From 60767d1215233461273d4d16df8ff52cf15b4010 Mon Sep 17 00:00:00 2001 From: sabetts Date: Thu, 7 Sep 2000 16:49:23 +0000 Subject: [PATCH] restructured tree, added automake and autoconf to the build process. --- AUTHORS | 6 + ChangeLog | 0 INSTALL | 182 +++++++++++++++++ Makefile | 358 ++++++++++++++++++++++++++++++++-- Makefile.am | 2 + NEWS | 3 + configure.in | 35 ++++ doc/.cvsignore | 4 + doc/Makefile.am | 1 + doc/ratpoison.info | 134 +++++++++++++ doc/ratpoison.texi | 171 ++++++++++++++++ src/.cvsignore | 8 + src/Makefile.am | 5 + src/bar.c | 141 ++++++++++++++ src/bar.h | 29 +++ src/conf.h | 44 +++++ src/data.h | 78 ++++++++ src/events.c | 473 +++++++++++++++++++++++++++++++++++++++++++++ src/events.h | 29 +++ src/input.c | 75 +++++++ src/input.h | 1 + src/list.c | 271 ++++++++++++++++++++++++++ src/list.h | 35 ++++ src/main.c | 261 +++++++++++++++++++++++++ src/manage.c | 175 +++++++++++++++++ src/manage.h | 30 +++ src/number.c | 130 +++++++++++++ src/number.h | 3 + src/ratpoison.h | 40 ++++ 29 files changed, 2704 insertions(+), 20 deletions(-) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 configure.in create mode 100644 doc/.cvsignore create mode 100644 doc/Makefile.am create mode 100644 doc/ratpoison.info create mode 100644 doc/ratpoison.texi create mode 100644 src/.cvsignore create mode 100644 src/Makefile.am create mode 100644 src/bar.c create mode 100644 src/bar.h create mode 100644 src/conf.h create mode 100644 src/data.h create mode 100644 src/events.c create mode 100644 src/events.h create mode 100644 src/input.c create mode 100644 src/input.h create mode 100644 src/list.c create mode 100644 src/list.h create mode 100644 src/main.c create mode 100644 src/manage.c create mode 100644 src/manage.h create mode 100644 src/number.c create mode 100644 src/number.h create mode 100644 src/ratpoison.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b2ae343 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,6 @@ +Shawn Betts (sabetts@sfu.ca) + +Shawn is the original author and current maintainer for +ratpoison. Sickened by the rat and the trend in window managers, he +sat down one evening and pulled an all-nighter writing the first +version of ratpoison. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile b/Makefile index 0ff3854..8512102 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,349 @@ -# Where to install the ratpoison executable -INSTALL_DIR=/usr/local/bin +# Generated automatically from Makefile.in by configure. +# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. -# Spew lots of debug messages -DEBUG = -DDEBUG +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +SHELL = /bin/sh + +srcdir = . +top_srcdir = . +prefix = /usr/local +exec_prefix = ${prefix} + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +libexecdir = ${exec_prefix}/libexec +datadir = ${prefix}/share +sysconfdir = ${prefix}/etc +sharedstatedir = ${prefix}/com +localstatedir = ${prefix}/var +libdir = ${exec_prefix}/lib +infodir = ${prefix}/info +mandir = ${prefix}/man +includedir = ${prefix}/include +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/ratpoison +pkglibdir = $(libdir)/ratpoison +pkgincludedir = $(includedir)/ratpoison + +top_builddir = . + +ACLOCAL = aclocal +AUTOCONF = autoconf +AUTOMAKE = automake +AUTOHEADER = autoheader + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} +transform = s,x,x, + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : CC = gcc -LIBS = -lX11 -LDFLAGS = -L/usr/X11R6/lib -CFLAGS = -g -Wall -I/usr/X11R6/include +MAKEINFO = makeinfo +PACKAGE = ratpoison +VERSION = 0.0.3 + +SUBDIRS = doc src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ./src/config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ +Makefile.in NEWS aclocal.m4 configure configure.in install-sh missing \ +mkinstalldirs src/config.h.in src/stamp-h.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +src/config.h: src/stamp-h + @if test ! -f $@; then \ + rm -f src/stamp-h; \ + $(MAKE) src/stamp-h; \ + else :; fi +src/stamp-h: $(srcdir)/src/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=src/config.h \ + $(SHELL) ./config.status + @echo timestamp > src/stamp-h 2> /dev/null +$(srcdir)/src/config.h.in: $(srcdir)/src/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/src/stamp-h.in; \ + $(MAKE) $(srcdir)/src/stamp-h.in; \ + else :; fi +$(srcdir)/src/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/src/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f src/config.h + +maintainer-clean-hdr: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + + + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-tags clean-generic mostlyclean-am + +clean: clean-recursive -SRC = main.o events.o manage.o list.o bar.o number.o input.o -HEADERS = bar.h conf.h data.h events.h list.h manage.h ratpoison.h number.h input.h +distclean-am: distclean-hdr distclean-tags distclean-generic clean-am -all: ratpoison ratpoison.info +distclean: distclean-recursive + -rm -f config.status -ratpoison: $(SRC) - gcc $(SRC) -o $@ $(CFLAGS) $(LDFLAGS) $(LIBS) +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." -ratpoison.info : ratpoison.texi - makeinfo ratpoison.texi +maintainer-clean: maintainer-clean-recursive + -rm -f config.status -install: ratpoison - cp ratpoison $(INSTALL_DIR) +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean -%.o : %.c $(HEADERS) - $(CC) -c $(CFLAGS) $(DEBUG) $< -o $@ -clean : - rm -f *.o ratpoison ratpoison.info +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..1c85a9d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = doc src diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..9585897 --- /dev/null +++ b/NEWS @@ -0,0 +1,3 @@ +* Features + +* Bugs diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..1e08bbe --- /dev/null +++ b/configure.in @@ -0,0 +1,35 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(src/main.c) +AM_INIT_AUTOMAKE(ratpoison, 0.0.3) + +AM_CONFIG_HEADER(src/config.h) + +dnl Checks for programs. +CFLAGS="$CFLAGS -Wall" +AC_PROG_CC + +dnl Check for the X libs +AC_PATH_X +AC_PATH_XTRA + +if test "x$no_x" = "xyes"; then + AC_MSG_ERROR([*** Can't find X11 headers and libs]) +fi + +LDFLAGS="$LDFLAGS $X_LDFLAGS $X_LIBS $X_EXTRA_LIBS" +CFLAGS="$CFLAGS $X_CFLAGS" + +AC_CHECK_LIB(X11, XOpenDisplay,, + AC_MSG_ERROR([*** Can't find libX11])) + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(unistd.h) + +dnl Checks for typedefs, structures, and compiler characteristics. + +dnl Checks for library functions. +AC_TYPE_SIGNAL + +AC_OUTPUT(Makefile doc/Makefile src/Makefile) diff --git a/doc/.cvsignore b/doc/.cvsignore new file mode 100644 index 0000000..6c49f9d --- /dev/null +++ b/doc/.cvsignore @@ -0,0 +1,4 @@ +ratpoison.info +Makefile.in +Makefile +texinfo.tex diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..96a2f8b --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1 @@ +info_TEXINFOS = ratpoison.texi diff --git a/doc/ratpoison.info b/doc/ratpoison.info new file mode 100644 index 0000000..13e9059 --- /dev/null +++ b/doc/ratpoison.info @@ -0,0 +1,134 @@ +This is ratpoison.info, produced by makeinfo version 4.0 from +ratpoison.texi. + +START-INFO-DIR-ENTRY +* ratpoison: (ratpoison). A rat-free Window Manager. +END-INFO-DIR-ENTRY + + This is the ratpoison user manual. + + Copyright (C) 2000 Shawn Betts + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided also +that the sections entitled "Copying" and "GNU General Public License" +are included exactly as in the original, and provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Free Software Foundation. + + This document explains how to use ratpoison. + + +File: ratpoison.info, Node: Top, Next: About, Prev: (dir), Up: (dir) + +* Menu: + +* About:: What is ratpoison? +* Contacting:: How do I contact the ratpoison developers? +* Using ratpoison:: Key commands and functionality + + +File: ratpoison.info, Node: About, Next: Contacting, Prev: Top, Up: Top + +About +***** + + ratpoison is a simple Window Manager with no fat library +dependencies, no fancy graphics, no window decorations, and no flashy +wank. It is largely modelled after GNU Screen which has done wonders in +virtual terminal market. + + All interaction with the window manager is done through keystrokes. +ratpoison has a prefix map to minimize the key clobbering that cripples +EMACS and other quality pieces of software. + + You'll also be pleased to hear that there is NO ratpoison.conf to +configure. If you want to configure ratpoison, edit the source. + + ratpoison was written by Shawn Betts +(). + + +File: ratpoison.info, Node: Contacting, Next: Using ratpoison, Prev: About, Up: Top + +Contacting +********** + + ratpoison is hosted on . To see the latest +developments in ratpoison go to + or visit the ratpoison +webpage at . + + There is also a ratpoison mailing list: +. For details on subscribing and +for the list archives go to the ratpoison sourceforge.net project. + + +File: ratpoison.info, Node: Using ratpoison, Prev: Contacting, Up: Top + +Using ratpoison +*************** + + ratpoison is a very simple window manager. Each window is maximized +and has no border decorations. Here is a list of commands and what they +do: + +`C-t C-c' + This opens a new XTerm. + +`C-t C-e' + This opens a new EMACS session. You will probably only need to do + this once. + +`C-t C-w' + This displays the Program Bar which displays the windows you + currently have running. The number before each window name is used + to jump to that window. You can to this by typing `C-t C-' + where `' is the number of the window. Note that only windows + with numbers from 0 to 9 can be referenced. + + After 5 seconds the Program Bar disappears. + +`C-t C-p' + This jumps you to the previous window in the window list. + +`C-t C-n' + This jumps you to the next window in the window list. + +`C-t C-' + This jumps you to window where is the window number as + shown in the Program Bar. + +`C-t C-t' + This toggles between the current window and the last window. + +`C-t t' + Sometimes you need to send a C-t to the current window. This + keystroke does just that. + +`C-t k' + This deletes the current window. + +`C-t K' + This destroys the current window. Normally you should only need to + use `C-t k', but just incase you need to rip the heart out of a + misbehaving window this command should do the trick. + + + +Tag Table: +Node: Top1119 +Node: About1394 +Node: Contacting2112 +Node: Using ratpoison2623 + +End Tag Table diff --git a/doc/ratpoison.texi b/doc/ratpoison.texi new file mode 100644 index 0000000..2cfe31a --- /dev/null +++ b/doc/ratpoison.texi @@ -0,0 +1,171 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename ratpoison.info +@settitle ratpoison manual +@setchapternewpage odd +@c %**end of header + +@ifinfo +@format +START-INFO-DIR-ENTRY +* ratpoison: (ratpoison). A rat-free Window Manager. +END-INFO-DIR-ENTRY +@end format + +@ifinfo +This is the ratpoison user manual. + +Copyright @copyright{} 2000 Shawn Betts + +Permission is granted to make and distribute verbatim +copies of this manual provided the copyright notice and +this permission notice are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX +and print the results, provided the printed document +carries a copying permission notice identical to this +one except for the removal of this paragraph (this +paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified +versions of this manual under the conditions for +verbatim copying, provided also that the sections +entitled ``Copying'' and ``GNU General Public License'' +are included exactly as in the original, and provided +that the entire resulting derived work is distributed +under the terms of a permission notice identical to this +one. + +Permission is granted to copy and distribute +translations of this manual into another language, +under the above conditions for modified versions, +except that this permission notice may be stated in a +translation approved by the Free Software Foundation. +@end ifinfo + +@titlepage +@sp 10 +@titlefont{Ratpoison} +@author Shawn Betts + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2000 Shawn Betts + +Permission is granted to make and distribute verbatim +copies of this manual provided the copyright notice and +this permission notice are preserved on all copies. + +Permission is granted to copy and distribute modified +versions of this manual under the conditions for +verbatim copying, provided also that the sections +entitled ``Copying'' and ``GNU General Public License'' +are included exactly as in the original, and provided +that the entire resulting derived work is distributed +under the terms of a permission notice identical to this +one. + +Permission is granted to copy and distribute +translations of this manual into another language, +under the above conditions for modified versions, +except that this permission notice may be stated in a +translation approved by the Free Software Foundation. +@end titlepage + +@end ifinfo + +@ifinfo +This document explains how to use ratpoison. +@end ifinfo + +@node Top, About, (dir), (dir) + +@menu +* About:: What is ratpoison? +* Contacting:: How do I contact the ratpoison developers? +* Using ratpoison:: Key commands and functionality +@end menu + +@node About, Contacting, Top, Top +@chapter About + +ratpoison is a simple Window Manager with no fat library dependencies, +no fancy graphics, no window decorations, and no flashy wank. It is +largely modelled after GNU Screen which has done wonders in virtual +terminal market. + +All interaction with the window manager is done through +keystrokes. ratpoison has a prefix map to minimize the key clobbering +that cripples EMACS and other quality pieces of software. + +You'll also be pleased to hear that there is NO ratpoison.conf to +configure. If you want to configure ratpoison, edit the source. + +ratpoison was written by Shawn Betts (@email{sabetts@@users.sourceforge.net}). + +@node Contacting, Using ratpoison, About, Top +@chapter Contacting +ratpoison is hosted on @url{sourceforge.net}. To see the latest +developments in ratpoison go to +@url{http://www.sourceforge.net/projects/ratpoison} or visit the +ratpoison webpage at @url{http://ratpoison.sourceforge.net}. + +There is also a ratpoison mailing list: +@email{ratpoison-devel@@lists.sourceforge.net}. For details on subscribing +and for the list archives go to the ratpoison sourceforge.net project. + +@node Using ratpoison, , Contacting, Top +@chapter Using ratpoison + +ratpoison is a very simple window manager. Each window is maximized and +has no border decorations. Here is a list of commands and what they do: + +@table @kbd + +@item C-t C-c +This opens a new XTerm. + +@item C-t C-e +This opens a new EMACS session. You will probably only need to do this +once. + +@item C-t C-w +This displays the Program Bar which displays the windows you currently +have running. The number before each window name is used to jump to that +window. You can to this by typing @kbd{C-t C-} where @kbd{} is the +number of the window. Note that only windows with numbers from 0 to 9 +can be referenced. + +After 5 seconds the Program Bar disappears. + +@item C-t C-p +This jumps you to the previous window in the window list. + +@item C-t C-n +This jumps you to the next window in the window list. + +@item C-t C- +This jumps you to window where is the window number as shown in +the Program Bar. + +@item C-t C-t +This toggles between the current window and the last window. + +@item C-t t +Sometimes you need to send a C-t to the current window. This keystroke +does just that. + +@item C-t k +This deletes the current window. + +@item C-t K +This destroys the current window. Normally you should only need to use +@kbd{C-t k}, but just incase you need to rip the heart out of a +misbehaving window this command should do the trick. + +@end table + +@bye + diff --git a/src/.cvsignore b/src/.cvsignore new file mode 100644 index 0000000..29c83c0 --- /dev/null +++ b/src/.cvsignore @@ -0,0 +1,8 @@ +Makefile.in +Makefile +*.in +ratpoison +config.h +stamp-h +stamp-h.in +.deps diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..d3af0be --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,5 @@ +bin_PROGRAMS = ratpoison + +ratpoison_SOURCES = bar.c bar.h conf.h data.h events.c events.h \ +input.c input.h list.c list.h main.c manage.c manage.h number.c \ +number.h ratpoison.h diff --git a/src/bar.c b/src/bar.c new file mode 100644 index 0000000..d06dcc8 --- /dev/null +++ b/src/bar.c @@ -0,0 +1,141 @@ +/* Functionality for a bar across the bottom of the screen listing the + * windows currently managed. + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ratpoison.h" + +int +hide_bar (screen_info *s) +{ + if (s->bar_is_raised) + { + s->bar_is_raised = 0; + XUnmapWindow (dpy, s->bar_window); + return 1; + } + + return 0; +} + +int +show_bar (screen_info *s) +{ + if (!s->bar_is_raised) + { + s->bar_is_raised = 1; + XMapWindow (dpy, s->bar_window); + update_window_names (s); + + /* Set an alarm to auto-hide the bar BAR_TIMEOUT seconds later */ + alarm (BAR_TIMEOUT); + return 1; + } + + return 0; +} + +/* Toggle the display of the program bar */ +void +toggle_bar (screen_info *s) +{ + if (!hide_bar (s)) show_bar (s); +} + +static int +calc_bar_width (XFontStruct *font) +{ + char str[100]; /* window names are capped at 99 chars */ + int size = 1; + rp_window *cur; + + for (cur = rp_window_head; cur; cur = cur->next) + { + if (cur->state == STATE_UNMAPPED) continue; + + sprintf (str, "%d-%s", cur->number, cur->name); + size += 10 + XTextWidth (font, str, strlen (str)); + } + + return size; +} + +int +bar_x (screen_info *s, int width) +{ + if (BAR_LOCATION >= 2) return s->root_attr.width - width; + else return 0; +} + +int +bar_y (screen_info *s) +{ + if (BAR_LOCATION % 2) return 0; + else return s->root_attr.height - (FONT_HEIGHT (s->font) + BAR_PADDING * 2) - 2; +} + +void +update_window_names (screen_info *s) +{ + char str[100]; /* window names are capped at 99 chars */ + int width = calc_bar_width (s->font); + rp_window *cur; + int cur_x = 5; + + if (!s->bar_is_raised) return; + + XMoveResizeWindow (dpy, s->bar_window, + bar_x (s, width), bar_y (s), + width, + (FONT_HEIGHT (s->font) + BAR_PADDING * 2)); + XClearWindow (dpy, s->bar_window); + XRaiseWindow (dpy, s->bar_window); + + if (rp_window_head == NULL) return; + + /* Draw them in reverse order they were added in, so the oldest + windows appear on the left and the newest on the right end of the + program bar. */ + for (cur = rp_window_head; cur; cur = cur->next) + { + if (cur->state == STATE_UNMAPPED) continue; + + sprintf (str, "%d-%s", cur->number, cur->name); + if ( rp_current_window == cur) + { + XDrawString (dpy, s->bar_window, s->bold_gc, cur_x, + BAR_PADDING + s->font->max_bounds.ascent, str, strlen (str)); + } + else + { + XDrawString (dpy, s->bar_window, s->normal_gc, cur_x, + BAR_PADDING + s->font->max_bounds.ascent, str, strlen (str)); + } + + cur_x += 10 + XTextWidth (s->font, str, strlen (str)); + } +} diff --git a/src/bar.h b/src/bar.h new file mode 100644 index 0000000..6083762 --- /dev/null +++ b/src/bar.h @@ -0,0 +1,29 @@ +/* functions for managing the program bar + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#ifndef _BAR_H +#define _BAR_H + +void update_window_names (screen_info *s); +void toggle_bar (screen_info *s); +int show_bar (screen_info *s); +int hide_bar (screen_info *s); +int bar_y (screen_info *s); +int bar_x (screen_info *s, int width); +#endif _BAR_H diff --git a/src/conf.h b/src/conf.h new file mode 100644 index 0000000..8efee2e --- /dev/null +++ b/src/conf.h @@ -0,0 +1,44 @@ +/* Config file for ratpoison. Edit these values and recompile. + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#define KEY_PREFIX 't' +#define MODIFIER_PREFIX ControlMask + +#define KEY_XTERM 'c' +#define KEY_EMACS 'e' +#define KEY_PREVWINDOW 'p' +#define KEY_NEXTWINDOW 'n' +#define KEY_LASTWINDOW 't' /* key to toggle between the current window and the last visitted one */ +#define KEY_TOGGLEBAR 'w' /* key to toggle the display of the program bar */ +#define KEY_DELETE 'k' /* delete a window SHIFT+key will Destroy the window */ +#define KEY_WINBYNAME '\'' /* key to jump to a window by name */ +#define KEY_RENAME 'a' /* key to rename a window. */ + +#define TERM_PROG "xterm" /* command to boot an x term */ +#define EMACS_PROG "emacs" /* command to boot emacs */ + +#define BAR_FG_COLOR "Gray60" +#define BAR_BG_COLOR "Lightgreen" +#define BAR_BOLD_COLOR "Black" /* To indicate the current window */ + +#define FONT_NAME "fixed" /* The font you wish to use */ +#define BAR_PADDING 3 /* The amount of padding on the top and bottom of the program bar */ +#define BAR_LOCATION 3 /* 0=bottom-left 1=top-left 2=bottom-right 3=top-right */ +#define BAR_TIMEOUT 5 /* Number of seconds before the progam bar autohides 0=don't autohide */ + diff --git a/src/data.h b/src/data.h new file mode 100644 index 0000000..5623a58 --- /dev/null +++ b/src/data.h @@ -0,0 +1,78 @@ +/* our datatypes and global variables + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#ifndef _DATA_H +#define _DATA_H + +#include +#include + +#define FONT_HEIGHT(f) ((f)->max_bounds.ascent + (f)->max_bounds.descent) + +#define STATE_UNMAPPED 0 +#define STATE_MAPPED 1 + + +typedef struct rp_window rp_window; +typedef struct screen_info screen_info; + +struct rp_window +{ + screen_info *scr; + Window w; + int number; + char *name; + int state; + int last_access; + int named; + rp_window *next, *prev; +}; + +struct screen_info +{ + GC normal_gc; + GC bold_gc; + XFontStruct *font; /* The font we want to use. */ + XWindowAttributes root_attr; + Window root, bar_window, key_window, input_window; + int bar_is_raised; + int screen_num; /* Our screen number as dictated my X */ + Colormap def_cmap; +}; + +extern rp_window *rp_window_head, *rp_window_tail; +extern rp_window *rp_current_window; +extern screen_info *screens; +extern int num_screens; + +extern Display *dpy; +extern Atom rp_restart; + +extern Atom wm_state; +extern Atom wm_change_state; +extern Atom wm_protocols; +extern Atom wm_delete; +extern Atom wm_take_focus; +extern Atom wm_colormaps; + +/* Set to 1 to indicate that the WM should exit at it's earliest + convenience. */ +extern int exit_signal; + +#endif /* _DATA_H */ diff --git a/src/events.c b/src/events.c new file mode 100644 index 0000000..a835eb3 --- /dev/null +++ b/src/events.c @@ -0,0 +1,473 @@ +/* Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ratpoison.h" + +extern Display *dpy; + +void +spawn(char *prog) +{ + /* + * ugly dance to avoid leaving zombies. Could use SIGCHLD, + * but it's not very portable. + */ + if (fork() == 0) { + if (fork() == 0) { + putenv(DisplayString(dpy)); + execlp(prog, prog, 0); + fprintf(stderr, "ratpoison: exec %s ", prog); + perror(" failed"); + exit(EXIT_FAILURE); + } + exit(0); + } + wait((int *) 0); +#ifdef DEBUG + printf ("spawned %s\n", prog); +#endif +} + +void +new_window (XCreateWindowEvent *e) +{ + rp_window *win; + screen_info *s; + + if (e->override_redirect) return; + + s = find_screen (e->parent); + win = find_window (e->window); + + if (s && !win && e->window != s->key_window && e->window != s->bar_window + && e->window != s->input_window) + { + win = add_to_window_list (s, e->window); + win->state = STATE_UNMAPPED; + } +} + +void +unmap_notify (XEvent *ev) +{ + screen_info *s; + rp_window *win; + + s = find_screen (ev->xunmap.event); + win = find_window (ev->xunmap.window); + + if (s && win) + { + /* Give back the window number. the window will get another one, + if it in remapped. */ + return_window_number (win->number); + win->number = -1; + win->state = STATE_UNMAPPED; + update_window_names (s); + } +} + +void +map_request (XEvent *ev) +{ + screen_info *s; + rp_window *win; + + s = find_screen (ev->xmap.event); + win = find_window (ev->xmap.window); + + if (s && win) + { + switch (win->state) + { + case STATE_UNMAPPED: + manage (win, s); + case STATE_MAPPED: + XMapRaised (dpy, win->w); + rp_current_window = win; + set_active_window (rp_current_window); + } + } + else + { + printf ("Not managed.\n"); + XMapWindow (dpy, ev->xmap.window); + } +} + +int +more_destroy_events () +{ + XEvent ev; + + if (XCheckTypedEvent (dpy, DestroyNotify, &ev)) + { + XPutBackEvent (dpy, &ev); + return 1; + } + return 0; +} + +void +destroy_window (XDestroyWindowEvent *ev) +{ + /* if there are multiple destroy events queued, and a mapped window + is deleted then switch_window_pending is set to 1 and the window + switch is done after all destroy events have been done. */ + static int switch_window_pending = 0; + int last_destroy_event; + rp_window *win; + + win = find_window (ev->window); + + last_destroy_event = !more_destroy_events(); + if (win) + { + /* Goto the last accessed window. */ + if (win == rp_current_window) + { + printf ("Destroying current window.\n"); + + /* tell ratpoison to switch to the last window when all the + destroy events have been delt with. */ + switch_window_pending = 1; + unmanage (win); + } + else + { + printf ("Destroying some other window.\n"); + unmanage (win); + } + } + + if (last_destroy_event && switch_window_pending) + { + last_window (); + switch_window_pending = 0; + } +} + +void +configure_request (XConfigureRequestEvent *e) +{ + XConfigureEvent ce; + rp_window *win; + + win = find_window (e->window); + + if (win) + { + ce.type = ConfigureNotify; + ce.event = e->window; + ce.window = e->window; + ce.x = 0; + ce.y = 0; + ce.width = win->scr->root_attr.width; + ce.height = win->scr->root_attr.height; + ce.border_width = 0; + ce.above = None; + ce.override_redirect = 0; + + if (e->value_mask & CWStackMode && win->state == STATE_MAPPED) + { + if (e->detail == Above) + { + rp_current_window = win; + set_active_window (rp_current_window); + } + else if (e->detail == Below && win == rp_current_window) + { + last_window (); + } + } + + XSendEvent(dpy, win->w, False, StructureNotifyMask, (XEvent*)&ce); + } +} + +void +delete_window () +{ + XEvent ev; + int status; + + if (rp_current_window == NULL) return; + + ev.xclient.type = ClientMessage; + ev.xclient.window = rp_current_window->w; + ev.xclient.message_type = wm_protocols; + ev.xclient.format = 32; + ev.xclient.data.l[0] = wm_delete; + ev.xclient.data.l[1] = CurrentTime; + + status = XSendEvent(dpy, rp_current_window->w, False, 0, &ev); + if (status == 0) fprintf(stderr, "ratpoison: XSendEvent failed\n"); +} + +void +kill_window () +{ + if (rp_current_window == NULL) return; + + XKillClient(dpy, rp_current_window->w); +} + +static void +client_msg (XClientMessageEvent *ev) +{ + printf ("Recieved client message.\n"); +} + +static void +goto_win_by_name (screen_info *s) +{ + char winname[100]; + + get_input (s, "Window: ", winname, 100); + printf ("user entered: %s\n", winname); + + goto_window_name (winname); +} + +static void +handle_key (screen_info *s) +{ + int revert; + Window fwin; + XEvent ev; + int keysym; + +#ifdef DEBUG + printf ("handling key.\n"); +#endif + + XGetInputFocus (dpy, &fwin, &revert); + XSetInputFocus (dpy, s->key_window, RevertToPointerRoot, CurrentTime); + XMaskEvent (dpy, KeyPressMask, &ev); + XSetInputFocus (dpy, fwin, revert, CurrentTime); + + if (XLookupKeysym((XKeyEvent *) &ev, 0) == KEY_PREFIX && !ev.xkey.state) + { + /* Generate the prefix keystroke for the app */ + ev.xkey.window = fwin; + ev.xkey.state = MODIFIER_PREFIX; + XSendEvent (dpy, fwin, False, KeyPressMask, &ev); + XSync (dpy, False); + return; + } + + keysym = XLookupKeysym((XKeyEvent *) &ev, 0); + + if (keysym == KEY_TOGGLEBAR) + { + toggle_bar (s); + return; + } + + /* All functions tested for after this point hide the program bar. */ + hide_bar (s); + + if (keysym >= '0' && keysym <= '9') + { + goto_window_number (XLookupKeysym((XKeyEvent *) &ev, 0) - '0'); + hide_bar (s); + return; + } + + switch (keysym) + { + case KEY_XTERM: + spawn (TERM_PROG); + break; + case KEY_EMACS: + spawn (EMACS_PROG); + break; + case KEY_PREVWINDOW: + prev_window (); + break; + case KEY_NEXTWINDOW: + next_window (); + break; + case KEY_LASTWINDOW: + last_window (); + break; + case KEY_WINBYNAME: + goto_win_by_name (s); + break; + case KEY_RENAME: + rename_current_window (); + break; + case KEY_DELETE: + if (ev.xkey.state & ShiftMask) kill_window (); + else delete_window (); + break; + default: + fprintf (stderr, "Unknown key command '%c'\n", (char)keysym); + break; + } +} + +void +key_press (XEvent *ev) +{ + screen_info *s; + unsigned int modifier = ev->xkey.state; + int ks = XLookupKeysym((XKeyEvent *) ev, 0); + + s = find_screen (ev->xkey.root); + + if (s && ks == KEY_PREFIX && (modifier & MODIFIER_PREFIX)) + { + handle_key (s); + } +} + +void +property_notify (XEvent *ev) +{ + rp_window *win; + + printf ("atom: %ld\n", ev->xproperty.atom); + + win = find_window (ev->xproperty.window); + + if (win) + { + if (ev->xproperty.atom == XA_WM_NAME) + { + printf ("updating window name\n"); + if (update_window_name (win)) + { + update_window_names (win->scr); + } + } + } +} + +/* Given an event, call the correct function to handle it. */ +void +delegate_event (XEvent *ev) +{ + switch (ev->type) + { + case ConfigureRequest: + printf ("ConfigureRequest\n"); + configure_request (&ev->xconfigurerequest); + break; + case CirculateRequest: + printf ("CirculateRequest\n"); + break; + case CreateNotify: + printf ("CreateNotify\n"); + new_window (&ev->xcreatewindow); + break; + case DestroyNotify: + printf ("DestroyNotify\n"); + destroy_window (&ev->xdestroywindow); + break; + case ClientMessage: + client_msg (&ev->xclient); + printf ("ClientMessage\n"); + break; + case ColormapNotify: + printf ("ColormapNotify\n"); + break; + case PropertyNotify: + printf ("PropertyNotify\n"); + property_notify (ev); + break; + case SelectionClear: + printf ("SelectionClear\n"); + break; + case SelectionNotify: + printf ("SelectionNotify\n"); + break; + case SelectionRequest: + printf ("SelectionRequest\n"); + break; + case EnterNotify: + printf ("EnterNotify\n"); + break; + case ReparentNotify: + printf ("ReparentNotify\n"); + break; + case FocusIn: + printf ("FocusIn\n"); + break; + + case MapRequest: + printf ("MapRequest\n"); + map_request (ev); + break; + + case KeyPress: + printf ("KeyPress\n"); + key_press (ev); + break; + + case UnmapNotify: + printf ("UnmapNotify\n"); + unmap_notify (ev); + break; + + case MotionNotify: + printf ("MotionNotify\n"); + break; + case Expose: + printf ("Expose\n"); + break; + case FocusOut: + printf ("FocusOut\n"); + break; + case ConfigureNotify: + printf ("ConfigureNotify\n"); + break; + case MapNotify: + printf ("MapNotify\n"); + break; + case MappingNotify: + printf ("MappingNotify\n"); + break; + default: + printf ("Unhandled event %d\n", ev->type); + } +} + +void +handle_events () +{ + XEvent ev; + + for (;;) + { + XNextEvent (dpy, &ev); + delegate_event (&ev); + } +} + + diff --git a/src/events.h b/src/events.h new file mode 100644 index 0000000..8751e68 --- /dev/null +++ b/src/events.h @@ -0,0 +1,29 @@ +/* Function prototypes + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#ifndef _EVENTS_H +#define _EVENTS_H + +void handle_events (); +void delegate_event (XEvent *ev); +void key_press (XEvent *ev); +void map_request (XEvent *ev); +void unmap_notify (XEvent *ev); + +#endif _EVENTS_H diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..ad8f093 --- /dev/null +++ b/src/input.c @@ -0,0 +1,75 @@ +/* for reading kdb input from the user. Currently only used to read in + the name of a window to jump to. */ + +#include +#include +#include + +#include "ratpoison.h" + + +static int +read_key () +{ + XEvent ev; + + XMaskEvent (dpy, KeyPressMask, &ev); + return XLookupKeysym ((XKeyEvent *)&ev, 0); +} + +/* pass in a pointer a string and how much room we have, and fill it + in with text from the user. */ +void +get_input (screen_info *s, char *prompt, char *str, int len) +{ + int cur_len; /* Current length of the string. */ + int ch; + int revert; + Window fwin; + int prompt_width = XTextWidth (s->font, prompt, strlen (prompt)); + int width = 100 + prompt_width; + + /* We don't want to draw overtop of the program bar. */ + hide_bar (s); + + XMapWindow (dpy, s->input_window); + XMoveResizeWindow (dpy, s->input_window, + bar_x (s, width), bar_y (s), width, (FONT_HEIGHT (s->font) + BAR_PADDING * 2)); + XClearWindow (dpy, s->input_window); + XRaiseWindow (dpy, s->input_window); + + /* draw the window prompt. */ + XDrawString (dpy, s->input_window, s->bold_gc, 5, + BAR_PADDING + s->font->max_bounds.ascent, prompt, strlen (prompt)); + + XGetInputFocus (dpy, &fwin, &revert); + XSetInputFocus (dpy, s->input_window, RevertToPointerRoot, CurrentTime); + + cur_len = 0; + while ((ch = read_key ()) != XK_Return) + { + printf ("key %d\n", ch); + if (ch == XK_BackSpace) + { + if (cur_len > 0) cur_len--; + XClearWindow (dpy, s->input_window); + XDrawString (dpy, s->input_window, s->bold_gc, 5, + BAR_PADDING + s->font->max_bounds.ascent, prompt, strlen (prompt)); + XDrawString (dpy, s->input_window, s->bold_gc, 5 + prompt_width, + BAR_PADDING + s->font->max_bounds.ascent, str, cur_len); + } + else if (ch >= ' ') + { + str[cur_len] = ch; + if (cur_len < len - 1) cur_len++; + + XDrawString (dpy, s->input_window, s->bold_gc, 5 + prompt_width, + BAR_PADDING + s->font->max_bounds.ascent, str, cur_len); + } + } + + str[cur_len] = 0; + XSetInputFocus (dpy, fwin, RevertToPointerRoot, CurrentTime); + XUnmapWindow (dpy, s->input_window); +} + diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..9d49bbf --- /dev/null +++ b/src/input.h @@ -0,0 +1 @@ +void get_input (screen_info *s, char *prompt, char *str, int len); diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..ee04b34 --- /dev/null +++ b/src/list.c @@ -0,0 +1,271 @@ +/* functions for handling the window list + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include + +#include "ratpoison.h" + +rp_window *rp_window_head, *rp_window_tail; +rp_window *rp_current_window; + +rp_window * +add_to_window_list (screen_info *s, Window w) +{ + rp_window *new_window; + + new_window = malloc (sizeof (rp_window)); + if (new_window == NULL) + { + fprintf (stderr, "list.c:add_to_window_list():Out of memory!\n"); + exit (EXIT_FAILURE); + } + new_window->w = w; + new_window->scr = s; + new_window->last_access = 0; + new_window->prev = NULL; + new_window->state = STATE_UNMAPPED; + new_window->number = -1; + new_window->named = 0; + + if ((new_window->name = malloc (strlen ("Unnamed") + 1)) == NULL) + { + fprintf (stderr, "list.c:add_to_window_list():Out of memory.\n"); + exit (EXIT_FAILURE); + } + strcpy (new_window->name, "Unnamed"); + + if (rp_window_head == NULL) + { + /* The list is empty. */ + rp_window_head = new_window; + rp_window_tail = new_window; + new_window->next = NULL; + return new_window; + } + + /* Add the window to the head of the list. */ + new_window->next = rp_window_head; + rp_window_head->prev = new_window; + rp_window_head = new_window; + + return new_window; +} + +/* Check to see if the window is already in our list of managed windows. */ +rp_window * +find_window (Window w) +{ + rp_window *cur; + + for (cur = rp_window_head; cur; cur = cur->next) + if (cur->w == w) return cur; + + return NULL; +} + +void +remove_from_window_list (rp_window *w) +{ + if (rp_window_head == w) rp_window_head = w->next; + if (rp_window_tail == w) rp_window_tail = w->prev; + + if (w->prev != NULL) w->prev->next = w->next; + if (w->next != NULL) w->next->prev = w->prev; + + /* set rp_current_window to NULL, so a dangling pointer is not + left. */ + if (rp_current_window == w) rp_current_window = NULL; + + free (w); +#ifdef DEBUG + printf ("Removed window from list.\n"); +#endif +} + +void +set_current_window (rp_window *win) +{ + rp_current_window = win; +} + +void +init_window_list () +{ + rp_window_head = rp_window_tail = NULL; + rp_current_window = NULL; +} + +void +next_window () +{ + if (rp_current_window != NULL) + { + rp_current_window = rp_current_window->next; + if (rp_current_window == NULL) + { + rp_current_window = rp_window_head; + } + if (rp_current_window->state == STATE_UNMAPPED) next_window (); + set_active_window (rp_current_window); + } +} + +void +prev_window () +{ + if (rp_current_window != NULL) + { + set_current_window (rp_current_window->prev); + if (rp_current_window == NULL) + { + rp_current_window = rp_window_tail; + } + if (rp_current_window->state == STATE_UNMAPPED) prev_window (); + set_active_window (rp_current_window); + } +} + +rp_window * +find_window_by_number (int n) +{ + rp_window *cur; + + for (cur=rp_window_head; cur; cur=cur->next) + { + if (cur->state != STATE_MAPPED) continue; + + if (n == cur->number) return cur; + } + + return NULL; +} + +/* A case insensitive strncmp. */ +static int +str_comp (char *s1, char *s2, int len) +{ + int i; + + for (i=0; inext) + { + if (str_comp (name, cur->name, strlen (name))) return cur; + } + + return NULL; +} + +void +goto_window_name (char *name) +{ + rp_window *win; + + if ((win = find_window_by_name (name)) == NULL) + { + return; + } + + rp_current_window = win; + set_active_window (rp_current_window); +} + +void +goto_window_number (int n) +{ + rp_window *win; + + if ((win = find_window_by_number (n)) == NULL) + { + return; + } + + rp_current_window = win; + set_active_window (rp_current_window); +} + +rp_window * +find_last_accessed_window () +{ + int last_access = 0; + rp_window *cur, *most_recent; + + /* Find the first mapped window */ + for (most_recent = rp_window_head; most_recent; most_recent=most_recent->next) + { + if (most_recent->state == STATE_MAPPED) break; + } + + /* If there are no mapped windows, don't bother with the next part */ + if (most_recent == NULL) return NULL; + + for (cur=rp_window_head; cur; cur=cur->next) + { + if (cur->last_access >= last_access + && cur != rp_current_window + && cur->state == STATE_MAPPED) + { + most_recent = cur; + last_access = cur->last_access; + } + } + + return most_recent; +} + +void +last_window () +{ + rp_current_window = find_last_accessed_window (); + set_active_window (rp_current_window); +} + +void +set_active_window (rp_window *rp_w) +{ + static int counter = 1; /* increments every time this function + is called. This way we can track + which window was last accessed. */ + + if (rp_w == NULL) return; + + counter++; + rp_w->last_access = counter; + + if (rp_w->scr->bar_is_raised) update_window_names (rp_w->scr); + + XSetInputFocus (dpy, rp_w->w, + RevertToPointerRoot, CurrentTime); + XRaiseWindow (dpy, rp_w->w); + + /* Make sure the program bar is always on the top */ + update_window_names (rp_w->scr); +} diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..170c2e2 --- /dev/null +++ b/src/list.h @@ -0,0 +1,35 @@ +/* functions for managing the window list + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#ifndef _LIST_H +#define _LIST_H + +rp_window *add_to_window_list (screen_info *s, Window w); +void init_window_list (); +void remove_from_window_list (rp_window *w); +void next_window (); +void prev_window (); +void last_window (); +rp_window *find_window (Window w); +void maximize_current_window (); +void set_active_window (rp_window *rp_w); +void set_current_window (rp_window *win); +void goto_window_number (int n); +void goto_window_name (char *name); +#endif /* _LIST_H */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..313d7fc --- /dev/null +++ b/src/main.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ratpoison.h" + +static void init_screen (screen_info *s, int screen_num); + +Atom wm_state; +Atom wm_change_state; +Atom wm_protocols; +Atom wm_delete; +Atom wm_take_focus; +Atom wm_colormaps; + +Atom rp_restart; + +screen_info *screens; +int num_screens; +Display *dpy; +int exit_signal = 0; /* Set by the signal handler. if this + is set, quit. */ +static XFontStruct *font; + +char **myargv; + +void +sighandler () +{ + fprintf (stderr, "ratpoison: Agg! I've been SHOT!\n"); + clean_up (); + exit (EXIT_FAILURE); +} + +void +hup_handler () +{ + /* This doesn't seem to restart more than once for some reason...*/ + + fprintf (stderr, "ratpoison: Restarting with a fresh plate.\n"); + clean_up (); + execvp(myargv[0], myargv); +} + +void +alrm_handler () +{ + int i; + +#ifdef DEBUG + printf ("alarm recieved.\n"); +#endif + + /* FIXME: should only hide 1 bar, but we hide them all. */ + for (i=0; irequest_code == X_ChangeWindowAttributes && e->error_code == BadAccess) { + fprintf(stderr, "ratpoison: There can be only ONE.\n"); + exit(EXIT_FAILURE); + } + + XGetErrorText (d, e->error_code, error_msg, sizeof (error_msg)); + fprintf (stderr, "ratpoison: %s!\n", error_msg); + + return 0; + // exit (EXIT_FAILURE); +} + +int +main (int argc, char *argv[]) +{ + int i; + + myargv = argv; + + if (!(dpy = XOpenDisplay (NULL))) + { + fprintf (stderr, "Can't open display\n"); + return EXIT_FAILURE; + } + + /* Setup signal handlers. */ + XSetErrorHandler(handler); + if (signal (SIGALRM, alrm_handler) == SIG_IGN) signal (SIGALRM, SIG_IGN); + if (signal (SIGTERM, sighandler) == SIG_IGN) signal (SIGTERM, SIG_IGN); + if (signal (SIGINT, sighandler) == SIG_IGN) signal (SIGINT, SIG_IGN); + if (signal (SIGHUP, hup_handler) == SIG_IGN) + { + printf ("Ignoring HUP.\n"); + signal (SIGHUP, SIG_IGN); + } + + init_numbers (); + init_window_list (); + + font = XLoadQueryFont (dpy, FONT_NAME); + if (font == NULL) + { + fprintf (stderr, "ratpoison: Cannot load font %s.\n", FONT_NAME); + exit (EXIT_FAILURE); + } + + num_screens = ScreenCount (dpy); + if ((screens = (screen_info *)malloc (sizeof (screen_info) * num_screens)) == NULL) + { + fprintf (stderr, "ratpoison:main.c:Out of memory!\n"); + exit (EXIT_FAILURE); + } + + printf ("%d screens.\n", num_screens); + + /* Initialize the screens */ + for (i=0; iscreen_num = screen_num; + s->root = RootWindow (dpy, screen_num); + s->def_cmap = DefaultColormap (dpy, screen_num); + s->font = font; + XGetWindowAttributes (dpy, s->root, &s->root_attr); + + /* Get our program bar colors */ + if (!XAllocNamedColor (dpy, s->def_cmap, BAR_FG_COLOR, &fg_color, &junk)) + { + fprintf (stderr, "Unknown color '%s'\n", BAR_FG_COLOR); + } + + if (!XAllocNamedColor (dpy, s->def_cmap, BAR_BG_COLOR, &bg_color, &junk)) + { + fprintf (stderr, "Unknown color '%s'\n", BAR_BG_COLOR); + } + + if (!XAllocNamedColor (dpy, s->def_cmap, BAR_BOLD_COLOR, &bold_color, &junk)) + { + fprintf (stderr, "Unknown color '%s'\n", BAR_BOLD_COLOR); + } + + /* Setup the GC for drawing the font. */ + gv.foreground = fg_color.pixel; + gv.background = bg_color.pixel; + gv.function = GXcopy; + gv.line_width = 1; + gv.subwindow_mode = IncludeInferiors; + gv.font = font->fid; + s->normal_gc = XCreateGC(dpy, s->root, + GCForeground | GCBackground | GCFunction + | GCLineWidth | GCSubwindowMode | GCFont, + &gv); + gv.foreground = bold_color.pixel; + s->bold_gc = XCreateGC(dpy, s->root, + GCForeground | GCBackground | GCFunction + | GCLineWidth | GCSubwindowMode | GCFont, + &gv); + + XSelectInput(dpy, s->root, + PropertyChangeMask | ColormapChangeMask + | SubstructureRedirectMask | KeyPressMask + | SubstructureNotifyMask ); + XSync (dpy, 0); + + /* Create the program bar window. */ + s->bar_is_raised = 0; + s->bar_window = XCreateSimpleWindow (dpy, s->root, 0, 0, + 1, 1, 1, fg_color.pixel, bg_color.pixel); + XSelectInput (dpy, s->bar_window, StructureNotifyMask); + + /* Setup the window that will recieve all keystrokes once the prefix + key has been pressed. */ + s->key_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, 0, WhitePixel (dpy, 0), BlackPixel (dpy, 0)); + XSelectInput (dpy, s->key_window, KeyPressMask); + XMapWindow (dpy, s->key_window); + + /* Create the input window. */ + s->input_window = XCreateSimpleWindow (dpy, s->root, 0, 0, + 1, 1, 1, fg_color.pixel, bg_color.pixel); + XSelectInput (dpy, s->input_window, KeyPressMask); + scanwins (s); +} + +void +clean_up () +{ + XSetInputFocus (dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XCloseDisplay (dpy); +} + +/* Given a root window, return the screen_info struct */ +screen_info * +find_screen (Window w) +{ + int i; + + for (i=0; i +#include +#include +#include +#include + +#include +#include +#include + +#include "ratpoison.h" + +extern Atom wm_state; + +static void +grab_prefix_key (Window w) +{ + XGrabKey(dpy, XKeysymToKeycode (dpy, KEY_PREFIX ), MODIFIER_PREFIX, w, True, + GrabModeAsync, GrabModeAsync); +} + +/* Reget the WM_NAME property for the window and update its name. */ +int +update_window_name (rp_window *win) +{ + XTextProperty text; + char **name_list; + int list_len; + int i; + + /* Don't overwrite the window name if the user specified one. */ + if (win->named) return 0; + + if (!XGetWMName (dpy, win->w, &text)) + { + fprintf (stderr, "ratpoison:manage.c: I can't get the WMName.\n"); + return 0; + } + + if (!XTextPropertyToStringList (&text, &name_list, &list_len)) + { + fprintf (stderr, "ratpoison:manage.c:Error retrieving TextList.\n"); + return 0; + } + + for (i=0; i 0) + { + char *loc; + + free (win->name); + if ((win->name = malloc (strlen (name_list[0]) + 1)) == NULL) + { + fprintf (stderr, "manage.c:update_window_name():Out of memory!\n"); + exit (EXIT_FAILURE); + } + strcpy (win->name, name_list[0]); + + /* A bit of a hack. If there's a : in the string, crop the + string off there. This is mostly brought on by netscape's + disgusting tendency to put its current URL in the WMName!! + arg! */ + loc = strchr (win->name, ':'); + if (loc) loc[0] = '\0'; + } + + /* Its our responsibility to free this. */ + XFreeStringList (name_list); + + return 1; +} + +void +rename_current_window () +{ + char winname[100]; + + if (rp_current_window == NULL) return; + + get_input (rp_current_window->scr, "Name: ", winname, 100); + printf ("user entered: %s\n", winname); + + free (rp_current_window->name); + rp_current_window->name = malloc (sizeof (char) * strlen (winname) + 1); + if (rp_current_window->name == NULL) + { + fprintf (stderr, "ratpoison:rename_window(): Out of memory\n"); + exit (EXIT_FAILURE); + } + strcpy (rp_current_window->name, winname); + rp_current_window->named = 1; + + /* Update the program bar. */ + update_window_names (rp_current_window->scr); +} + +void +manage (rp_window *win, screen_info *s) +{ + if (!update_window_name (win)) return; + + /* We successfully got the name, which means we can start managing! */ + XMapWindow (dpy, win->w); + XMoveResizeWindow (dpy, win->w, 0, 0, s->root_attr.width, s->root_attr.height); + XSelectInput (dpy, win->w, PropertyChangeMask); + XAddToSaveSet(dpy, win->w); + grab_prefix_key (win->w); + + win->state = STATE_MAPPED; + win->number = get_unique_window_number (); + +#ifdef DEBUG + printf ("window '%s' managed.\n", win->name); +#endif +} + +void +unmanage (rp_window *w) +{ + return_window_number (w->number); + remove_from_window_list (w); +} + +/* When starting up scan existing windows and start managing them. */ +void +scanwins(screen_info *s) +{ + rp_window *win; + XWindowAttributes attr; + unsigned int i, nwins; + Window dw1, dw2, *wins; + + XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins); +#ifdef DEBUG + printf ("windows: %d\n", nwins); +#endif + + for (i = 0; i < nwins; i++) + { + XGetWindowAttributes(dpy, wins[i], &attr); + if (wins[i] == s->bar_window || wins[i] == s->key_window || wins[i] == s->input_window) continue; + + if (attr.override_redirect != True) + { + win = add_to_window_list (s, wins[i]); + if (attr.map_state != IsUnmapped) manage (win, s); + } + } + XFree((void *) wins); /* cast is to shut stoopid compiler up */ +} diff --git a/src/manage.h b/src/manage.h new file mode 100644 index 0000000..58a5590 --- /dev/null +++ b/src/manage.h @@ -0,0 +1,30 @@ +/* manage.h + * + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#ifndef _MANAGE_H +#define _MANAGE_H + +#include "data.h" + +void scanwins(screen_info *s); +void manage (rp_window *w, screen_info *s); +void unmanage (rp_window *w); +int update_window_name (rp_window *win); +void rename_current_window (); +#endif /* _MANAGE_H */ diff --git a/src/number.c b/src/number.c new file mode 100644 index 0000000..6bd11c6 --- /dev/null +++ b/src/number.c @@ -0,0 +1,130 @@ +/* handles the handing out of and uniqueness of window numbers. + + * Copyright (C) 2000 Shawn Betts + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA */ + +#include +#include + +#include "ratpoison.h" + + +/* A list of the numbers taken. */ +static int *numbers_taken; + +/* the number of numbers currently stored in the numbers_taken + array. */ +static int num_taken; + +/* the size of the numbers_taken array. */ +static int max_taken; + +static int +number_is_taken (int n) +{ + int i; + + for (i=0; i= max_taken) + { + max_taken *= 2; + numbers_taken = realloc (numbers_taken, sizeof (int) * max_taken); + if (numbers_taken == NULL) + { + fprintf (stderr, "numbers.c: Out of memory\n"); + exit (EXIT_FAILURE); + } + } + num_taken++; + + return num_taken-1; +} + +static int +add_to_list (int n) +{ + if (number_is_taken (n)) return 0; /* failed. */ + + numbers_taken[find_empty_cell()] = n; + return 1; /* success! */ +} + +/* returns a unique number that can be used as the window number in + the program bar. */ +int +get_unique_window_number () +{ + int i; + + /* look for a unique number, and add it to the list of taken + numbers. */ + i = 0; + while (!add_to_list (i)) i++; + + return i; +} + +/* When a window is destroyed, it gives back its window number with + this function. */ +void +return_window_number (int n) +{ + int i; + + for (i=0; i