JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
rename scrotwm to spectrwm
authorMarco Peereboom <marco@conformal.com>
Wed, 15 Feb 2012 20:09:13 +0000 (14:09 -0600)
committerMarco Peereboom <marco@conformal.com>
Wed, 15 Feb 2012 20:09:13 +0000 (14:09 -0600)
35 files changed:
Makefile
baraction.sh
freebsd/Makefile
linux/Makefile
linux/scrotwm.desktop [deleted file]
linux/spectrwm.desktop [new file with mode: 0644]
osx/Makefile
release.sh
scrotwm.1 [deleted file]
scrotwm.c [deleted file]
scrotwm.conf [deleted file]
scrotwm_cz.conf [deleted file]
scrotwm_es.1 [deleted file]
scrotwm_es.conf [deleted file]
scrotwm_fr.conf [deleted file]
scrotwm_fr_ch.conf [deleted file]
scrotwm_it.1 [deleted file]
scrotwm_pt.1 [deleted file]
scrotwm_ru.1 [deleted file]
scrotwm_se.conf [deleted file]
scrotwm_us.conf [deleted file]
spectrwm.1 [new file with mode: 0644]
spectrwm.c [new file with mode: 0644]
spectrwm.conf [new file with mode: 0644]
spectrwm_cz.conf [new file with mode: 0644]
spectrwm_es.1 [new file with mode: 0644]
spectrwm_es.conf [new file with mode: 0644]
spectrwm_fr.conf [new file with mode: 0644]
spectrwm_fr_ch.conf [new file with mode: 0644]
spectrwm_it.1 [new file with mode: 0644]
spectrwm_pt.1 [new file with mode: 0644]
spectrwm_ru.1 [new file with mode: 0644]
spectrwm_se.conf [new file with mode: 0644]
spectrwm_us.conf [new file with mode: 0644]
version.h

index ad27745..048eb32 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,9 +5,9 @@ PREFIX?=/usr/local
 BINDIR=${PREFIX}/bin
 SUBDIR= lib
 
-PROG=scrotwm
-#MAN=scrotwm_pt.1 scrotwm_ru.1
-MAN=scrotwm.1 scrotwm_es.1 scrotwm_it.1
+PROG=spectrwm
+#MAN=spectrwm_pt.1 spectrwm_ru.1
+MAN=spectrwm.1 spectrwm_es.1 spectrwm_it.1
 
 CFLAGS+=-std=c89 -Wall -Wno-uninitialized -ggdb3
 # Uncomment define below to disallow user settable clock format string
@@ -16,13 +16,13 @@ CPPFLAGS+= -I${X11BASE}/include
 LDADD+=-lutil -L${X11BASE}/lib -lX11 -lXrandr -lXtst
 BUILDVERSION != sh "${.CURDIR}/buildver.sh"
 .if !${BUILDVERSION} == ""
-CPPFLAGS+= -DSCROTWM_BUILDSTR=\"$(BUILDVERSION)\"
+CPPFLAGS+= -DSPECTRWM_BUILDSTR=\"$(BUILDVERSION)\"
 .endif
 
 MANDIR= ${PREFIX}/man/man
 
-#scrotwm_ru.cat1: scrotwm_ru.1
-#       nroff -mandoc ${.CURDIR}/scrotwm_ru.1 > ${.TARGET}
+#spectrwm_ru.cat1: spectrwm_ru.1
+#       nroff -mandoc ${.CURDIR}/spectrwm_ru.1 > ${.TARGET}
 
 obj: _xenocara_obj
 
index c3ac272..e87b93d 100644 (file)
@@ -4,7 +4,7 @@
 print_date() {
        # The date is printed to the status bar by default.
        # To print the date through this script, set clock_enabled to 0
-       # in scrotwm.conf.  Uncomment "print_date" below.
+       # in spectrwm.conf.  Uncomment "print_date" below.
        FORMAT="%a %b %d %R %Z %Y"
        DATE=`date "+${FORMAT}"`
        echo -n "${DATE}     "
index 8b23a4d..c8f03b2 100644 (file)
@@ -10,7 +10,7 @@ MANDIR?= $(PREFIX)/man
 LVERS!=        awk -F = '/major/ { printf( "%s.", $$2 ) } /minor/ { printf( "%s", $$2 ) }' ${.CURDIR}/../lib/shlib_version
 BUILDVERSION!= sh "${.CURDIR}/../buildver.sh"
 .if !${BUILDVERSION} == ""
-CFLAGS+= -DSCROTWM_BUILDSTR=\"$(BUILDVERSION)\"
+CFLAGS+= -DSPECTRWM_BUILDSTR=\"$(BUILDVERSION)\"
 .endif
 
 CFLAGS+= -Wall -Wno-uninitialized -I. -I${LOCALBASE}/include
@@ -18,16 +18,16 @@ CFLAGS+= -DSWM_LIB=\"$(LIBDIR)/libswmhack.so.$(LVERS)\"
 LDADD+= -lutil -L${LOCALBASE}/lib -lX11 -lXrandr -lXtst
 
 
-all: scrotwm libswmhack.so.$(LVERS)
+all: spectrwm libswmhack.so.$(LVERS)
 
-scrotwm.c:
-       ln -sf ../scrotwm.c
+spectrwm.c:
+       ln -sf ../spectrwm.c
        ln -sf ../version.h
 
 swm_hack.c:
        ln -sf ../lib/swm_hack.c
 
-scrotwm: scrotwm.o
+spectrwm: spectrwm.o
        $(CC) $(LDFLAGS) $(LDADD) -o ${.TARGET} ${.ALLSRC}
 
 swm_hack.so: swm_hack.c
@@ -40,15 +40,15 @@ install: all
        install -m 755 -d $(DESTDIR)$(BINDIR)
        install -m 755 -d $(DESTDIR)$(LIBDIR)
        install -m 755 -d $(DESTDIR)$(MANDIR)/man1
-       install -m 755 scrotwm $(DESTDIR)$(BINDIR)
+       install -m 755 spectrwm $(DESTDIR)$(BINDIR)
        install -m 755 libswmhack.so.$(LVERS) $(DESTDIR)$(LIBDIR)
-       install -m 644 ../scrotwm.1 $(DESTDIR)$(MANDIR)/man1/scrotwm.1
-       install -m 644 ../scrotwm_es.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_es.1
-       install -m 644 ../scrotwm_it.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_it.1
-       install -m 644 ../scrotwm_pt.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_pt.1
-       install -m 644 ../scrotwm_ru.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_ru.1
+       install -m 644 ../spectrwm.1 $(DESTDIR)$(MANDIR)/man1/spectrwm.1
+       install -m 644 ../spectrwm_es.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_es.1
+       install -m 644 ../spectrwm_it.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_it.1
+       install -m 644 ../spectrwm_pt.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_pt.1
+       install -m 644 ../spectrwm_ru.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_ru.1
 
 clean:
-       rm -f scrotwm *.o *.so libswmhack.so.* scrotwm.c swm_hack.c version.h
+       rm -f spectrwm *.o *.so libswmhack.so.* spectrwm.c swm_hack.c version.h
 
 .sinclude <bsd.port.post.mk>
index d8f0206..2060184 100644 (file)
@@ -11,16 +11,16 @@ CC= gcc
 
 LVERS= $(shell . ../lib/shlib_version; echo $$major.$$minor)
 
-all: scrotwm libswmhack.so.$(LVERS)
+all: spectrwm libswmhack.so.$(LVERS)
 
-scrotwm.c:
-       ln -sf ../scrotwm.c
+spectrwm.c:
+       ln -sf ../spectrwm.c
        ln -sf ../version.h
 
 swm_hack.c:
        ln -sf ../lib/swm_hack.c
 
-scrotwm: scrotwm.o linux.o
+spectrwm: spectrwm.o linux.o
        $(CC) $(LDFLAGS) -o $@ $+ $(LDADD)
 
 %.so: %.c
@@ -33,15 +33,15 @@ install: all
        install -m 755 -d $(DESTDIR)$(BINDIR)
        install -m 755 -d $(DESTDIR)$(LIBDIR)
        install -m 755 -d $(DESTDIR)$(MANDIR)/man1
-       install -m 755 scrotwm $(DESTDIR)$(BINDIR)
+       install -m 755 spectrwm $(DESTDIR)$(BINDIR)
        install -m 755 libswmhack.so.$(LVERS) $(DESTDIR)$(LIBDIR)
-       install -m 644 ../scrotwm.1 $(DESTDIR)$(MANDIR)/man1/scrotwm.1
-       install -m 644 ../scrotwm_es.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_es.1
-       install -m 644 ../scrotwm_it.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_it.1
-       install -m 644 ../scrotwm_pt.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_pt.1
-       install -m 644 ../scrotwm_ru.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_ru.1
+       install -m 644 ../spectrwm.1 $(DESTDIR)$(MANDIR)/man1/spectrwm.1
+       install -m 644 ../spectrwm_es.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_es.1
+       install -m 644 ../spectrwm_it.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_it.1
+       install -m 644 ../spectrwm_pt.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_pt.1
+       install -m 644 ../spectrwm_ru.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_ru.1
 
 clean:
-       rm -f scrotwm *.o *.so libswmhack.so.* scrotwm.c swm_hack.c version.h
+       rm -f spectrwm *.o *.so libswmhack.so.* spectrwm.c swm_hack.c version.h
 
 .PHONY: all install clean
diff --git a/linux/scrotwm.desktop b/linux/scrotwm.desktop
deleted file mode 100644 (file)
index fdc5ad2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-[Desktop Entry]
-Name=ScrotWM
-Comment=The ScrotWM window manager
-Type=Application
-Exec=/usr/bin/scrotwm
-TryExec=/usr/bin/scrotwm
diff --git a/linux/spectrwm.desktop b/linux/spectrwm.desktop
new file mode 100644 (file)
index 0000000..1ed4c7d
--- /dev/null
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Name=spectrwm
+Comment=The spectrwm window manager
+Type=Application
+Exec=/usr/bin/spectrwm
+TryExec=/usr/bin/spectrwm
index 7d16a6d..7e34441 100644 (file)
@@ -11,15 +11,15 @@ CC= gcc
 
 LVERS= $(shell . ../lib/shlib_version; echo $$major.$$minor)
 
-all: scrotwm libswmhack.so.$(LVERS)
+all: spectrwm libswmhack.so.$(LVERS)
 
-scrotwm.c:
-       ln -sf ../scrotwm.c
+spectrwm.c:
+       ln -sf ../spectrwm.c
 
 swm_hack.c:
        ln -sf ../lib/swm_hack.c
 
-scrotwm: scrotwm.o osx.o
+spectrwm: spectrwm.o osx.o
        $(CC) $(LDFLAGS) -o $@ $+ $(LDADD)
 
 %.so: %.c
@@ -34,15 +34,15 @@ install: all
        install -m 755 -d $(DESTDIR)$(BINDIR)
        install -m 755 -d $(DESTDIR)$(LIBDIR)
        install -m 755 -d $(DESTDIR)$(MANDIR)/man1
-       install -m 755 scrotwm $(DESTDIR)$(BINDIR)
+       install -m 755 spectrwm $(DESTDIR)$(BINDIR)
        install -m 755 libswmhack.so.$(LVERS) $(DESTDIR)$(LIBDIR)
-       install -m 644 ../scrotwm.1 $(DESTDIR)$(MANDIR)/man1/scrotwm.1
-       install -m 644 ../scrotwm_es.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_es.1
-       install -m 644 ../scrotwm_it.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_it.1
-       install -m 644 ../scrotwm_pt.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_pt.1
-       install -m 644 ../scrotwm_ru.1 $(DESTDIR)$(MANDIR)/man1/scrotwm_ru.1
+       install -m 644 ../spectrwm.1 $(DESTDIR)$(MANDIR)/man1/spectrwm.1
+       install -m 644 ../spectrwm_es.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_es.1
+       install -m 644 ../spectrwm_it.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_it.1
+       install -m 644 ../spectrwm_pt.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_pt.1
+       install -m 644 ../spectrwm_ru.1 $(DESTDIR)$(MANDIR)/man1/spectrwm_ru.1
 
 clean:
-       rm -f scrotwm *.o *.so libswmhack.so.* scrotwm.c swm_hack.c
+       rm -f spectrwm *.o *.so libswmhack.so.* spectrwm.c swm_hack.c
 
 .PHONY: all install clean
index 3ac9b92..801b056 100644 (file)
@@ -7,7 +7,7 @@
 #   - Tags the release
 #   - Creates a release tarball
 
-PROJECT=scrotwm
+PROJECT=spectrwm
 PROJECT_UC=$(echo $PROJECT | tr '[:lower:]' '[:upper:]')
 SCRIPT=$(basename $0)
 HEADER=version.h
diff --git a/scrotwm.1 b/scrotwm.1
deleted file mode 100644 (file)
index 21bc043..0000000
--- a/scrotwm.1
+++ /dev/null
@@ -1,854 +0,0 @@
-.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
-.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: February 8 2012 $
-.Dt SCROTWM 1
-.Os
-.Sh NAME
-.Nm scrotwm
-.Nd window manager for X11
-.Sh SYNOPSIS
-.Nm scrotwm
-.Sh DESCRIPTION
-.Nm
-is a minimalistic window manager that tries to stay out of the way so that
-valuable screen real estate can be used for much more important stuff.
-It has sane defaults and does not require one to learn a language to do any
-configuration.
-It was written by hackers for hackers and it strives to be small, compact and
-fast.
-.Pp
-When
-.Nm
-starts up, it reads settings from its configuration file,
-.Pa scrotwm.conf .
-See the
-.Sx CONFIGURATION FILES
-section below.
-.Pp
-The following notation is used throughout this page:
-.Pp
-.Bl -tag -width Ds -offset indent -compact
-.It Cm M
-Meta
-.It Cm S
-Shift
-.It Aq Cm Name
-Named key
-.It Cm M1
-Mouse button 1
-.It Cm M3
-Mouse button 3
-.El
-.Pp
-.Nm
-is very simple in its use.
-Most of the actions are initiated via key or mouse bindings.
-See the
-.Sx BINDINGS
-section below for defaults and customizations.
-.Sh CONFIGURATION FILES
-.Nm
-first tries to open the user specific file,
-.Pa ~/.scrotwm.conf .
-If that file is unavailable,
-it then tries to open the global configuration file
-.Pa /etc/scrotwm.conf .
-.Pp
-The format of the file is \*(Ltkeyword\*(Gt = \*(Ltsetting\*(Gt.
-For example:
-.Pp
-.Dl color_focus = red
-.Pp
-Enabling or disabling an option is done by using 1 or 0 respectively.
-.Pp
-The file supports the following keywords:
-.Bl -tag -width 2m
-.It Ic autorun
-Launch an application in a specified workspace at start-of-day.
-Defined in the format ws[<idx>]:application, e.g. ws[2]:xterm launches an
-xterm in workspace 2.
-.It Ic bar_action
-External script that populates additional information in the status bar,
-such as battery life.
-.It Ic bar_at_bottom
-Place the statusbar at the bottom of each region instead of the top.
-.It Ic bar_border Ns Bq Ar x
-Color of the status bar border in screen
-.Ar x .
-.It Ic bar_border_width
-Set status bar border thickness in pixels.
-Disable border by setting to 0.
-.It Ic bar_color Ns Bq Ar x
-Color of the status bar window in screen
-.Ar x .
-.It Ic bar_delay
-Update frequency, in seconds, of external script that populates the status bar.
-.It Ic bar_enabled
-Enable or disable status bar.
-.It Ic bar_font
-Status bar font.
-.It Ic bar_font_color Ns Bq Ar x
-Color of the font in status bar in screen
-.Ar x .
-.It Ic bar_justify
-Justify the status bar text. Possible values are
-.Pa left ,
-.Pa center ,
-and
-.Pa right .
-.It Ic bind Ns Bq Ar x
-Bind key combo to action
-.Ar x .
-See the
-.Sx BINDINGS
-section below.
-.It Ic border_width
-Set window border thickness in pixels.
-Disable all borders by setting to 0.
-.It Ic clock_enabled
-Enable or disable displaying the clock in the status bar.
-Disable by setting to 0
-so a custom clock could be used in the
-.Pa bar_action
-script.
-.It Ic color_focus
-Border color of the currently focussed window.
-.It Ic color_unfocus
-Border color of unfocussed windows.
-.It Ic dialog_ratio
-Some applications have dialogue windows that are too small to be useful.
-This ratio is the screen size to what they will be resized.
-For example, 0.6 is 60% of the physical screen size.
-.It Ic disable_border
-Remove border when bar is disabled and there is only one window on the screen.
-.It Ic focus_mode
-Using a value of
-.Pa follow_cursor
-will make the window manager focus the window
-under the mouse when switching workspaces and creating windows.
-.It Ic keyboard_mapping
-Clear all key bindings and load new key bindings from the specified file.
-This allows you to load pre-defined key bindings for your keyboard layout.
-See the
-.Sx KEYBOARD MAPPING FILES
-section below for a list of keyboard mapping files that have been provided
-for several keyboard layouts.
-.It Ic layout
-Select layout to use at start-of-day.
-Defined in the format
-ws[idx]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode, e.g.
-ws[2]:-4:0:1:0:horizontal sets worskspace 2 to the horizontal stack mode and
-shrinks the master area by 4 ticks and adds one window to the stack, while
-maintaining default floating window behavior.
-Possible stack_mode values are
-.Pa vertical ,
-.Pa horizontal
-and
-.Pa fullscreen .
-.Pp
-See
-.Pa master_grow ,
-.Pa master_shrink ,
-.Pa master_add ,
-.Pa master_del ,
-.Pa stack_inc ,
-.Pa stack_dec ,
-and
-.Pa always_raise
-for more information.
-Note that the stacking options are complicated and have side-effects.
-One should familiarize oneself with these commands before experimenting with the
-.Pa layout
-option.
-.Pp
-This setting is not retained at restart.
-.It Ic modkey
-Change mod key.
-Mod1 is generally the ALT key and Mod4 is the windows key on a PC.
-.It Ic program Ns Bq Ar p
-Define new action to spawn a program
-.Ar p .
-See the
-.Sx PROGRAMS
-section below.
-.It Ic quirk Ns Bq Ar c:n
-Add "quirk" for windows with class
-.Ar c
-and name
-.Ar n .
-See the
-.Sx QUIRKS
-section below.
-.It Ic region
-Allocates a custom region, removing any autodetected regions which occupy the same
-space on the screen.
-Defined in the format screen[<idx>]:WIDTHxHEIGHT+X+Y,
-e.g.\& screen[1]:800x1200+0+0.
-.Pp
-To make a screen span multiple monitors, create a region big enough to cover
-them all, e.g. screen[1]:2048x768+0+0 makes the screen span two monitors with
-1024x768 resolution sitting one next to the other.
-.It Ic stack_enabled
-Enable or disable displaying the current stacking algorithm in the status bar.
-.It Ic term_width
-Set a preferred minimum width for the terminal.
-If this value is greater than 0,
-.Nm
-will attempt to adjust the font sizes in the terminal to keep the terminal
-width above this number as the window is resized.
-Only
-.Xr xterm 1
-is currently supported.
-The
-.Xr xterm 1
-binary must not be setuid or setgid, which it is by default on most systems.
-Users may need to set program[term] (see the
-.Sx PROGRAMS
-section) to use an alternate copy of the
-.Xr xterm 1
-binary without the setgid bit set.
-.It Ic title_class_enabled
-Enable or disable displaying the window class in the status bar.
-Enable by setting to 1.
-.It Ic title_name_enabled
-Enable or disable displaying the window title in the status bar.
-Enable by setting to 1.
-.It Ic urgent_enabled
-Enable or disable the urgency hint.
-Note that many terminal emulators require this to be enabled for it to
-propagate.
-In xterm, for example, one needs to add the following line
-.Pa xterm.urgentOnBell: true
-to
-.Pa .Xdefaults .
-.It Ic verbose_layout
-Enable or disable displaying the current master and stack values in the status
-bar.
-Enable by setting to 1.
-.It Ic window_name_enabled
-Enable or disable displaying the window name in the status bar.
-Enable by setting to 1.
-.El
-.Pp
-Colors need to be specified per the
-.Xr XQueryColor 3
-specification and fonts need to be specified per the
-.Xr XQueryFont 3
-specification.
-.Pp
-To list the available fonts in your system see
-.Xr fc-list 1
-or
-.Xr xlsfonts 1
-manpages.
-The
-.Xr xfontsel 1
-application can help you to show the X Logical Font Description ("XLFD") used
-as setting in the keyword
-.Pa bar_font .
-.Sh PROGRAMS
-.Nm
-allows you to define custom actions to launch programs of your choice and then
-bind them the same as with built-in actions.
-See the
-.Sx BINDINGS
-section below.
-.Pp
-The default programs are described below:
-.Pp
-.Bl -tag -width "screenshot_wind" -offset indent -compact
-.It Cm term
-xterm
-.It Cm screenshot_all
-screenshot.sh full
-.It Cm screenshot_wind
-screenshot.sh window
-.It Cm lock
-xlock
-.It Cm initscr
-initscreen.sh
-.It Cm menu
-dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
-.El
-.Pp
-Custom programs in the configuration file are specified as follows:
-.Pp
-.Dl program[<name>] = <progpath> [<arg> [... <arg>]]
-.Pp
-.Aq name
-is any identifier that does not conflict with a built-in action or keyword,
-.Aq progpath
-is the desired program, and
-.Aq arg
-is zero or more arguments to the program.
-.Pp
-The following variables represent settable values in
-.Nm
-(see the
-.Sx CONFIGURATION FILES
-section above),
-and may be used in the
-.Aq arg
-fields and will be substituted for values at the time the program is spawned:
-.Pp
-.Bl -tag -width "$bar_font_color" -offset indent -compact
-.It Cm $bar_border
-.It Cm $bar_color
-.It Cm $bar_font
-.It Cm $bar_font_color
-.It Cm $color_focus
-.It Cm $color_unfocus
-.El
-.Pp
-Example:
-.Bd -literal -offset indent
-program[ff] = /usr/local/bin/firefox http://scrotwm.org/
-bind[ff] = Mod+Shift+b # Now Mod+Shift+B launches firefox
-.Ed
-.Pp
-To undo the previous:
-.Bd -literal -offset indent
-bind[] = Mod+Shift+b
-program[ff] =
-.Ed
-.Sh BINDINGS
-.Nm
-provides many functions (or actions) accessed via key or mouse bindings.
-.Pp
-The current mouse bindings are described below:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M1
-Focus window
-.It Cm M-M1
-Move window
-.It Cm M-M3
-Resize window
-.It Cm M-S-M3
-Resize window while maintaining it centered
-.El
-.Pp
-The default key bindings are described below:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M-S- Ns Aq Cm Return
-term
-.It Cm M-p
-menu
-.It Cm M-S-q
-quit
-.It Cm M-q
-restart
-.It Cm M- Ns Aq Cm Space
-cycle_layout
-.It Cm M-S- Ns Aq Cm \e
-flip_layout
-.It Cm M-S- Ns Aq Cm Space
-stack_reset
-.It Cm M-h
-master_shrink
-.It Cm M-l
-master_grow
-.It Cm M-,
-master_add
-.It Cm M-.
-master_del
-.It Cm M-S-,
-stack_inc
-.It Cm M-S-.
-stack_dec
-.It Cm M- Ns Aq Cm Return
-swap_main
-.It Xo
-.Cm M-j ,
-.Cm M- Ns Aq Cm TAB
-.Xc
-focus_next
-.It Xo
-.Cm M-k ,
-.Cm M-S- Ns Aq Cm TAB
-.Xc
-focus_prev
-.It Cm M-m
-focus_main
-.It Cm M-S-j
-swap_next
-.It Cm M-S-k
-swap_prev
-.It Cm M-b
-bar_toggle
-.It Cm M-x
-wind_del
-.It Cm M-S-x
-wind_kill
-.It Cm M- Ns Aq Ar n
-.Pf ws_ Ar n
-.It Cm M-S- Ns Aq Ar n
-.Pf mvws_ Ar n
-.It Cm M- Ns Aq Cm Right
-ws_next
-.It Cm M- Ns Aq Cm Left
-ws_prev
-.It Cm M- Ns Aq Cm Up
-ws_next_all
-.It Cm M- Ns Aq Cm Down
-ws_prev_all
-.It Cm M-a
-ws_prior
-.It Cm M-S- Ns Aq Cm Right
-screen_next
-.It Cm M-S- Ns Aq Cm Left
-screen_prev
-.It Cm M-s
-screenshot_all
-.It Cm M-S-s
-screenshot_wind
-.It Cm M-S-v
-version
-.It Cm M-t
-float_toggle
-.It Cm M-S- Ns Aq Cm Delete
-lock
-.It Cm M-S-i
-initscr
-.It Cm M-w
-iconify
-.It Cm M-S-w
-uniconify
-.It Cm M-S-r
-always_raise
-.It Cm M-v
-button2
-.It Cm M--
-width_shrink
-.It Cm M-=
-width_grow
-.It Cm M-S--
-height_shrink
-.It Cm M-S-=
-height_grow
-.It Cm M-[
-move_left
-.It Cm M-]
-move_right
-.It Cm M-S-[
-move_up
-.It Cm M-S-]
-move_down
-.It Cm M-S-/
-name_workspace
-.It Cm M-/
-search_workspace
-.It Cm M-f
-search_win
-.El
-.Pp
-The action names and descriptions are listed below:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXXX" -offset indent -compact
-.It Cm term
-Spawn a new terminal
-(see
-.Sx PROGRAMS
-above).
-.It Cm menu
-Menu
-(see
-.Sx PROGRAMS
-above).
-.It Cm quit
-Quit
-.Nm .
-.It Cm restart
-Restart
-.Nm .
-.It Cm cycle_layout
-Cycle layout.
-.It Cm flip_layout
-Swap the master and stacking areas.
-.It Cm stack_reset
-Reset layout.
-.It Cm master_shrink
-Shrink master area.
-.It Cm master_grow
-Grow master area.
-.It Cm master_add
-Add windows to master area.
-.It Cm master_del
-Remove windows from master area.
-.It Cm stack_inc
-Add columns/rows to stacking area.
-.It Cm stack_dec
-Remove columns/rows from stacking area.
-.It Cm swap_main
-Move current window to master area.
-.It Cm focus_next
-Focus next window in workspace.
-.It Cm focus_prev
-Focus previous window in workspace.
-.It Cm focus_main
-Focus on main window in workspace.
-.It Cm swap_next
-Swap with next window in workspace.
-.It Cm swap_prev
-Swap with previous window in workspace.
-.It Cm bar_toggle
-Toggle status bar in all workspaces.
-.It Cm wind_del
-Delete current window in workspace.
-.It Cm wind_kill
-Destroy current window in workspace.
-.It Cm ws_ Ns Ar n
-Switch to workspace
-.Ar n ,
-where
-.Ar n
-is 1 through 10.
-.It Cm mvws_ Ns Ar n
-Move current window to workspace
-.Ar n ,
-where
-.Ar n
-is 1 through 10.
-.It Cm ws_next
-Switch to next workspace with a window in it.
-.It Cm ws_prev
-Switch to previous workspace with a window in it.
-.It Cm ws_next_all
-Switch to next workspace.
-.It Cm ws_prev_all
-Switch to previous workspace.
-.It Cm ws_prior
-Switch to last visited workspace.
-.It Cm screen_next
-Move pointer to next region.
-.It Cm screen_prev
-Move pointer to previous region.
-.It Cm screenshot_all
-Take screenshot of entire screen (if enabled)
-(see
-.Sx PROGRAMS
-above).
-.It Cm screenshot_wind
-Take screenshot of selected window (if enabled)
-(see
-.Sx PROGRAMS
-above).
-.It Cm version
-Toggle version in status bar.
-.It Cm float_toggle
-Toggle focused window between tiled and floating.
-.It Cm lock
-Lock screen
-(see
-.Sx PROGRAMS
-above).
-.It Cm initscr
-Reinitialize physical screens
-(see
-.Sx PROGRAMS
-above).
-.It Cm iconify
-Minimize (unmap) currently focused window.
-.It Cm uniconify
-Maximize (map) window returned by dmenu selection.
-.It Cm always_raise
-When set tiled windows are allowed to obscure floating windows.
-.It Cm button2
-Fake a middle mouse button click (mouse button 2).
-.It Cm width_shrink
-Shrink the width of a floating window.
-.It Cm width_grow
-Grow the width of a floating window.
-.It Cm height_shrink
-Shrink the height of a floating window.
-.It Cm height_grow
-Grow the height of a floating window.
-.It Cm move_left
-Move a floating window a step to the left.
-.It Cm move_right
-Move a floating window a step to the right.
-.It Cm move_up
-Move a floating window a step upwards.
-.It Cm move_down
-Move a floating window a step downwards.
-.It Cm name_workspace
-Name the current workspace.
-.It Cm search_workspace
-Search for a workspace.
-.It Cm search_win
-Search the windows in the current workspace.
-.El
-.Pp
-Custom bindings in the configuration file are specified as follows:
-.Pp
-.Dl bind[<action>] = <keys>
-.Pp
-.Aq action
-is one of the actions listed above (or empty) and
-.Aq keys
-is in the form of zero or more modifier keys
-(MOD, Mod1, Shift, etc.) and one or more normal keys
-(b, space, etc.), separated by "+".
-For example:
-.Bd -literal -offset indent
-bind[reset] = Mod4+q # bind Windows-key + q to reset
-bind[] = Mod1+q # unbind Alt + q
-.Ed
-.Pp
-To use the currently defined
-.Ic modkey ,
-specify MOD as the modifier key.
-.Pp
-Multiple key combinations may be bound to the same action.
-.Sh KEYBOARD MAPPING FILES
-Keyboard mapping files for several keyboard layouts are listed
-below.
-These files can be used with the
-.Pa keyboard_mapping
-setting to load pre-defined key bindings for the specified
-keyboard layout.
-.Pp
-.Bl -tag -width "scrotwm_XX.confXXX" -offset indent -compact
-.It Cm scrotwm_cz.conf
-Czech Republic keyboard layout
-.It Cm scrotwm_es.conf
-Spanish keyboard layout
-.It Cm scrotwm_fr.conf
-French keyboard layout
-.It Cm scrotwm_fr_ch.conf
-Swiss French keyboard layout
-.It Cm scrotwm_se.conf
-Swedish keyboard layout
-.It Cm scrotwm_us.conf
-United States keyboard layout
-.El
-.Sh QUIRKS
-.Nm
-provides "quirks" which handle windows that must be treated specially
-in a tiling window manager, such as some dialogs and fullscreen apps.
-.Pp
-The default quirks are described below:
-.Pp
-.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
-.It Firefox\-bin:firefox\-bin
-TRANSSZ
-.It Firefox:Dialog
-FLOAT
-.It Gimp:gimp
-FLOAT + ANYWHERE
-.It MPlayer:xv
-FLOAT + FULLSCREEN + FOCUSPREV
-.It OpenOffice.org 2.4:VCLSalFrame
-FLOAT
-.It OpenOffice.org 3.1:VCLSalFrame
-FLOAT
-.It pcb:pcb
-FLOAT
-.It xine:Xine Window
-FLOAT + ANYWHERE
-.It xine:xine Panel
-FLOAT + ANYWHERE
-.It xine:xine Video Fullscreen Window
-FULLSCREEN + FLOAT
-.It Xitk:Xitk Combo
-FLOAT + ANYWHERE
-.It Xitk:Xine Window
-FLOAT + ANYWHERE
-.It XTerm:xterm
-XTERM_FONTADJ
-.El
-.Pp
-The quirks themselves are described below:
-.Pp
-.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
-.It FLOAT
-This window should not be tiled, but allowed to float freely.
-.It TRANSSZ
-Adjusts size on transient windows that are too small using dialog_ratio
-(see
-.Sx CONFIGURATION FILES ) .
-.It ANYWHERE
-Allow window to position itself, uncentered.
-.It XTERM_FONTADJ
-Adjust xterm fonts when resizing.
-.It FULLSCREEN
-Remove border to allow window to use full screen size.
-.It FOCUSPREV
-On exit force focus on previously focused application not previous application
-in the stack.
-.El
-.Pp
-Custom quirks in the configuration file are specified as follows:
-.Pp
-.Dl quirk[<class>:<name>] = <quirk> [ + <quirk> ... ]
-.Pp
-.Aq class
-and
-.Aq name
-specify the window to which the quirk(s) apply, and
-.Aq quirk
-is one of the quirks from the list above.
-For example:
-.Bd -literal -offset indent
-quirk[MPlayer:xv] = FLOAT + FULLSCREEN + FOCUSPREV
-quirk[pcb:pcb] = NONE  # remove existing quirk
-.Ed
-.Pp
-You can obtain
-.Aq class
-and
-.Aq name
-by running
-.Xr xprop 1
-and then clicking on the desired window.
-In the following example the main window of Firefox was clicked:
-.Bd -literal -offset indent
-$ xprop | grep WM_CLASS
-WM_CLASS(STRING) = "Navigator", "Firefox"
-.Ed
-.Pp
-Note that grepping for WM_CLASS flips class and name.
-In the example above the quirk entry would be:
-.Bd -literal -offset indent
-quirk[Firefox:Navigator] = FLOAT
-.Ed
-.Pp
-.Nm
-also automatically assigns quirks to windows based on the value
-of the window's _NET_WM_WINDOW_TYPE property as follows:
-.Pp
-.Bl -tag -width "_NET_WM_WINDOW_TYPE_TOOLBAR<TAB>XXX" -offset indent -compact
-.It _NET_WM_WINDOW_TYPE_DOCK
-FLOAT + ANYWHERE
-.It _NET_WM_WINDOW_TYPE_TOOLBAR
-FLOAT + ANYWHERE
-.It _NET_WM_WINDOW_TYPE_UTILITY
-FLOAT + ANYWHERE
-.It _NET_WM_WINDOW_TYPE_SPLASH
-FLOAT
-.It _NET_WM_WINDOW_TYPE_DIALOG
-FLOAT
-.El
-.Pp
-In all other cases, no automatic quirks are assigned to the window.
-Quirks specified in the configuration file override the automatic quirks.
-.Sh EWMH
-.Nm
-partially implements the Extended Window Manager Hints (EWMH) specification.
-This enables controlling windows as well as
-.Nm
-itself from external scripts and programs.
-This is achieved by
-.Nm
-responding to certain ClientMessage events.
-From the terminal these events
-can be conveniently sent using tools such as
-.Xr wmctrl 1
-and
-.Xr xdotool 1 .
-For the
-actual format of these ClientMessage events, see the EWMH specification.
-.Pp
-The id of the currently focused window is stored in the _NET_ACTIVE_WINDOW
-property of the root window.
-This can be used for example to retrieve the
-title of the currently active window with
-.Xr xprop 1
-and
-.Xr grep 1 :
-.Bd -literal -offset indent
-$ WINDOWID=`xprop \-root _NET_ACTIVE_WINDOW | grep \-o "0x.*"`
-$ xprop \-id $WINDOWID WM_NAME | grep \-o "\\".*\\""
-.Ed
-.Pp
-A window can be focused by sending a _NET_ACTIVE_WINDOW client message
-to the root window.
-For example, using
-.Xr wmctrl 1
-to send the message
-(assuming 0x4a0000b is the id of the window to be focused):
-.Bd -literal -offset indent
-$ wmctrl \-i \-a 0x4a0000b
-.Ed
-.Pp
-Windows can be closed by sending a _NET_CLOSE_WINDOW client message
-to the root window.
-For example, using
-.Xr wmctrl 1
-to send the message
-(assuming 0x4a0000b is the id of the window to be closed):
-.Bd -literal -offset indent
-$ wmctrl \-i \-c 0x4a0000b
-.Ed
-.Pp
-Windows can be floated and un-floated by adding or removing the
-_NET_WM_STATE_ABOVE atom from the _NET_WM_STATE property of the window.
-This can be achieved by sending a _NET_WM_STATE client message to the
-root window.
-For example, the following toggles the floating state of
-a window using
-.Xr wmctrl 1
-to send the message (assuming 0x4a0000b is the  id of the window floated
-or un-floated):
-.Bd -literal -offset indent
-$ wmctrl \-i \-r 0x4a0000b \-b toggle,_NET_WM_STATE_ABOVE
-.Ed
-.Pp
-Floating windows can also be resized and moved by sending a
-_NET_MOVERESIZE_WINDOW client message to the root window.
-For example,
-using
-.Xr wmctrl 1
-to send the message (assuming 0x4a0000b is the id of
-the window to be resize/moved):
-.Bd -literal -offset indent
-$ wmctrl \-i \-r 0x4a0000b \-e 0,100,50,640,480
-.Ed
-.Pp
-This moves the window to (100,50) and resizes it to 640x480.
-.Pp
-Any _NET_MOVERESIZE_WINDOW events received for stacked windows are ignored.
-.Sh SIGNALS
-Sending
-.Nm
-a HUP signal will restart it.
-.Sh FILES
-.Bl -tag -width "/etc/scrotwm.confXXX" -compact
-.It Pa ~/.scrotwm.conf
-.Nm
-user specific settings.
-.It Pa /etc/scrotwm.conf
-.Nm
-global settings.
-.El
-.Sh HISTORY
-.Nm
-was inspired by xmonad & dwm.
-.Sh AUTHORS
-.An -nosplit
-.Nm
-was written by:
-.Pp
-.Bl -tag -width "Ryan Thomas McBride Aq mcbride@countersiege.com " -offset indent -compact
-.It Cm Marco Peereboom Aq marco@peereboom.us
-.It Cm Ryan Thomas McBride Aq mcbride@countersiege.com
-.It Cm Darrin Chandler Aq dwchandler@stilyagin.com
-.It Cm Pierre-Yves Ritschard Aq pyr@spootnik.org
-.It Cm Tuukka Kataja Aq stuge@xor.fi
-.It Cm Jason L. Wright Aq jason@thought.net
-.It Cm Reginald Kennedy Aq rk@rejii.com
-.El
diff --git a/scrotwm.c b/scrotwm.c
deleted file mode 100644 (file)
index 9545475..0000000
--- a/scrotwm.c
+++ /dev/null
@@ -1,7095 +0,0 @@
-/*
- * Copyright (c) 2009-2012 Marco Peereboom <marco@peereboom.us>
- * Copyright (c) 2009-2011 Ryan McBride <mcbride@countersiege.com>
- * Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
- * Copyright (c) 2009 Pierre-Yves Ritschard <pyr@spootnik.org>
- * Copyright (c) 2010 Tuukka Kataja <stuge@xor.fi>
- * Copyright (c) 2011 Jason L. Wright <jason@thought.net>
- * Copyright (c) 2011-2012 Reginald Kennedy <rk@rejii.com>
- * Copyright (c) 2012 Lawrence Teo <lteo@lteo.net>
- * Copyright (c) 2012 Tiago Cunha <tcunha@gmx.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-/*
- * Much code and ideas taken from dwm under the following license:
- * MIT/X Consortium License
- *
- * 2006-2008 Anselm R Garbe <garbeam at gmail dot com>
- * 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
- * 2006-2007 Jukka Salmi <jukka at salmi dot ch>
- * 2007 Premysl Hruby <dfenze at gmail dot com>
- * 2007 Szabolcs Nagy <nszabolcs at gmail dot com>
- * 2007 Christof Musik <christof at sendfax dot de>
- * 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
- * 2007-2008 Peter Hartlich <sgkkr at hartlich dot com>
- * 2008 Martin Hurton <martin dot hurton at gmail dot com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <locale.h>
-#include <unistd.h>
-#include <time.h>
-#include <signal.h>
-#include <string.h>
-#include <util.h>
-#include <pwd.h>
-#include <paths.h>
-#include <ctype.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/queue.h>
-#include <sys/param.h>
-#include <sys/select.h>
-#if defined(__linux__)
-#include "tree.h"
-#elif defined(__OpenBSD__)
-#include <sys/tree.h>
-#elif defined(__FreeBSD__)
-#include <sys/tree.h>
-#else
-#include <sys/tree.h>
-#endif
-
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/Xrandr.h>
-#include <X11/extensions/XTest.h>
-
-#ifdef __OSX__
-#include <osx.h>
-#endif
-
-#include "version.h"
-
-#ifdef SCROTWM_BUILDSTR
-static const char      *buildstr = SCROTWM_BUILDSTR;
-#else
-static const char      *buildstr = SCROTWM_VERSION;
-#endif
-
-#if RANDR_MAJOR < 1
-#  error XRandR versions less than 1.0 are not supported
-#endif
-
-#if RANDR_MAJOR >= 1
-#if RANDR_MINOR >= 2
-#define SWM_XRR_HAS_CRTC
-#endif
-#endif
-
-/*#define SWM_DEBUG*/
-#ifdef SWM_DEBUG
-#define DPRINTF(x...)          do { if (swm_debug) fprintf(stderr, x); } while (0)
-#define DNPRINTF(n,x...)       do { if (swm_debug & n) fprintf(stderr, x); } while (0)
-#define SWM_D_MISC             0x0001
-#define SWM_D_EVENT            0x0002
-#define SWM_D_WS               0x0004
-#define SWM_D_FOCUS            0x0008
-#define SWM_D_MOVE             0x0010
-#define SWM_D_STACK            0x0020
-#define SWM_D_MOUSE            0x0040
-#define SWM_D_PROP             0x0080
-#define SWM_D_CLASS            0x0100
-#define SWM_D_KEY              0x0200
-#define SWM_D_QUIRK            0x0400
-#define SWM_D_SPAWN            0x0800
-#define SWM_D_EVENTQ           0x1000
-#define SWM_D_CONF             0x2000
-#define SWM_D_BAR              0x4000
-
-u_int32_t              swm_debug = 0
-                           | SWM_D_MISC
-                           | SWM_D_EVENT
-                           | SWM_D_WS
-                           | SWM_D_FOCUS
-                           | SWM_D_MOVE
-                           | SWM_D_STACK
-                           | SWM_D_MOUSE
-                           | SWM_D_PROP
-                           | SWM_D_CLASS
-                           | SWM_D_KEY
-                           | SWM_D_QUIRK
-                           | SWM_D_SPAWN
-                           | SWM_D_EVENTQ
-                           | SWM_D_CONF
-                           | SWM_D_BAR
-                           ;
-#else
-#define DPRINTF(x...)
-#define DNPRINTF(n,x...)
-#endif
-
-#define LENGTH(x)              (sizeof x / sizeof x[0])
-#define MODKEY                 Mod1Mask
-#define CLEANMASK(mask)                (mask & ~(numlockmask | LockMask))
-#define BUTTONMASK             (ButtonPressMask|ButtonReleaseMask)
-#define MOUSEMASK              (BUTTONMASK|PointerMotionMask)
-#define SWM_PROPLEN            (16)
-#define SWM_FUNCNAME_LEN       (32)
-#define SWM_KEYS_LEN           (255)
-#define SWM_QUIRK_LEN          (64)
-#define X(r)                   (r)->g.x
-#define Y(r)                   (r)->g.y
-#define WIDTH(r)               (r)->g.w
-#define HEIGHT(r)              (r)->g.h
-#define SH_MIN(w)              (w)->sh_mask & PMinSize
-#define SH_MIN_W(w)            (w)->sh.min_width
-#define SH_MIN_H(w)            (w)->sh.min_height
-#define SH_MAX(w)              (w)->sh_mask & PMaxSize
-#define SH_MAX_W(w)            (w)->sh.max_width
-#define SH_MAX_H(w)            (w)->sh.max_height
-#define SH_INC(w)              (w)->sh_mask & PResizeInc
-#define SH_INC_W(w)            (w)->sh.width_inc
-#define SH_INC_H(w)            (w)->sh.height_inc
-#define SWM_MAX_FONT_STEPS     (3)
-#define WINID(w)               ((w) ? (w)->id : 0)
-#define YESNO(x)               ((x) ? "yes" : "no")
-
-#define SWM_FOCUS_DEFAULT      (0)
-#define SWM_FOCUS_SYNERGY      (1)
-#define SWM_FOCUS_FOLLOW       (2)
-
-#define SWM_CONF_DEFAULT       (0)
-#define SWM_CONF_KEYMAPPING    (1)
-
-#ifndef SWM_LIB
-#define SWM_LIB                        "/usr/local/lib/libswmhack.so"
-#endif
-
-char                   **start_argv;
-Atom                   astate;
-Atom                   aprot;
-Atom                   adelete;
-Atom                   takefocus;
-Atom                   a_wmname;
-Atom                   a_netwmname;
-Atom                   a_utf8_string;
-Atom                   a_string;
-Atom                   a_swm_iconic;
-volatile sig_atomic_t   running = 1;
-volatile sig_atomic_t   restart_wm = 0;
-int                    outputs = 0;
-int                    last_focus_event = FocusOut;
-int                    (*xerrorxlib)(Display *, XErrorEvent *);
-int                    other_wm;
-int                    ss_enabled = 0;
-int                    xrandr_support;
-int                    xrandr_eventbase;
-unsigned int           numlockmask = 0;
-Display                        *display;
-
-int                    cycle_empty = 0;
-int                    cycle_visible = 0;
-int                    term_width = 0;
-int                    font_adjusted = 0;
-unsigned int           mod_key = MODKEY;
-
-/* dmenu search */
-struct swm_region      *search_r;
-int                    select_list_pipe[2];
-int                    select_resp_pipe[2];
-pid_t                  searchpid;
-volatile sig_atomic_t  search_resp;
-int                    search_resp_action;
-
-struct search_window {
-       TAILQ_ENTRY(search_window)      entry;
-       int                             idx;
-       struct ws_win                   *win;
-       GC                              gc;
-       Window                          indicator;
-};
-TAILQ_HEAD(search_winlist, search_window);
-
-struct search_winlist search_wl;
-
-/* search actions */
-enum {
-       SWM_SEARCH_NONE,
-       SWM_SEARCH_UNICONIFY,
-       SWM_SEARCH_NAME_WORKSPACE,
-       SWM_SEARCH_SEARCH_WORKSPACE,
-       SWM_SEARCH_SEARCH_WINDOW
-};
-
-/* dialog windows */
-double                 dialog_ratio = 0.6;
-/* status bar */
-#define SWM_BAR_MAX            (256)
-#define SWM_BAR_JUSTIFY_LEFT   (0)
-#define SWM_BAR_JUSTIFY_CENTER (1)
-#define SWM_BAR_JUSTIFY_RIGHT  (2)
-#define SWM_BAR_OFFSET         (4)
-#define SWM_BAR_FONTS          "-*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*," \
-                               "-*-profont-*-*-*-*-*-*-*-*-*-*-*-*,"       \
-                               "-*-times-medium-r-*-*-*-*-*-*-*-*-*-*,"    \
-                               "-misc-fixed-medium-r-*-*-*-*-*-*-*-*-*-*"
-
-#ifdef X_HAVE_UTF8_STRING
-#define DRAWSTRING(x...)       Xutf8DrawString(x)
-#else
-#define DRAWSTRING(x...)       XmbDrawString(x)
-#endif
-
-char                   *bar_argv[] = { NULL, NULL };
-int                    bar_pipe[2];
-unsigned char          bar_ext[SWM_BAR_MAX];
-char                   bar_vertext[SWM_BAR_MAX];
-int                    bar_version = 0;
-sig_atomic_t           bar_alarm = 0;
-int                    bar_delay = 30;
-int                    bar_enabled = 1;
-int                    bar_border_width = 1;
-int                    bar_at_bottom = 0;
-int                    bar_extra = 1;
-int                    bar_extra_running = 0;
-int                    bar_verbose = 1;
-int                    bar_height = 0;
-int                    bar_justify = SWM_BAR_JUSTIFY_LEFT;
-int                    stack_enabled = 1;
-int                    clock_enabled = 1;
-int                    urgent_enabled = 0;
-char                   *clock_format = NULL;
-int                    title_name_enabled = 0;
-int                    title_class_enabled = 0;
-int                    window_name_enabled = 0;
-int                    focus_mode = SWM_FOCUS_DEFAULT;
-int                    disable_border = 0;
-int                    border_width = 1;
-int                    verbose_layout = 0;
-pid_t                  bar_pid;
-XFontSet               bar_fs;
-XFontSetExtents                *bar_fs_extents;
-char                   *bar_fonts;
-char                   *spawn_term[] = { NULL, NULL }; /* XXX fully dynamic */
-struct passwd          *pwd;
-
-#define SWM_MENU_FN    (2)
-#define SWM_MENU_NB    (4)
-#define SWM_MENU_NF    (6)
-#define SWM_MENU_SB    (8)
-#define SWM_MENU_SF    (10)
-
-/* layout manager data */
-struct swm_geometry {
-       int                     x;
-       int                     y;
-       int                     w;
-       int                     h;
-};
-
-struct swm_screen;
-struct workspace;
-
-/* virtual "screens" */
-struct swm_region {
-       TAILQ_ENTRY(swm_region) entry;
-       struct swm_geometry     g;
-       struct workspace        *ws;    /* current workspace on this region */
-       struct workspace        *ws_prior; /* prior workspace on this region */
-       struct swm_screen       *s;     /* screen idx */
-       Window                  bar_window;
-};
-TAILQ_HEAD(swm_region_list, swm_region);
-
-struct ws_win {
-       TAILQ_ENTRY(ws_win)     entry;
-       Window                  id;
-       Window                  transient;
-       struct ws_win           *child_trans;   /* transient child window */
-       struct swm_geometry     g;              /* current geometry */
-       struct swm_geometry     g_float;        /* geometry when floating */
-       struct swm_geometry     rg_float;       /* region geom when floating */
-       int                     g_floatvalid;   /* g_float geometry validity */
-       int                     floatmaxed;     /* whether maxed by max_stack */
-       int                     floating;
-       int                     manual;
-       int                     iconic;
-       unsigned int            ewmh_flags;
-       int                     font_size_boundary[SWM_MAX_FONT_STEPS];
-       int                     font_steps;
-       int                     last_inc;
-       int                     can_delete;
-       int                     take_focus;
-       int                     java;
-       unsigned long           quirks;
-       struct workspace        *ws;    /* always valid */
-       struct swm_screen       *s;     /* always valid, never changes */
-       XWindowAttributes       wa;
-       XSizeHints              sh;
-       long                    sh_mask;
-       XClassHint              ch;
-       XWMHints                *hints;
-};
-TAILQ_HEAD(ws_win_list, ws_win);
-
-/* pid goo */
-struct pid_e {
-       TAILQ_ENTRY(pid_e)      entry;
-       long                    pid;
-       int                     ws;
-};
-TAILQ_HEAD(pid_list, pid_e);
-struct pid_list                        pidlist = TAILQ_HEAD_INITIALIZER(pidlist);
-
-/* layout handlers */
-void   stack(void);
-void   vertical_config(struct workspace *, int);
-void   vertical_stack(struct workspace *, struct swm_geometry *);
-void   horizontal_config(struct workspace *, int);
-void   horizontal_stack(struct workspace *, struct swm_geometry *);
-void   max_stack(struct workspace *, struct swm_geometry *);
-void   plain_stacker(struct workspace *);
-void   fancy_stacker(struct workspace *);
-
-struct ws_win *find_window(Window);
-
-void   grabbuttons(struct ws_win *, int);
-void   new_region(struct swm_screen *, int, int, int, int);
-void   unmanage_window(struct ws_win *);
-long   getstate(Window);
-
-int    conf_load(char *, int);
-
-struct layout {
-       void            (*l_stack)(struct workspace *, struct swm_geometry *);
-       void            (*l_config)(struct workspace *, int);
-       u_int32_t       flags;
-#define SWM_L_FOCUSPREV                (1<<0)
-#define SWM_L_MAPONFOCUS       (1<<1)
-       void            (*l_string)(struct workspace *);
-} layouts[] =  {
-       /* stack,               configure */
-       { vertical_stack,       vertical_config,        0,      plain_stacker },
-       { horizontal_stack,     horizontal_config,      0,      plain_stacker },
-       { max_stack,            NULL,
-         SWM_L_MAPONFOCUS | SWM_L_FOCUSPREV,                   plain_stacker },
-       { NULL,                 NULL,                   0,      NULL  },
-};
-
-/* position of max_stack mode in the layouts array, index into layouts! */
-#define SWM_V_STACK            (0)
-#define SWM_H_STACK            (1)
-#define SWM_MAX_STACK          (2)
-
-#define SWM_H_SLICE            (32)
-#define SWM_V_SLICE            (32)
-
-/* define work spaces */
-struct workspace {
-       int                     idx;            /* workspace index */
-       char                    *name;          /* workspace name */
-       int                     always_raise;   /* raise windows on focus */
-       struct layout           *cur_layout;    /* current layout handlers */
-       struct ws_win           *focus;         /* may be NULL */
-       struct ws_win           *focus_prev;    /* may be NULL */
-       struct swm_region       *r;             /* may be NULL */
-       struct swm_region       *old_r;         /* may be NULL */
-       struct ws_win_list      winlist;        /* list of windows in ws */
-       struct ws_win_list      unmanagedlist;  /* list of dead windows in ws */
-       char                    stacker[10];    /* display stacker and layout */
-
-       /* stacker state */
-       struct {
-                               int horizontal_msize;
-                               int horizontal_mwin;
-                               int horizontal_stacks;
-                               int horizontal_flip;
-                               int vertical_msize;
-                               int vertical_mwin;
-                               int vertical_stacks;
-                               int vertical_flip;
-       } l_state;
-};
-
-enum   { SWM_S_COLOR_BAR, SWM_S_COLOR_BAR_BORDER, SWM_S_COLOR_BAR_FONT,
-         SWM_S_COLOR_FOCUS, SWM_S_COLOR_UNFOCUS, SWM_S_COLOR_MAX };
-
-/* physical screen mapping */
-#define SWM_WS_MAX             (10)
-struct swm_screen {
-       int                     idx;    /* screen index */
-       struct swm_region_list  rl;     /* list of regions on this screen */
-       struct swm_region_list  orl;    /* list of old regions */
-       Window                  root;
-       struct workspace        ws[SWM_WS_MAX];
-
-       /* colors */
-       struct {
-               unsigned long   color;
-               char            *name;
-       } c[SWM_S_COLOR_MAX];
-
-       GC                      bar_gc;
-};
-struct swm_screen      *screens;
-int                    num_screens;
-
-/* args to functions */
-union arg {
-       int                     id;
-#define SWM_ARG_ID_FOCUSNEXT   (0)
-#define SWM_ARG_ID_FOCUSPREV   (1)
-#define SWM_ARG_ID_FOCUSMAIN   (2)
-#define SWM_ARG_ID_FOCUSCUR    (4)
-#define SWM_ARG_ID_SWAPNEXT    (10)
-#define SWM_ARG_ID_SWAPPREV    (11)
-#define SWM_ARG_ID_SWAPMAIN    (12)
-#define SWM_ARG_ID_MOVELAST    (13)
-#define SWM_ARG_ID_MASTERSHRINK (20)
-#define SWM_ARG_ID_MASTERGROW  (21)
-#define SWM_ARG_ID_MASTERADD   (22)
-#define SWM_ARG_ID_MASTERDEL   (23)
-#define SWM_ARG_ID_FLIPLAYOUT  (24)
-#define SWM_ARG_ID_STACKRESET  (30)
-#define SWM_ARG_ID_STACKINIT   (31)
-#define SWM_ARG_ID_CYCLEWS_UP  (40)
-#define SWM_ARG_ID_CYCLEWS_DOWN        (41)
-#define SWM_ARG_ID_CYCLESC_UP  (42)
-#define SWM_ARG_ID_CYCLESC_DOWN        (43)
-#define SWM_ARG_ID_CYCLEWS_UP_ALL      (44)
-#define SWM_ARG_ID_CYCLEWS_DOWN_ALL    (45)
-#define SWM_ARG_ID_STACKINC    (50)
-#define SWM_ARG_ID_STACKDEC    (51)
-#define SWM_ARG_ID_SS_ALL      (60)
-#define SWM_ARG_ID_SS_WINDOW   (61)
-#define SWM_ARG_ID_DONTCENTER  (70)
-#define SWM_ARG_ID_CENTER      (71)
-#define SWM_ARG_ID_KILLWINDOW  (80)
-#define SWM_ARG_ID_DELETEWINDOW        (81)
-#define SWM_ARG_ID_WIDTHGROW   (90)
-#define SWM_ARG_ID_WIDTHSHRINK (91)
-#define SWM_ARG_ID_HEIGHTGROW  (92)
-#define SWM_ARG_ID_HEIGHTSHRINK        (93)
-#define SWM_ARG_ID_MOVEUP      (100)
-#define SWM_ARG_ID_MOVEDOWN    (101)
-#define SWM_ARG_ID_MOVELEFT    (102)
-#define SWM_ARG_ID_MOVERIGHT   (103)
-       char                    **argv;
-};
-
-void   focus(struct swm_region *, union arg *);
-void   focus_magic(struct ws_win *);
-
-/* quirks */
-struct quirk {
-       TAILQ_ENTRY(quirk)      entry;
-       char                    *class;
-       char                    *name;
-       unsigned long           quirk;
-#define SWM_Q_FLOAT            (1<<0)  /* float this window */
-#define SWM_Q_TRANSSZ          (1<<1)  /* transiend window size too small */
-#define SWM_Q_ANYWHERE         (1<<2)  /* don't position this window */
-#define SWM_Q_XTERM_FONTADJ    (1<<3)  /* adjust xterm fonts when resizing */
-#define SWM_Q_FULLSCREEN       (1<<4)  /* remove border */
-#define SWM_Q_FOCUSPREV                (1<<5)  /* focus on caller */
-};
-TAILQ_HEAD(quirk_list, quirk);
-struct quirk_list              quirks = TAILQ_HEAD_INITIALIZER(quirks);
-
-/*
- * Supported EWMH hints should be added to
- * both the enum and the ewmh array
- */
-enum { _NET_ACTIVE_WINDOW, _NET_MOVERESIZE_WINDOW, _NET_CLOSE_WINDOW,
-    _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DOCK,
-    _NET_WM_WINDOW_TYPE_TOOLBAR, _NET_WM_WINDOW_TYPE_UTILITY,
-    _NET_WM_WINDOW_TYPE_SPLASH, _NET_WM_WINDOW_TYPE_DIALOG,
-    _NET_WM_WINDOW_TYPE_NORMAL, _NET_WM_STATE,
-    _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT,
-    _NET_WM_STATE_SKIP_TASKBAR, _NET_WM_STATE_SKIP_PAGER,
-    _NET_WM_STATE_HIDDEN, _NET_WM_STATE_ABOVE, _SWM_WM_STATE_MANUAL,
-    _NET_WM_STATE_FULLSCREEN, _NET_WM_ALLOWED_ACTIONS, _NET_WM_ACTION_MOVE,
-    _NET_WM_ACTION_RESIZE, _NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_CLOSE,
-    SWM_EWMH_HINT_MAX };
-
-struct ewmh_hint {
-       char    *name;
-       Atom     atom;
-} ewmh[SWM_EWMH_HINT_MAX] =    {
-    /* must be in same order as in the enum */
-    {"_NET_ACTIVE_WINDOW", None},
-    {"_NET_MOVERESIZE_WINDOW", None},
-    {"_NET_CLOSE_WINDOW", None},
-    {"_NET_WM_WINDOW_TYPE", None},
-    {"_NET_WM_WINDOW_TYPE_DOCK", None},
-    {"_NET_WM_WINDOW_TYPE_TOOLBAR", None},
-    {"_NET_WM_WINDOW_TYPE_UTILITY", None},
-    {"_NET_WM_WINDOW_TYPE_SPLASH", None},
-    {"_NET_WM_WINDOW_TYPE_DIALOG", None},
-    {"_NET_WM_WINDOW_TYPE_NORMAL", None},
-    {"_NET_WM_STATE", None},
-    {"_NET_WM_STATE_MAXIMIZED_HORZ", None},
-    {"_NET_WM_STATE_MAXIMIZED_VERT", None},
-    {"_NET_WM_STATE_SKIP_TASKBAR", None},
-    {"_NET_WM_STATE_SKIP_PAGER", None},
-    {"_NET_WM_STATE_HIDDEN", None},
-    {"_NET_WM_STATE_ABOVE", None},
-    {"_SWM_WM_STATE_MANUAL", None},
-    {"_NET_WM_STATE_FULLSCREEN", None},
-    {"_NET_WM_ALLOWED_ACTIONS", None},
-    {"_NET_WM_ACTION_MOVE", None},
-    {"_NET_WM_ACTION_RESIZE", None},
-    {"_NET_WM_ACTION_FULLSCREEN", None},
-    {"_NET_WM_ACTION_CLOSE", None},
-};
-
-void            store_float_geom(struct ws_win *, struct swm_region *);
-int             floating_toggle_win(struct ws_win *);
-void            spawn_select(struct swm_region *, union arg *, char *, int *);
-unsigned char  *get_win_name(Window);
-
-int
-get_property(Window id, Atom atom, long count, Atom type, unsigned long *nitems,
-    unsigned long *nbytes, unsigned char **data)
-{
-       int                     format, status;
-       unsigned long           *nbytes_ret, *nitems_ret;
-       unsigned long           nbytes_tmp, nitems_tmp;
-       Atom                    real;
-
-       nbytes_ret = nbytes != NULL ? nbytes : &nbytes_tmp;
-       nitems_ret = nitems != NULL ? nitems : &nitems_tmp;
-
-       status = XGetWindowProperty(display, id, atom, 0L, count, False, type,
-           &real, &format, nitems_ret, nbytes_ret, data);
-
-       if (status != Success)
-               return False;
-       if (real != type)
-               return False;
-
-       return True;
-}
-
-void
-update_iconic(struct ws_win *win, int newv)
-{
-       int32_t v = newv;
-       Atom iprop;
-
-       win->iconic = newv;
-
-       iprop = XInternAtom(display, "_SWM_ICONIC", False);
-       if (!iprop)
-               return;
-       if (newv)
-               XChangeProperty(display, win->id, iprop, XA_INTEGER, 32,
-                   PropModeReplace, (unsigned char *)&v, 1);
-       else
-               XDeleteProperty(display, win->id, iprop);
-}
-
-int
-get_iconic(struct ws_win *win)
-{
-       int32_t v = 0;
-       int retfmt, status;
-       Atom iprop, rettype;
-       unsigned long nitems, extra;
-       unsigned char *prop = NULL;
-
-       iprop = XInternAtom(display, "_SWM_ICONIC", False);
-       if (!iprop)
-               goto out;
-       status = XGetWindowProperty(display, win->id, iprop, 0L, 1L,
-           False, XA_INTEGER, &rettype, &retfmt, &nitems, &extra, &prop);
-       if (status != Success)
-               goto out;
-       if (rettype != XA_INTEGER || retfmt != 32)
-               goto out;
-       if (nitems != 1)
-               goto out;
-       v = *((int32_t *)prop);
-
-out:
-       if (prop != NULL)
-               XFree(prop);
-       return (v);
-}
-
-void
-setup_ewmh(void)
-{
-       int                     i,j;
-       Atom                    sup_list;
-
-       sup_list = XInternAtom(display, "_NET_SUPPORTED", False);
-
-       for (i = 0; i < LENGTH(ewmh); i++)
-               ewmh[i].atom = XInternAtom(display, ewmh[i].name, False);
-
-       for (i = 0; i < ScreenCount(display); i++) {
-               /* Support check window will be created by workaround(). */
-
-               /* Report supported atoms */
-               XDeleteProperty(display, screens[i].root, sup_list);
-               for (j = 0; j < LENGTH(ewmh); j++)
-                       XChangeProperty(display, screens[i].root,
-                           sup_list, XA_ATOM, 32,
-                           PropModeAppend, (unsigned char *)&ewmh[j].atom,1);
-       }
-}
-
-void
-teardown_ewmh(void)
-{
-       int                     i, success;
-       unsigned char           *data = NULL;
-       unsigned long           n;
-       Atom                    sup_check, sup_list;
-       Window                  id;
-
-       sup_check = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
-       sup_list = XInternAtom(display, "_NET_SUPPORTED", False);
-
-       for (i = 0; i < ScreenCount(display); i++) {
-               /* Get the support check window and destroy it */
-               success = get_property(screens[i].root, sup_check, 1, XA_WINDOW,
-                   &n, NULL, &data);
-
-               if (success) {
-                       id = data[0];
-                       XDestroyWindow(display, id);
-                       XDeleteProperty(display, screens[i].root, sup_check);
-                       XDeleteProperty(display, screens[i].root, sup_list);
-               }
-
-               XFree(data);
-       }
-}
-
-void
-ewmh_autoquirk(struct ws_win *win)
-{
-       int                     success, i;
-       unsigned long           *data = NULL, n;
-       Atom                    type;
-
-       success = get_property(win->id, ewmh[_NET_WM_WINDOW_TYPE].atom, (~0L),
-           XA_ATOM, &n, NULL, (void *)&data);
-
-       if (!success) {
-               XFree(data);
-               return;
-       }
-
-       for (i = 0; i < n; i++) {
-               type = data[i];
-               if (type == ewmh[_NET_WM_WINDOW_TYPE_NORMAL].atom)
-                       break;
-               if (type == ewmh[_NET_WM_WINDOW_TYPE_DOCK].atom ||
-                   type == ewmh[_NET_WM_WINDOW_TYPE_TOOLBAR].atom ||
-                   type == ewmh[_NET_WM_WINDOW_TYPE_UTILITY].atom) {
-                       win->floating = 1;
-                       win->quirks = SWM_Q_FLOAT | SWM_Q_ANYWHERE;
-                       break;
-               }
-               if (type == ewmh[_NET_WM_WINDOW_TYPE_SPLASH].atom ||
-                   type == ewmh[_NET_WM_WINDOW_TYPE_DIALOG].atom) {
-                       win->floating = 1;
-                       win->quirks = SWM_Q_FLOAT;
-                       break;
-               }
-       }
-
-       XFree(data);
-}
-
-#define SWM_EWMH_ACTION_COUNT_MAX      (6)
-#define EWMH_F_FULLSCREEN              (1<<0)
-#define EWMH_F_ABOVE                   (1<<1)
-#define EWMH_F_HIDDEN                  (1<<2)
-#define EWMH_F_SKIP_PAGER              (1<<3)
-#define EWMH_F_SKIP_TASKBAR            (1<<4)
-#define SWM_F_MANUAL                   (1<<5)
-
-int
-ewmh_set_win_fullscreen(struct ws_win *win, int fs)
-{
-       struct swm_geometry     rg;
-
-       if (!win->ws->r)
-               return 0;
-
-       if (!win->floating)
-               return 0;
-
-       DNPRINTF(SWM_D_MISC, "ewmh_set_win_fullscreen: window: 0x%lx, "
-           "fullscreen %s\n", win->id, YESNO(fs));
-
-       rg = win->ws->r->g;
-
-       if (fs) {
-               store_float_geom(win, win->ws->r);
-
-               win->g = rg;
-       } else {
-               if (win->g_floatvalid) {
-                       /* refloat at last floating relative position */
-                       X(win) = win->g_float.x - win->rg_float.x + rg.x;
-                       Y(win) = win->g_float.y - win->rg_float.y + rg.y;
-                       WIDTH(win) = win->g_float.w;
-                       HEIGHT(win) = win->g_float.h;
-               }
-       }
-
-       return 1;
-}
-
-void
-ewmh_update_actions(struct ws_win *win)
-{
-       Atom                    actions[SWM_EWMH_ACTION_COUNT_MAX];
-       int                     n = 0;
-
-       if (win == NULL)
-               return;
-
-       actions[n++] = ewmh[_NET_WM_ACTION_CLOSE].atom;
-
-       if (win->floating) {
-               actions[n++] = ewmh[_NET_WM_ACTION_MOVE].atom;
-               actions[n++] = ewmh[_NET_WM_ACTION_RESIZE].atom;
-       }
-
-       XChangeProperty(display, win->id, ewmh[_NET_WM_ALLOWED_ACTIONS].atom,
-           XA_ATOM, 32, PropModeReplace, (unsigned char *)actions, n);
-}
-
-#define _NET_WM_STATE_REMOVE   0    /* remove/unset property */
-#define _NET_WM_STATE_ADD      1    /* add/set property */
-#define _NET_WM_STATE_TOGGLE   2    /* toggle property */
-
-void
-ewmh_update_win_state(struct ws_win *win, long state, long action)
-{
-       unsigned int            mask = 0;
-       unsigned int            changed = 0;
-       unsigned int            orig_flags;
-
-       if (win == NULL)
-               return;
-
-       if (state == ewmh[_NET_WM_STATE_FULLSCREEN].atom)
-               mask = EWMH_F_FULLSCREEN;
-       if (state == ewmh[_NET_WM_STATE_ABOVE].atom)
-               mask = EWMH_F_ABOVE;
-       if (state == ewmh[_SWM_WM_STATE_MANUAL].atom)
-               mask = SWM_F_MANUAL;
-       if (state == ewmh[_NET_WM_STATE_SKIP_PAGER].atom)
-               mask = EWMH_F_SKIP_PAGER;
-       if (state == ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom)
-               mask = EWMH_F_SKIP_TASKBAR;
-
-
-       orig_flags = win->ewmh_flags;
-
-       switch (action) {
-       case _NET_WM_STATE_REMOVE:
-               win->ewmh_flags &= ~mask;
-               break;
-       case _NET_WM_STATE_ADD:
-               win->ewmh_flags |= mask;
-               break;
-       case _NET_WM_STATE_TOGGLE:
-               win->ewmh_flags ^= mask;
-               break;
-       }
-
-       changed = (win->ewmh_flags & mask) ^ (orig_flags & mask) ? 1 : 0;
-
-       if (state == ewmh[_NET_WM_STATE_ABOVE].atom)
-               if (changed)
-                       if (!floating_toggle_win(win))
-                               win->ewmh_flags = orig_flags; /* revert */
-       if (state == ewmh[_SWM_WM_STATE_MANUAL].atom)
-               if (changed)
-                       win->manual = (win->ewmh_flags & SWM_F_MANUAL) != 0;
-       if (state == ewmh[_NET_WM_STATE_FULLSCREEN].atom)
-               if (changed)
-                       if (!ewmh_set_win_fullscreen(win,
-                           win->ewmh_flags & EWMH_F_FULLSCREEN))
-                               win->ewmh_flags = orig_flags; /* revert */
-
-       XDeleteProperty(display, win->id, ewmh[_NET_WM_STATE].atom);
-
-       if (win->ewmh_flags & EWMH_F_FULLSCREEN)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_FULLSCREEN].atom, 1);
-       if (win->ewmh_flags & EWMH_F_SKIP_PAGER)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_SKIP_PAGER].atom, 1);
-       if (win->ewmh_flags & EWMH_F_SKIP_TASKBAR)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom, 1);
-       if (win->ewmh_flags & EWMH_F_ABOVE)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_NET_WM_STATE_ABOVE].atom, 1);
-       if (win->ewmh_flags & SWM_F_MANUAL)
-               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
-                   XA_ATOM, 32, PropModeAppend,
-                   (unsigned char *)&ewmh[_SWM_WM_STATE_MANUAL].atom, 1);
-}
-
-void
-ewmh_get_win_state(struct ws_win *win)
-{
-       int                     success, i;
-       unsigned long           n;
-       Atom                    *states;
-
-       if (win == NULL)
-               return;
-
-       win->ewmh_flags = 0;
-       if (win->floating)
-               win->ewmh_flags |= EWMH_F_ABOVE;
-       if (win->manual)
-               win->ewmh_flags |= SWM_F_MANUAL;
-
-       success = get_property(win->id, ewmh[_NET_WM_STATE].atom,
-           (~0L), XA_ATOM, &n, NULL, (void *)&states);
-
-       if (!success)
-               return;
-
-       for (i = 0; i < n; i++)
-               ewmh_update_win_state(win, states[i], _NET_WM_STATE_ADD);
-
-       XFree(states);
-}
-
-/* events */
-#ifdef SWM_DEBUG
-char *
-geteventname(XEvent *e)
-{
-       char                    *name = NULL;
-
-       switch (e->type) {
-       case KeyPress:
-               name = "KeyPress";
-               break;
-       case KeyRelease:
-               name = "KeyRelease";
-               break;
-       case ButtonPress:
-               name = "ButtonPress";
-               break;
-       case ButtonRelease:
-               name = "ButtonRelease";
-               break;
-       case MotionNotify:
-               name = "MotionNotify";
-               break;
-       case EnterNotify:
-               name = "EnterNotify";
-               break;
-       case LeaveNotify:
-               name = "LeaveNotify";
-               break;
-       case FocusIn:
-               name = "FocusIn";
-               break;
-       case FocusOut:
-               name = "FocusOut";
-               break;
-       case KeymapNotify:
-               name = "KeymapNotify";
-               break;
-       case Expose:
-               name = "Expose";
-               break;
-       case GraphicsExpose:
-               name = "GraphicsExpose";
-               break;
-       case NoExpose:
-               name = "NoExpose";
-               break;
-       case VisibilityNotify:
-               name = "VisibilityNotify";
-               break;
-       case CreateNotify:
-               name = "CreateNotify";
-               break;
-       case DestroyNotify:
-               name = "DestroyNotify";
-               break;
-       case UnmapNotify:
-               name = "UnmapNotify";
-               break;
-       case MapNotify:
-               name = "MapNotify";
-               break;
-       case MapRequest:
-               name = "MapRequest";
-               break;
-       case ReparentNotify:
-               name = "ReparentNotify";
-               break;
-       case ConfigureNotify:
-               name = "ConfigureNotify";
-               break;
-       case ConfigureRequest:
-               name = "ConfigureRequest";
-               break;
-       case GravityNotify:
-               name = "GravityNotify";
-               break;
-       case ResizeRequest:
-               name = "ResizeRequest";
-               break;
-       case CirculateNotify:
-               name = "CirculateNotify";
-               break;
-       case CirculateRequest:
-               name = "CirculateRequest";
-               break;
-       case PropertyNotify:
-               name = "PropertyNotify";
-               break;
-       case SelectionClear:
-               name = "SelectionClear";
-               break;
-       case SelectionRequest:
-               name = "SelectionRequest";
-               break;
-       case SelectionNotify:
-               name = "SelectionNotify";
-               break;
-       case ColormapNotify:
-               name = "ColormapNotify";
-               break;
-       case ClientMessage:
-               name = "ClientMessage";
-               break;
-       case MappingNotify:
-               name = "MappingNotify";
-               break;
-       default:
-               name = "Unknown";
-       }
-
-       return name;
-}
-
-char *
-xrandr_geteventname(XEvent *e)
-{
-       char                    *name = NULL;
-
-       switch(e->type - xrandr_eventbase) {
-       case RRScreenChangeNotify:
-               name = "RRScreenChangeNotify";
-               break;
-       default:
-               name = "Unknown";
-       }
-
-       return name;
-}
-
-void
-dumpwins(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *win;
-       unsigned int            state;
-       XWindowAttributes       wa;
-
-       if (r->ws == NULL) {
-               warnx("dumpwins: invalid workspace");
-               return;
-       }
-
-       warnx("=== managed window list ws %02d ===", r->ws->idx);
-
-       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
-               state = getstate(win->id);
-               if (!XGetWindowAttributes(display, win->id, &wa))
-                       warnx("window: 0x%lx, failed XGetWindowAttributes",
-                           win->id);
-               warnx("window: 0x%lx, map_state: %d, state: %d, "
-                   "transient: 0x%lx", win->id, wa.map_state, state,
-                   win->transient);
-       }
-
-       warnx("===== unmanaged window list =====");
-       TAILQ_FOREACH(win, &r->ws->unmanagedlist, entry) {
-               state = getstate(win->id);
-               if (!XGetWindowAttributes(display, win->id, &wa))
-                       warnx("window: 0x%lx, failed XGetWindowAttributes",
-                           win->id);
-               warnx("window: 0x%lx, map_state: %d, state: %d, "
-                   "transient: 0x%lx", win->id, wa.map_state, state,
-                   win->transient);
-       }
-
-       warnx("=================================");
-}
-#else
-void
-dumpwins(struct swm_region *r, union arg *args)
-{
-}
-#endif /* SWM_DEBUG */
-
-void                   expose(XEvent *);
-void                   keypress(XEvent *);
-void                   buttonpress(XEvent *);
-void                   configurerequest(XEvent *);
-void                   configurenotify(XEvent *);
-void                   destroynotify(XEvent *);
-void                   enternotify(XEvent *);
-void                   focusevent(XEvent *);
-void                   mapnotify(XEvent *);
-void                   mappingnotify(XEvent *);
-void                   maprequest(XEvent *);
-void                   propertynotify(XEvent *);
-void                   unmapnotify(XEvent *);
-void                   visibilitynotify(XEvent *);
-void                   clientmessage(XEvent *);
-
-void                   (*handler[LASTEvent])(XEvent *) = {
-                               [Expose] = expose,
-                               [KeyPress] = keypress,
-                               [ButtonPress] = buttonpress,
-                               [ConfigureRequest] = configurerequest,
-                               [ConfigureNotify] = configurenotify,
-                               [DestroyNotify] = destroynotify,
-                               [EnterNotify] = enternotify,
-                               [FocusIn] = focusevent,
-                               [FocusOut] = focusevent,
-                               [MapNotify] = mapnotify,
-                               [MappingNotify] = mappingnotify,
-                               [MapRequest] = maprequest,
-                               [PropertyNotify] = propertynotify,
-                               [UnmapNotify] = unmapnotify,
-                               [VisibilityNotify] = visibilitynotify,
-                               [ClientMessage] = clientmessage,
-};
-
-void
-sighdlr(int sig)
-{
-       int                     saved_errno, status;
-       pid_t                   pid;
-
-       saved_errno = errno;
-
-       switch (sig) {
-       case SIGCHLD:
-               while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) != 0) {
-                       if (pid == -1) {
-                               if (errno == EINTR)
-                                       continue;
-#ifdef SWM_DEBUG
-                               if (errno != ECHILD)
-                                       warn("sighdlr: waitpid");
-#endif /* SWM_DEBUG */
-                               break;
-                       }
-                       if (pid == searchpid)
-                               search_resp = 1;
-
-#ifdef SWM_DEBUG
-                       if (WIFEXITED(status)) {
-                               if (WEXITSTATUS(status) != 0)
-                                       warnx("sighdlr: child exit status: %d",
-                                           WEXITSTATUS(status));
-                       } else
-                               warnx("sighdlr: child is terminated "
-                                   "abnormally");
-#endif /* SWM_DEBUG */
-               }
-               break;
-
-       case SIGHUP:
-               restart_wm = 1;
-               break;
-       case SIGINT:
-       case SIGTERM:
-       case SIGQUIT:
-               running = 0;
-               break;
-       }
-
-       errno = saved_errno;
-}
-
-struct pid_e *
-find_pid(long pid)
-{
-       struct pid_e            *p = NULL;
-
-       DNPRINTF(SWM_D_MISC, "find_pid: %lu\n", pid);
-
-       if (pid == 0)
-               return (NULL);
-
-       TAILQ_FOREACH(p, &pidlist, entry) {
-               if (p->pid == pid)
-                       return (p);
-       }
-
-       return (NULL);
-}
-
-unsigned long
-name_to_color(char *colorname)
-{
-       Colormap                cmap;
-       Status                  status;
-       XColor                  screen_def, exact_def;
-       unsigned long           result = 0;
-       char                    cname[32] = "#";
-
-       cmap = DefaultColormap(display, screens[0].idx);
-       status = XAllocNamedColor(display, cmap, colorname,
-           &screen_def, &exact_def);
-       if (!status) {
-               strlcat(cname, colorname + 2, sizeof cname - 1);
-               status = XAllocNamedColor(display, cmap, cname, &screen_def,
-                   &exact_def);
-       }
-       if (status)
-               result = screen_def.pixel;
-       else
-               warnx("color '%s' not found", colorname);
-
-       return (result);
-}
-
-void
-setscreencolor(char *val, int i, int c)
-{
-       if (i > 0 && i <= ScreenCount(display)) {
-               screens[i - 1].c[c].color = name_to_color(val);
-               free(screens[i - 1].c[c].name);
-               if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
-                       err(1, "strdup");
-       } else if (i == -1) {
-               for (i = 0; i < ScreenCount(display); i++) {
-                       screens[i].c[c].color = name_to_color(val);
-                       free(screens[i].c[c].name);
-                       if ((screens[i].c[c].name = strdup(val)) == NULL)
-                               err(1, "strdup");
-               }
-       } else
-               errx(1, "invalid screen index: %d out of bounds (maximum %d)",
-                   i, ScreenCount(display));
-}
-
-void
-fancy_stacker(struct workspace *ws)
-{
-       strlcpy(ws->stacker, "[   ]", sizeof ws->stacker);
-       if (ws->cur_layout->l_stack == vertical_stack)
-               snprintf(ws->stacker, sizeof ws->stacker,
-                   ws->l_state.vertical_flip ? "[%d>%d]" : "[%d|%d]",
-                   ws->l_state.vertical_mwin, ws->l_state.vertical_stacks);
-       if (ws->cur_layout->l_stack == horizontal_stack)
-               snprintf(ws->stacker, sizeof ws->stacker,
-                   ws->l_state.horizontal_flip ? "[%dv%d]" : "[%d-%d]",
-                   ws->l_state.horizontal_mwin, ws->l_state.horizontal_stacks);
-}
-
-void
-plain_stacker(struct workspace *ws)
-{
-       strlcpy(ws->stacker, "[ ]", sizeof ws->stacker);
-       if (ws->cur_layout->l_stack == vertical_stack)
-               strlcpy(ws->stacker, ws->l_state.vertical_flip ? "[>]" : "[|]",
-                   sizeof ws->stacker);
-       if (ws->cur_layout->l_stack == horizontal_stack)
-               strlcpy(ws->stacker, ws->l_state.horizontal_flip ? "[v]" : "[-]",
-                   sizeof ws->stacker);
-}
-
-void
-custom_region(char *val)
-{
-       unsigned int                    sidx, x, y, w, h;
-
-       if (sscanf(val, "screen[%u]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5)
-               errx(1, "invalid custom region, "
-                   "should be 'screen[<n>]:<n>x<n>+<n>+<n>");
-       if (sidx < 1 || sidx > ScreenCount(display))
-               errx(1, "invalid screen index: %d out of bounds (maximum %d)",
-                   sidx, ScreenCount(display));
-       sidx--;
-
-       if (w < 1 || h < 1)
-               errx(1, "region %ux%u+%u+%u too small", w, h, x, y);
-
-       if (x > DisplayWidth(display, sidx) ||
-           y > DisplayHeight(display, sidx) ||
-           w + x > DisplayWidth(display, sidx) ||
-           h + y > DisplayHeight(display, sidx)) {
-               warnx("ignoring region %ux%u+%u+%u - not within screen "
-                   "boundaries (%ux%u)", w, h, x, y,
-                   DisplayWidth(display, sidx), DisplayHeight(display, sidx));
-               return;
-       }
-
-       new_region(&screens[sidx], x, y, w, h);
-}
-
-void
-socket_setnonblock(int fd)
-{
-       int                     flags;
-
-       if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
-               err(1, "fcntl F_GETFL");
-       flags |= O_NONBLOCK;
-       if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
-               err(1, "fcntl F_SETFL");
-}
-
-void
-bar_print(struct swm_region *r, char *s)
-{
-       int                     x = 0;
-       size_t                  len;
-       XRectangle              ibox, lbox;
-
-       XClearWindow(display, r->bar_window);
-
-       len = strlen(s);
-       XmbTextExtents(bar_fs, s, len, &ibox, &lbox);
-
-       switch (bar_justify) {
-       case SWM_BAR_JUSTIFY_LEFT:
-               x = SWM_BAR_OFFSET;
-               break;
-       case SWM_BAR_JUSTIFY_CENTER:
-               x = (WIDTH(r) - lbox.width) / 2;
-               break;
-       case SWM_BAR_JUSTIFY_RIGHT:
-               x = WIDTH(r) - lbox.width - SWM_BAR_OFFSET;
-               break;
-       }
-
-       if (x < SWM_BAR_OFFSET)
-               x = SWM_BAR_OFFSET;
-
-       DRAWSTRING(display, r->bar_window, bar_fs, r->s->bar_gc,
-           x, (bar_fs_extents->max_logical_extent.height - lbox.height) / 2 -
-           lbox.y, s, len);
-}
-
-void
-bar_extra_stop(void)
-{
-       if (bar_pipe[0]) {
-               close(bar_pipe[0]);
-               bzero(bar_pipe, sizeof bar_pipe);
-       }
-       if (bar_pid) {
-               kill(bar_pid, SIGTERM);
-               bar_pid = 0;
-       }
-       strlcpy((char *)bar_ext, "", sizeof bar_ext);
-       bar_extra = 0;
-}
-
-void
-bar_class_name(char *s, ssize_t sz, struct ws_win *cur_focus)
-{
-       int                     do_class, do_name;
-       Status                  status;
-       XClassHint              *xch = NULL;
-
-       if ((title_name_enabled == 1 || title_class_enabled == 1) &&
-           cur_focus != NULL) {
-               if ((xch = XAllocClassHint()) == NULL)
-                       goto out;
-               status = XGetClassHint(display, cur_focus->id, xch);
-               if (status == BadWindow || status == BadAlloc)
-                       goto out;
-               do_class = (title_class_enabled && xch->res_class != NULL);
-               do_name = (title_name_enabled && xch->res_name != NULL);
-               if (do_class)
-                       strlcat(s, xch->res_class, sz);
-               if (do_class && do_name)
-                       strlcat(s, ":", sz);
-               if (do_name)
-                       strlcat(s, xch->res_name, sz);
-               strlcat(s, "    ", sz);
-       }
-out:
-       if (xch) {
-               XFree(xch->res_name);
-               XFree(xch->res_class);
-               XFree(xch);
-       }
-}
-
-void
-bar_window_name(char *s, ssize_t sz, struct ws_win *cur_focus)
-{
-       unsigned char           *title;
-
-       if (window_name_enabled && cur_focus != NULL) {
-               title = get_win_name(cur_focus->id);
-               if (title != NULL) {
-                       DNPRINTF(SWM_D_BAR, "bar_window_name: title: %s\n",
-                           title);
-
-                       if (cur_focus->floating)
-                               strlcat(s, "(f) ", sz);
-                       strlcat(s, (char *)title, sz);
-                       strlcat(s, " ", sz);
-                       XFree(title);
-               }
-       }
-}
-
-int            urgent[SWM_WS_MAX];
-void
-bar_urgent(char *s, ssize_t sz)
-{
-       XWMHints                *wmh = NULL;
-       struct ws_win           *win;
-       int                     i, j;
-       char                    b[8];
-
-       if (urgent_enabled == 0)
-               return;
-
-       for (i = 0; i < SWM_WS_MAX; i++)
-               urgent[i] = 0;
-
-       for (i = 0; i < ScreenCount(display); i++)
-               for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
-                               wmh = XGetWMHints(display, win->id);
-                               if (wmh == NULL)
-                                       continue;
-
-                               if (wmh->flags & XUrgencyHint)
-                                       urgent[j] = 1;
-                               XFree(wmh);
-                       }
-
-       strlcat(s, "* ", sz);
-       for (i = 0; i < SWM_WS_MAX; i++) {
-               if (urgent[i])
-                       snprintf(b, sizeof b, "%d ", i + 1);
-               else
-                       snprintf(b, sizeof b, "- ");
-               strlcat(s, b, sz);
-       }
-       strlcat(s, "*    ", sz);
-}
-
-void
-bar_update(void)
-{
-       time_t                  tmt;
-       struct tm               tm;
-       struct swm_region       *r;
-       int                     i, x;
-       size_t                  len;
-       char                    ws[SWM_BAR_MAX];
-       char                    s[SWM_BAR_MAX];
-       unsigned char           cn[SWM_BAR_MAX];
-       char                    loc[SWM_BAR_MAX];
-       char                    *b, *stack = "";
-
-       if (bar_enabled == 0)
-               return;
-       if (bar_extra && bar_extra_running) {
-               /* ignore short reads; it'll correct itself */
-               while ((b = fgetln(stdin, &len)) != NULL)
-                       if (b && b[len - 1] == '\n') {
-                               b[len - 1] = '\0';
-                               strlcpy((char *)bar_ext, b, sizeof bar_ext);
-                       }
-               if (b == NULL && errno != EAGAIN) {
-                       warn("bar_update: bar_extra failed");
-                       bar_extra_stop();
-               }
-       } else
-               strlcpy((char *)bar_ext, "", sizeof bar_ext);
-
-       if (clock_enabled == 0)
-               strlcpy(s, "", sizeof s);
-       else {
-               time(&tmt);
-               localtime_r(&tmt, &tm);
-               len = strftime(s, sizeof s, clock_format, &tm);
-               s[len] = '\0';
-               strlcat(s, "    ", sizeof s);
-       }
-
-       for (i = 0; i < ScreenCount(display); i++) {
-               x = 1;
-               TAILQ_FOREACH(r, &screens[i].rl, entry) {
-                       strlcpy((char *)cn, "", sizeof cn);
-                       strlcpy(ws, "", sizeof ws);
-                       if (r && r->ws) {
-                               bar_urgent((char *)cn, sizeof cn);
-                               bar_class_name((char *)cn, sizeof cn,
-                                   r->ws->focus);
-                               bar_window_name((char *)cn, sizeof cn,
-                                   r->ws->focus);
-                               if (r->ws->name)
-                                       snprintf(ws, sizeof ws, "<%s>",
-                                           r->ws->name);
-                       }
-                       if (stack_enabled)
-                               stack = r->ws->stacker;
-
-                       snprintf(loc, sizeof loc, "%d:%d %s %s   %s%s    %s    "
-                           "%s", x++, r->ws->idx + 1, stack, ws, s, cn,
-                           bar_ext, bar_vertext);
-                       bar_print(r, loc);
-               }
-       }
-       alarm(bar_delay);
-}
-
-void
-bar_check_opts(void)
-{
-       if (title_class_enabled || title_name_enabled || window_name_enabled)
-               bar_update();
-}
-
-void
-bar_signal(int sig)
-{
-       bar_alarm = 1;
-}
-
-void
-bar_toggle(struct swm_region *r, union arg *args)
-{
-       struct swm_region       *tmpr;
-       int                     i, sc = ScreenCount(display);
-
-       DNPRINTF(SWM_D_BAR, "bar_toggle\n");
-
-       if (bar_enabled)
-               for (i = 0; i < sc; i++)
-                       TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
-                               XUnmapWindow(display, tmpr->bar_window);
-       else
-               for (i = 0; i < sc; i++)
-                       TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
-                               XMapRaised(display, tmpr->bar_window);
-
-       bar_enabled = !bar_enabled;
-
-       stack();
-       /* must be after stack */
-       bar_update();
-}
-
-void
-bar_refresh(void)
-{
-       XSetWindowAttributes    wa;
-       struct swm_region       *r;
-       int                     i;
-
-       /* do this here because the conf file is in memory */
-       if (bar_extra && bar_extra_running == 0 && bar_argv[0]) {
-               /* launch external status app */
-               bar_extra_running = 1;
-               if (pipe(bar_pipe) == -1)
-                       err(1, "pipe error");
-               socket_setnonblock(bar_pipe[0]);
-               socket_setnonblock(bar_pipe[1]); /* XXX hmmm, really? */
-               if (dup2(bar_pipe[0], 0) == -1)
-                       err(1, "dup2");
-               if (dup2(bar_pipe[1], 1) == -1)
-                       err(1, "dup2");
-               if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
-                       err(1, "could not disable SIGPIPE");
-               switch (bar_pid = fork()) {
-               case -1:
-                       err(1, "cannot fork");
-                       break;
-               case 0: /* child */
-                       close(bar_pipe[0]);
-                       execvp(bar_argv[0], bar_argv);
-                       err(1, "%s external app failed", bar_argv[0]);
-                       break;
-               default: /* parent */
-                       close(bar_pipe[1]);
-                       break;
-               }
-       }
-
-       bzero(&wa, sizeof wa);
-       for (i = 0; i < ScreenCount(display); i++)
-               TAILQ_FOREACH(r, &screens[i].rl, entry) {
-                       wa.border_pixel =
-                           screens[i].c[SWM_S_COLOR_BAR_BORDER].color;
-                       wa.background_pixel =
-                           screens[i].c[SWM_S_COLOR_BAR].color;
-                       XChangeWindowAttributes(display, r->bar_window,
-                           CWBackPixel | CWBorderPixel, &wa);
-               }
-       bar_update();
-}
-
-void
-bar_setup(struct swm_region *r)
-{
-       char                    *default_string;
-       char                    **missing_charsets;
-       int                     num_missing_charsets = 0;
-       int                     i, x, y;
-
-       if (bar_fs) {
-               XFreeFontSet(display, bar_fs);
-               bar_fs = NULL;
-       }
-
-
-       DNPRINTF(SWM_D_BAR, "bar_setup: loading bar_fonts: %s\n", bar_fonts);
-
-       bar_fs = XCreateFontSet(display, bar_fonts, &missing_charsets,
-           &num_missing_charsets, &default_string);
-
-       if (num_missing_charsets > 0) {
-               warnx("Unable to load charset(s):");
-
-               for (i = 0; i < num_missing_charsets; ++i)
-                       warnx("%s", missing_charsets[i]);
-
-               XFreeStringList(missing_charsets);
-
-               if (strcmp(default_string, ""))
-                       warnx("Glyphs from those sets will be replaced "
-                           "by '%s'.", default_string);
-               else
-                       warnx("Glyphs from those sets won't be drawn.");
-       }
-
-       if (bar_fs == NULL)
-               errx(1, "Error creating font set structure.");
-
-       bar_fs_extents = XExtentsOfFontSet(bar_fs);
-
-       bar_height = bar_fs_extents->max_logical_extent.height +
-           2 * bar_border_width;
-
-       if (bar_height < 1)
-               bar_height = 1;
-
-       x = X(r);
-       y = bar_at_bottom ? (Y(r) + HEIGHT(r) - bar_height) : Y(r);
-
-       r->bar_window = XCreateSimpleWindow(display,
-           r->s->root, x, y, WIDTH(r) - 2 * bar_border_width,
-           bar_height - 2 * bar_border_width,
-           bar_border_width, r->s->c[SWM_S_COLOR_BAR_BORDER].color,
-           r->s->c[SWM_S_COLOR_BAR].color);
-       XSelectInput(display, r->bar_window, VisibilityChangeMask);
-       if (bar_enabled)
-               XMapRaised(display, r->bar_window);
-       DNPRINTF(SWM_D_BAR, "bar_setup: bar_window: 0x%lx\n", r->bar_window);
-
-       if (signal(SIGALRM, bar_signal) == SIG_ERR)
-               err(1, "could not install bar_signal");
-       bar_refresh();
-}
-
-void
-drain_enter_notify(void)
-{
-       int                     i = 0;
-       XEvent                  cne;
-
-       while (XCheckMaskEvent(display, EnterWindowMask, &cne))
-               i++;
-
-       DNPRINTF(SWM_D_MISC, "drain_enter_notify: drained: %d\n", i);
-}
-
-void
-set_win_state(struct ws_win *win, long state)
-{
-       long                    data[] = {state, None};
-
-       DNPRINTF(SWM_D_EVENT, "set_win_state: window: 0x%lx\n", win->id);
-
-       if (win == NULL)
-               return;
-
-       XChangeProperty(display, win->id, astate, astate, 32, PropModeReplace,
-           (unsigned char *)data, 2);
-}
-
-long
-getstate(Window w)
-{
-       long                    result = -1;
-       unsigned char           *p = NULL;
-       unsigned long           n;
-
-       if (!get_property(w, astate, 2L, astate, &n, NULL, &p))
-               return (-1);
-       if (n != 0)
-               result = *((long *)p);
-       XFree(p);
-       return (result);
-}
-
-void
-version(struct swm_region *r, union arg *args)
-{
-       bar_version = !bar_version;
-       if (bar_version)
-               snprintf(bar_vertext, sizeof bar_vertext,
-                   "Version: %s Build: %s", SCROTWM_VERSION, buildstr);
-       else
-               strlcpy(bar_vertext, "", sizeof bar_vertext);
-       bar_update();
-}
-
-void
-client_msg(struct ws_win *win, Atom a)
-{
-       XClientMessageEvent     cm;
-
-       if (win == NULL)
-               return;
-
-       bzero(&cm, sizeof cm);
-       cm.type = ClientMessage;
-       cm.window = win->id;
-       cm.message_type = aprot;
-       cm.format = 32;
-       cm.data.l[0] = a;
-       cm.data.l[1] = CurrentTime;
-       XSendEvent(display, win->id, False, 0L, (XEvent *)&cm);
-}
-
-/* synthetic response to a ConfigureRequest when not making a change */
-void
-config_win(struct ws_win *win, XConfigureRequestEvent  *ev)
-{
-       XConfigureEvent         ce;
-
-       if (win == NULL)
-               return;
-
-       /* send notification of unchanged state. */
-       ce.type = ConfigureNotify;
-       ce.x = X(win);
-       ce.y = Y(win);
-       ce.width = WIDTH(win);
-       ce.height = HEIGHT(win);
-       ce.override_redirect = False;
-
-       if (ev == NULL) {
-               /* EWMH */
-               ce.display = display;
-               ce.event = win->id;
-               ce.window = win->id;
-               ce.border_width = border_width;
-               ce.above = None;
-       } else {
-               /* normal */
-               ce.display = ev->display;
-               ce.event = ev->window;
-               ce.window = ev->window;
-
-               /* make response appear more WM_SIZE_HINTS-compliant */
-               if (win->sh_mask)
-                       DNPRINTF(SWM_D_MISC, "config_win: hints: window: 0x%lx,"
-                           " sh_mask: %ld, min: %d x %d, max: %d x %d, inc: "
-                           "%d x %d\n", win->id, win->sh_mask, SH_MIN_W(win),
-                           SH_MIN_H(win), SH_MAX_W(win), SH_MAX_H(win),
-                           SH_INC_W(win), SH_INC_H(win));
-
-               /* min size */
-               if (SH_MIN(win)) {
-                       /* the hint may be set... to 0! */
-                       if (SH_MIN_W(win) > 0 && ce.width < SH_MIN_W(win))
-                               ce.width = SH_MIN_W(win);
-                       if (SH_MIN_H(win) > 0 && ce.height < SH_MIN_H(win))
-                               ce.height = SH_MIN_H(win);
-               }
-
-               /* max size */
-               if (SH_MAX(win)) {
-                       /* may also be advertized as 0 */
-                       if (SH_MAX_W(win) > 0 && ce.width > SH_MAX_W(win))
-                               ce.width = SH_MAX_W(win);
-                       if (SH_MAX_H(win) > 0 && ce.height > SH_MAX_H(win))
-                               ce.height = SH_MAX_H(win);
-               }
-
-               /* resize increment. */
-               if (SH_INC(win)) {
-                       if (SH_INC_W(win) > 1 && ce.width > SH_INC_W(win))
-                               ce.width -= (ce.width - SH_MIN_W(win)) %
-                                   SH_INC_W(win);
-                       if (SH_INC_H(win) > 1 && ce.height > SH_INC_H(win))
-                               ce.height -= (ce.height - SH_MIN_H(win)) %
-                                   SH_INC_H(win);
-               }
-
-               /* adjust x and y for requested border_width. */
-               ce.x += border_width - ev->border_width;
-               ce.y += border_width - ev->border_width;
-               ce.border_width = ev->border_width;
-               ce.above = ev->above;
-       }
-
-       DNPRINTF(SWM_D_MISC, "config_win: ewmh: %s, window: 0x%lx, (x,y) w x h: "
-           "(%d,%d) %d x %d, border: %d\n", YESNO(ev == NULL), win->id, ce.x,
-           ce.y, ce.width, ce.height, ce.border_width);
-
-       XSendEvent(display, win->id, False, StructureNotifyMask, (XEvent *)&ce);
-}
-
-int
-count_win(struct workspace *ws, int count_transient)
-{
-       struct ws_win           *win;
-       int                     count = 0;
-
-       TAILQ_FOREACH(win, &ws->winlist, entry) {
-               if (count_transient == 0 && win->floating)
-                       continue;
-               if (count_transient == 0 && win->transient)
-                       continue;
-               if (win->iconic)
-                       continue;
-               count++;
-       }
-       DNPRINTF(SWM_D_MISC, "count_win: %d\n", count);
-
-       return (count);
-}
-
-void
-quit(struct swm_region *r, union arg *args)
-{
-       DNPRINTF(SWM_D_MISC, "quit\n");
-       running = 0;
-}
-
-void
-unmap_window(struct ws_win *win)
-{
-       if (win == NULL)
-               return;
-
-       /* don't unmap again */
-       if (getstate(win->id) == IconicState)
-               return;
-
-       set_win_state(win, IconicState);
-
-       XUnmapWindow(display, win->id);
-       XSetWindowBorder(display, win->id,
-           win->s->c[SWM_S_COLOR_UNFOCUS].color);
-}
-
-void
-unmap_all(void)
-{
-       struct ws_win           *win;
-       int                     i, j;
-
-       for (i = 0; i < ScreenCount(display); i++)
-               for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
-                               unmap_window(win);
-}
-
-void
-fake_keypress(struct ws_win *win, int keysym, int modifiers)
-{
-       XKeyEvent event;
-
-       if (win == NULL)
-               return;
-
-       event.display = display;        /* Ignored, but what the hell */
-       event.window = win->id;
-       event.root = win->s->root;
-       event.subwindow = None;
-       event.time = CurrentTime;
-       event.x = X(win);
-       event.y = Y(win);
-       event.x_root = 1;
-       event.y_root = 1;
-       event.same_screen = True;
-       event.keycode = XKeysymToKeycode(display, keysym);
-       event.state = modifiers;
-
-       event.type = KeyPress;
-       XSendEvent(event.display, event.window, True,
-           KeyPressMask, (XEvent *)&event);
-
-       event.type = KeyRelease;
-       XSendEvent(event.display, event.window, True,
-           KeyPressMask, (XEvent *)&event);
-
-}
-
-void
-restart(struct swm_region *r, union arg *args)
-{
-       DNPRINTF(SWM_D_MISC, "restart: %s\n", start_argv[0]);
-
-       /* disable alarm because the following code may not be interrupted */
-       alarm(0);
-       if (signal(SIGALRM, SIG_IGN) == SIG_ERR)
-               err(1, "can't disable alarm");
-
-       bar_extra_stop();
-       bar_extra = 1;
-       unmap_all();
-       XCloseDisplay(display);
-       execvp(start_argv[0], start_argv);
-       warn("execvp failed");
-       quit(NULL, NULL);
-}
-
-struct swm_region *
-root_to_region(Window root)
-{
-       struct swm_region       *r = NULL;
-       Window                  rr, cr;
-       int                     i, x, y, wx, wy;
-       unsigned int            mask;
-
-       for (i = 0; i < ScreenCount(display); i++)
-               if (screens[i].root == root)
-                       break;
-
-       if (XQueryPointer(display, screens[i].root,
-           &rr, &cr, &x, &y, &wx, &wy, &mask) != False) {
-               /* choose a region based on pointer location */
-               TAILQ_FOREACH(r, &screens[i].rl, entry)
-                       if (x >= X(r) && x <= X(r) + WIDTH(r) &&
-                           y >= Y(r) && y <= Y(r) + HEIGHT(r))
-                               break;
-       }
-
-       if (r == NULL)
-               r = TAILQ_FIRST(&screens[i].rl);
-
-       return (r);
-}
-
-struct ws_win *
-find_unmanaged_window(Window id)
-{
-       struct ws_win           *win;
-       int                     i, j;
-
-       for (i = 0; i < ScreenCount(display); i++)
-               for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].unmanagedlist,
-                           entry)
-                               if (id == win->id)
-                                       return (win);
-       return (NULL);
-}
-
-struct ws_win *
-find_window(Window id)
-{
-       struct ws_win           *win;
-       Window                  wrr, wpr, *wcr = NULL;
-       int                     i, j;
-       unsigned int            nc;
-
-       for (i = 0; i < ScreenCount(display); i++)
-               for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
-                               if (id == win->id)
-                                       return (win);
-
-       /* if we were looking for the parent return that window instead */
-       if (XQueryTree(display, id, &wrr, &wpr, &wcr, &nc) == 0)
-               return (NULL);
-       if (wcr)
-               XFree(wcr);
-
-       /* ignore not found and root */
-       if (wpr == 0 || wrr == wpr)
-               return (NULL);
-
-       /* look for parent */
-       for (i = 0; i < ScreenCount(display); i++)
-               for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
-                               if (wpr == win->id)
-                                       return (win);
-
-       return (NULL);
-}
-
-void
-spawn(int ws_idx, union arg *args, int close_fd)
-{
-       int                     fd;
-       char                    *ret = NULL;
-
-       DNPRINTF(SWM_D_MISC, "spawn: %s\n", args->argv[0]);
-
-       if (display)
-               close(ConnectionNumber(display));
-
-       setenv("LD_PRELOAD", SWM_LIB, 1);
-
-       if (asprintf(&ret, "%d", ws_idx) == -1) {
-               warn("spawn: asprintf SWM_WS");
-               _exit(1);
-       }
-       setenv("_SWM_WS", ret, 1);
-       free(ret);
-       ret = NULL;
-
-       if (asprintf(&ret, "%d", getpid()) == -1) {
-               warn("spawn: asprintf _SWM_PID");
-               _exit(1);
-       }
-       setenv("_SWM_PID", ret, 1);
-       free(ret);
-       ret = NULL;
-
-       if (setsid() == -1) {
-               warn("spawn: setsid");
-               _exit(1);
-       }
-
-       if (close_fd) {
-               /*
-                * close stdin and stdout to prevent interaction between apps
-                * and the baraction script
-                * leave stderr open to record errors
-               */
-               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) {
-                       warn("spawn: open");
-                       _exit(1);
-               }
-               dup2(fd, STDIN_FILENO);
-               dup2(fd, STDOUT_FILENO);
-               if (fd > 2)
-                       close(fd);
-       }
-
-       execvp(args->argv[0], args->argv);
-
-       warn("spawn: execvp");
-       _exit(1);
-}
-
-void
-spawnterm(struct swm_region *r, union arg *args)
-{
-       DNPRINTF(SWM_D_MISC, "spawnterm\n");
-
-       if (fork() == 0) {
-               if (term_width)
-                       setenv("_SWM_XTERM_FONTADJ", "", 1);
-               spawn(r->ws->idx, args, 1);
-       }
-}
-
-void
-kill_refs(struct ws_win *win)
-{
-       int                     i, x;
-       struct swm_region       *r;
-       struct workspace        *ws;
-
-       if (win == NULL)
-               return;
-
-       for (i = 0; i < ScreenCount(display); i++)
-               TAILQ_FOREACH(r, &screens[i].rl, entry)
-                       for (x = 0; x < SWM_WS_MAX; x++) {
-                               ws = &r->s->ws[x];
-                               if (win == ws->focus)
-                                       ws->focus = NULL;
-                               if (win == ws->focus_prev)
-                                       ws->focus_prev = NULL;
-                       }
-}
-
-int
-validate_win(struct ws_win *testwin)
-{
-       struct ws_win           *win;
-       struct workspace        *ws;
-       struct swm_region       *r;
-       int                     i, x;
-
-       if (testwin == NULL)
-               return (0);
-
-       for (i = 0; i < ScreenCount(display); i++)
-               TAILQ_FOREACH(r, &screens[i].rl, entry)
-                       for (x = 0; x < SWM_WS_MAX; x++) {
-                               ws = &r->s->ws[x];
-                               TAILQ_FOREACH(win, &ws->winlist, entry)
-                                       if (win == testwin)
-                                               return (0);
-                       }
-       return (1);
-}
-
-int
-validate_ws(struct workspace *testws)
-{
-       struct swm_region       *r;
-       struct workspace        *ws;
-       int                     i, x;
-
-       /* validate all ws */
-       for (i = 0; i < ScreenCount(display); i++)
-               TAILQ_FOREACH(r, &screens[i].rl, entry)
-                       for (x = 0; x < SWM_WS_MAX; x++) {
-                               ws = &r->s->ws[x];
-                               if (ws == testws)
-                                       return (0);
-                       }
-       return (1);
-}
-
-void
-unfocus_win(struct ws_win *win)
-{
-       XEvent                  cne;
-       Window                  none = None;
-
-       DNPRINTF(SWM_D_FOCUS, "unfocus_win: window: 0x%lx\n", WINID(win));
-
-       if (win == NULL)
-               return;
-       if (win->ws == NULL)
-               return;
-
-       if (validate_ws(win->ws))
-               return; /* XXX this gets hit with thunderbird, needs fixing */
-
-       if (win->ws->r == NULL)
-               return;
-
-       if (validate_win(win)) {
-               kill_refs(win);
-               return;
-       }
-
-       if (win->ws->focus == win) {
-               win->ws->focus = NULL;
-               win->ws->focus_prev = win;
-       }
-
-       if (validate_win(win->ws->focus)) {
-               kill_refs(win->ws->focus);
-               win->ws->focus = NULL;
-       }
-       if (validate_win(win->ws->focus_prev)) {
-               kill_refs(win->ws->focus_prev);
-               win->ws->focus_prev = NULL;
-       }
-
-       /* drain all previous unfocus events */
-       while (XCheckTypedEvent(display, FocusOut, &cne) == True)
-               ;
-
-       grabbuttons(win, 0);
-       XSetWindowBorder(display, win->id,
-           win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
-
-       XChangeProperty(display, win->s->root,
-           ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
-           PropModeReplace, (unsigned char *)&none,1);
-}
-
-void
-unfocus_all(void)
-{
-       struct ws_win           *win;
-       int                     i, j;
-
-       DNPRINTF(SWM_D_FOCUS, "unfocus_all\n");
-
-       for (i = 0; i < ScreenCount(display); i++)
-               for (j = 0; j < SWM_WS_MAX; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
-                               unfocus_win(win);
-}
-
-void
-focus_win(struct ws_win *win)
-{
-       XEvent                  cne;
-       Window                  cur_focus;
-       int                     rr;
-       struct ws_win           *cfw = NULL;
-
-
-       DNPRINTF(SWM_D_FOCUS, "focus_win: window: 0x%lx\n", WINID(win));
-
-       if (win == NULL)
-               return;
-       if (win->ws == NULL)
-               return;
-
-       if (validate_ws(win->ws))
-               return; /* XXX this gets hit with thunderbird, needs fixing */
-
-       if (validate_win(win)) {
-               kill_refs(win);
-               return;
-       }
-
-       if (validate_win(win)) {
-               kill_refs(win);
-               return;
-       }
-
-       XGetInputFocus(display, &cur_focus, &rr);
-       if ((cfw = find_window(cur_focus)) != NULL)
-               unfocus_win(cfw);
-       else {
-               /* use larger hammer since the window was killed somehow */
-               TAILQ_FOREACH(cfw, &win->ws->winlist, entry)
-                       if (cfw->ws && cfw->ws->r && cfw->ws->r->s)
-                               XSetWindowBorder(display, cfw->id,
-                                   cfw->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
-       }
-
-       win->ws->focus = win;
-
-       if (win->ws->r != NULL) {
-               /* drain all previous focus events */
-               while (XCheckTypedEvent(display, FocusIn, &cne) == True)
-                       ;
-
-               if (win->java == 0)
-                       XSetInputFocus(display, win->id,
-                           RevertToParent, CurrentTime);
-               grabbuttons(win, 1);
-               XSetWindowBorder(display, win->id,
-                   win->ws->r->s->c[SWM_S_COLOR_FOCUS].color);
-               if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
-                   win->ws->always_raise)
-                       XMapRaised(display, win->id);
-
-               XChangeProperty(display, win->s->root,
-                   ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
-                   PropModeReplace, (unsigned char *)&win->id,1);
-       }
-
-       bar_check_opts();
-}
-
-void
-switchws(struct swm_region *r, union arg *args)
-{
-       int                     wsid = args->id, unmap_old = 0;
-       struct swm_region       *this_r, *other_r;
-       struct ws_win           *win;
-       struct workspace        *new_ws, *old_ws;
-       union arg               a;
-
-       if (!(r && r->s))
-               return;
-
-       this_r = r;
-       old_ws = this_r->ws;
-       new_ws = &this_r->s->ws[wsid];
-
-       DNPRINTF(SWM_D_WS, "switchws: screen[%d]:%dx%d+%d+%d: %d -> %d\n",
-           r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), old_ws->idx, wsid);
-
-       if (new_ws == NULL || old_ws == NULL)
-               return;
-       if (new_ws == old_ws)
-               return;
-
-       other_r = new_ws->r;
-       if (other_r == NULL) {
-               /* the other workspace is hidden, hide this one */
-               old_ws->r = NULL;
-               unmap_old = 1;
-       } else {
-               /* the other ws is visible in another region, exchange them */
-               other_r->ws_prior = new_ws;
-               other_r->ws = old_ws;
-               old_ws->r = other_r;
-       }
-       this_r->ws_prior = old_ws;
-       this_r->ws = new_ws;
-       new_ws->r = this_r;
-
-       /* this is needed so that we can click on a window after a restart */
-       unfocus_all();
-
-       stack();
-       a.id = SWM_ARG_ID_FOCUSCUR;
-       focus(new_ws->r, &a);
-
-       bar_update();
-
-       /* unmap old windows */
-       if (unmap_old)
-               TAILQ_FOREACH(win, &old_ws->winlist, entry)
-                       unmap_window(win);
-
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-}
-
-void
-cyclews(struct swm_region *r, union arg *args)
-{
-       union                   arg a;
-       struct swm_screen       *s = r->s;
-       int                     cycle_all = 0;
-
-       DNPRINTF(SWM_D_WS, "cyclews: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
-           args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
-
-       a.id = r->ws->idx;
-       do {
-               switch (args->id) {
-               case SWM_ARG_ID_CYCLEWS_UP_ALL:
-                       cycle_all = 1;
-                       /* FALLTHROUGH */
-               case SWM_ARG_ID_CYCLEWS_UP:
-                       if (a.id < SWM_WS_MAX - 1)
-                               a.id++;
-                       else
-                               a.id = 0;
-                       break;
-               case SWM_ARG_ID_CYCLEWS_DOWN_ALL:
-                       cycle_all = 1;
-                       /* FALLTHROUGH */
-               case SWM_ARG_ID_CYCLEWS_DOWN:
-                       if (a.id > 0)
-                               a.id--;
-                       else
-                               a.id = SWM_WS_MAX - 1;
-                       break;
-               default:
-                       return;
-               };
-
-               if (!cycle_all &&
-                   (cycle_empty == 0 && TAILQ_EMPTY(&s->ws[a.id].winlist)))
-                       continue;
-               if (cycle_visible == 0 && s->ws[a.id].r != NULL)
-                       continue;
-
-               switchws(r, &a);
-       } while (a.id != r->ws->idx);
-}
-
-void
-priorws(struct swm_region *r, union arg *args)
-{
-       union arg               a;
-
-       DNPRINTF(SWM_D_WS, "priorws: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
-           args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
-
-       if (r->ws_prior == NULL)
-               return;
-
-       a.id = r->ws_prior->idx;
-       switchws(r, &a);
-}
-
-void
-cyclescr(struct swm_region *r, union arg *args)
-{
-       struct swm_region       *rr = NULL;
-       union arg               a;
-       int                     i, x, y;
-
-       /* do nothing if we don't have more than one screen */
-       if (!(ScreenCount(display) > 1 || outputs > 1))
-               return;
-
-       i = r->s->idx;
-       switch (args->id) {
-       case SWM_ARG_ID_CYCLESC_UP:
-               rr = TAILQ_NEXT(r, entry);
-               if (rr == NULL)
-                       rr = TAILQ_FIRST(&screens[i].rl);
-               break;
-       case SWM_ARG_ID_CYCLESC_DOWN:
-               rr = TAILQ_PREV(r, swm_region_list, entry);
-               if (rr == NULL)
-                       rr = TAILQ_LAST(&screens[i].rl, swm_region_list);
-               break;
-       default:
-               return;
-       };
-       if (rr == NULL)
-               return;
-
-       /* move mouse to region */
-       x = X(rr) + 1;
-       y = Y(rr) + 1 + (bar_enabled ? bar_height : 0);
-       XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, x, y);
-
-       a.id = SWM_ARG_ID_FOCUSCUR;
-       focus(rr, &a);
-
-       if (rr->ws->focus) {
-               /* move to focus window */
-               x = X(rr->ws->focus) + 1;
-               y = Y(rr->ws->focus) + 1;
-               XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, x, y);
-       }
-}
-
-void
-sort_windows(struct ws_win_list *wl)
-{
-       struct ws_win           *win, *parent, *nxt;
-
-       if (wl == NULL)
-               return;
-
-       for (win = TAILQ_FIRST(wl); win != TAILQ_END(wl); win = nxt) {
-               nxt = TAILQ_NEXT(win, entry);
-               if (win->transient) {
-                       parent = find_window(win->transient);
-                       if (parent == NULL) {
-                               warnx("not possible bug");
-                               continue;
-                       }
-                       TAILQ_REMOVE(wl, win, entry);
-                       TAILQ_INSERT_AFTER(wl, parent, win, entry);
-               }
-       }
-
-}
-
-void
-swapwin(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *target, *source;
-       struct ws_win           *cur_focus;
-       struct ws_win_list      *wl;
-
-
-       DNPRINTF(SWM_D_WS, "swapwin: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
-           args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
-
-       cur_focus = r->ws->focus;
-       if (cur_focus == NULL)
-               return;
-
-       source = cur_focus;
-       wl = &source->ws->winlist;
-
-       switch (args->id) {
-       case SWM_ARG_ID_SWAPPREV:
-               if (source->transient)
-                       source = find_window(source->transient);
-               target = TAILQ_PREV(source, ws_win_list, entry);
-               if (target && target->transient)
-                       target = find_window(target->transient);
-               TAILQ_REMOVE(wl, source, entry);
-               if (target == NULL)
-                       TAILQ_INSERT_TAIL(wl, source, entry);
-               else
-                       TAILQ_INSERT_BEFORE(target, source, entry);
-               break;
-       case SWM_ARG_ID_SWAPNEXT:
-               target = TAILQ_NEXT(source, entry);
-               /* move the parent and let the sort handle the move */
-               if (source->transient)
-                       source = find_window(source->transient);
-               TAILQ_REMOVE(wl, source, entry);
-               if (target == NULL)
-                       TAILQ_INSERT_HEAD(wl, source, entry);
-               else
-                       TAILQ_INSERT_AFTER(wl, target, source, entry);
-               break;
-       case SWM_ARG_ID_SWAPMAIN:
-               target = TAILQ_FIRST(wl);
-               if (target == source) {
-                       if (source->ws->focus_prev != NULL &&
-                           source->ws->focus_prev != target)
-
-                               source = source->ws->focus_prev;
-                       else
-                               return;
-               }
-               if (target == NULL || source == NULL)
-                       return;
-               source->ws->focus_prev = target;
-               TAILQ_REMOVE(wl, target, entry);
-               TAILQ_INSERT_BEFORE(source, target, entry);
-               TAILQ_REMOVE(wl, source, entry);
-               TAILQ_INSERT_HEAD(wl, source, entry);
-               break;
-       case SWM_ARG_ID_MOVELAST:
-               TAILQ_REMOVE(wl, source, entry);
-               TAILQ_INSERT_TAIL(wl, source, entry);
-               break;
-       default:
-               DNPRINTF(SWM_D_MOVE, "swapwin: invalid id: %d\n", args->id);
-               return;
-       }
-
-       sort_windows(wl);
-
-       stack();
-}
-
-void
-focus_prev(struct ws_win *win)
-{
-       struct ws_win           *winfocus = NULL;
-       struct ws_win           *cur_focus = NULL;
-       struct ws_win_list      *wl = NULL;
-       struct workspace        *ws = NULL;
-
-       DNPRINTF(SWM_D_FOCUS, "focus_prev: window: 0x%lx\n", WINID(win));
-
-       if (!(win && win->ws))
-               return;
-
-       ws = win->ws;
-       wl = &ws->winlist;
-       cur_focus = ws->focus;
-
-       /* pickle, just focus on whatever */
-       if (cur_focus == NULL) {
-               /* use prev_focus if valid */
-               if (ws->focus_prev && ws->focus_prev != cur_focus &&
-                   find_window(WINID(ws->focus_prev)))
-                       winfocus = ws->focus_prev;
-               if (winfocus == NULL)
-                       winfocus = TAILQ_FIRST(wl);
-               goto done;
-       }
-
-       /* if transient focus on parent */
-       if (cur_focus->transient) {
-               winfocus = find_window(cur_focus->transient);
-               goto done;
-       }
-
-       /* if in max_stack try harder */
-       if ((win->quirks & SWM_Q_FOCUSPREV) ||
-           (ws->cur_layout->flags & SWM_L_FOCUSPREV)) {
-               if (cur_focus != ws->focus_prev)
-                       winfocus = ws->focus_prev;
-               else if (cur_focus != ws->focus)
-                       winfocus = ws->focus;
-               else
-                       winfocus = TAILQ_PREV(win, ws_win_list, entry);
-               if (winfocus)
-                       goto done;
-       }
-
-       if (cur_focus == win)
-               winfocus = TAILQ_PREV(win, ws_win_list, entry);
-       if (winfocus == NULL)
-               winfocus = TAILQ_LAST(wl, ws_win_list);
-       if (winfocus == NULL || winfocus == win)
-               winfocus = TAILQ_NEXT(cur_focus, entry);
-
-done:
-       focus_magic(winfocus);
-}
-
-void
-focus(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *winfocus = NULL, *head;
-       struct ws_win           *cur_focus = NULL;
-       struct ws_win_list      *wl = NULL;
-       struct workspace        *ws = NULL;
-       int                     all_iconics;
-
-       if (!(r && r->ws))
-               return;
-
-       DNPRINTF(SWM_D_FOCUS, "focus: id: %d\n", args->id);
-
-       /* treat FOCUS_CUR special */
-       if (args->id == SWM_ARG_ID_FOCUSCUR) {
-               if (r->ws->focus && r->ws->focus->iconic == 0)
-                       winfocus = r->ws->focus;
-               else if (r->ws->focus_prev && r->ws->focus_prev->iconic == 0)
-                       winfocus = r->ws->focus_prev;
-               else
-                       TAILQ_FOREACH(winfocus, &r->ws->winlist, entry)
-                               if (winfocus->iconic == 0)
-                                       break;
-
-               focus_magic(winfocus);
-               return;
-       }
-
-       if ((cur_focus = r->ws->focus) == NULL)
-               return;
-       ws = r->ws;
-       wl = &ws->winlist;
-       if (TAILQ_EMPTY(wl))
-               return;
-       /* make sure there is at least one uniconified window */
-       all_iconics = 1;
-       TAILQ_FOREACH(winfocus, wl, entry)
-               if (winfocus->iconic == 0) {
-                       all_iconics = 0;
-                       break;
-               }
-       if (all_iconics)
-               return;
-
-       switch (args->id) {
-       case SWM_ARG_ID_FOCUSPREV:
-               head = TAILQ_PREV(cur_focus, ws_win_list, entry);
-               if (head == NULL)
-                       head = TAILQ_LAST(wl, ws_win_list);
-               winfocus = head;
-               if (WINID(winfocus) == cur_focus->transient) {
-                       head = TAILQ_PREV(winfocus, ws_win_list, entry);
-                       if (head == NULL)
-                               head = TAILQ_LAST(wl, ws_win_list);
-                       winfocus = head;
-               }
-
-               /* skip iconics */
-               if (winfocus && winfocus->iconic) {
-                       while (winfocus != cur_focus) {
-                               if (winfocus == NULL)
-                                       winfocus = TAILQ_LAST(wl, ws_win_list);
-                               if (winfocus->iconic == 0)
-                                       break;
-                               winfocus = TAILQ_PREV(winfocus, ws_win_list,
-                                   entry);
-                       }
-               }
-               break;
-
-       case SWM_ARG_ID_FOCUSNEXT:
-               head = TAILQ_NEXT(cur_focus, entry);
-               if (head == NULL)
-                       head = TAILQ_FIRST(wl);
-               winfocus = head;
-
-               /* skip iconics */
-               if (winfocus && winfocus->iconic) {
-                       while (winfocus != cur_focus) {
-                               if (winfocus == NULL)
-                                       winfocus = TAILQ_FIRST(wl);
-                               if (winfocus->iconic == 0)
-                                       break;
-                               winfocus = TAILQ_NEXT(winfocus, entry);
-                       }
-               }
-               break;
-
-       case SWM_ARG_ID_FOCUSMAIN:
-               winfocus = TAILQ_FIRST(wl);
-               if (winfocus == cur_focus)
-                       winfocus = cur_focus->ws->focus_prev;
-               break;
-
-       default:
-               return;
-       }
-
-       focus_magic(winfocus);
-}
-
-void
-cycle_layout(struct swm_region *r, union arg *args)
-{
-       struct workspace        *ws = r->ws;
-       union arg               a;
-
-       DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx);
-
-       ws->cur_layout++;
-       if (ws->cur_layout->l_stack == NULL)
-               ws->cur_layout = &layouts[0];
-
-       stack();
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-       a.id = SWM_ARG_ID_FOCUSCUR;
-       focus(r, &a);
-       bar_update();
-}
-
-void
-stack_config(struct swm_region *r, union arg *args)
-{
-       struct workspace        *ws = r->ws;
-
-       DNPRINTF(SWM_D_STACK, "stack_config: id: %d workspace: %d\n",
-           args->id, ws->idx);
-
-       if (ws->cur_layout->l_config != NULL)
-               ws->cur_layout->l_config(ws, args->id);
-
-       if (args->id != SWM_ARG_ID_STACKINIT)
-               stack();
-       bar_update();
-}
-
-void
-stack(void) {
-       struct swm_geometry     g;
-       struct swm_region       *r;
-       int                     i;
-#ifdef SWM_DEBUG
-       int j;
-#endif
-
-       DNPRINTF(SWM_D_STACK, "stack: begin\n");
-
-       for (i = 0; i < ScreenCount(display); i++) {
-#ifdef SWM_DEBUG
-               j = 0;
-#endif
-               TAILQ_FOREACH(r, &screens[i].rl, entry) {
-                       DNPRINTF(SWM_D_STACK, "stack: workspace: %d "
-                           "(screen: %d, region: %d)\n", r->ws->idx, i, j++);
-
-                       /* start with screen geometry, adjust for bar */
-                       g = r->g;
-                       g.w -= 2 * border_width;
-                       g.h -= 2 * border_width;
-                       if (bar_enabled) {
-                               if (!bar_at_bottom)
-                                       g.y += bar_height;
-                               g.h -= bar_height;
-                       }
-                       r->ws->cur_layout->l_stack(r->ws, &g);
-                       r->ws->cur_layout->l_string(r->ws);
-                       /* save r so we can track region changes */
-                       r->ws->old_r = r;
-               }
-       }
-       if (font_adjusted)
-               font_adjusted--;
-
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-
-       DNPRINTF(SWM_D_STACK, "stack: end\n");
-}
-
-void
-store_float_geom(struct ws_win *win, struct swm_region *r)
-{
-       /* retain window geom and region geom */
-       win->g_float = win->g;
-       win->rg_float = r->g;
-       win->g_floatvalid = 1;
-}
-
-void
-stack_floater(struct ws_win *win, struct swm_region *r)
-{
-       unsigned int            mask;
-       XWindowChanges          wc;
-
-       if (win == NULL)
-               return;
-
-       bzero(&wc, sizeof wc);
-       mask = CWX | CWY | CWBorderWidth | CWWidth | CWHeight;
-
-       /*
-        * to allow windows to change their size (e.g. mplayer fs) only retrieve
-        * geom on ws switches or return from max mode
-        */
-       if (win->floatmaxed || (r != r->ws->old_r && win->g_floatvalid
-           && !(win->ewmh_flags & EWMH_F_FULLSCREEN))) {
-               /*
-                * use stored g and rg to set relative position and size
-                * as in old region or before max stack mode
-                */
-               X(win) = win->g_float.x - win->rg_float.x + X(r);
-               Y(win) = win->g_float.y - win->rg_float.y + Y(r);
-               WIDTH(win) = win->g_float.w;
-               HEIGHT(win) = win->g_float.h;
-               win->g_floatvalid = 0;
-       }
-
-       win->floatmaxed = 0;
-
-       if ((win->quirks & SWM_Q_FULLSCREEN) && (WIDTH(win) >= WIDTH(r)) &&
-           (HEIGHT(win) >= HEIGHT(r)))
-               wc.border_width = 0;
-       else
-               wc.border_width = border_width;
-       if (win->transient && (win->quirks & SWM_Q_TRANSSZ)) {
-               WIDTH(win) = (double)WIDTH(r) * dialog_ratio;
-               HEIGHT(win) = (double)HEIGHT(r) * dialog_ratio;
-       }
-
-       if (!win->manual) {
-               /*
-                * floaters and transients are auto-centred unless moved
-                * or resized
-                */
-               X(win) = X(r) + (WIDTH(r) - WIDTH(win)) /  2 - wc.border_width;
-               Y(win) = Y(r) + (HEIGHT(r) - HEIGHT(win)) / 2 - wc.border_width;
-       }
-
-       /* win can be outside r if new r smaller than old r */
-       /* Ensure top left corner inside r (move probs otherwise) */
-       if (X(win) < X(r) - wc.border_width)
-               X(win) = X(r) - wc.border_width;
-       if (X(win) > X(r) + WIDTH(r) - 1)
-               X(win) = (WIDTH(win) > WIDTH(r)) ? X(r) :
-                   (X(r) + WIDTH(r) - WIDTH(win) - 2 * wc.border_width);
-       if (Y(win) < Y(r) - wc.border_width)
-               Y(win) = Y(r) - wc.border_width;
-       if (Y(win) > Y(r) + HEIGHT(r) - 1)
-               Y(win) = (HEIGHT(win) > HEIGHT(r)) ? Y(r) :
-                   (Y(r) + HEIGHT(r) - HEIGHT(win) - 2 * wc.border_width);
-
-       wc.x = X(win);
-       wc.y = Y(win);
-       wc.width = WIDTH(win);
-       wc.height = HEIGHT(win);
-
-       /*
-        * Retain floater and transient geometry for correct positioning
-        * when ws changes region
-        */
-       if (!(win->ewmh_flags & EWMH_F_FULLSCREEN))
-               store_float_geom(win, r);
-
-       DNPRINTF(SWM_D_MISC, "stack_floater: window: %lu, (x,y) w x h: (%d,%d) "
-           "%d x %d\n", win->id, wc.x, wc.y, wc.width, wc.height);
-
-       XConfigureWindow(display, win->id, mask, &wc);
-}
-
-/*
- * Send keystrokes to terminal to decrease/increase the font size as the
- * window size changes.
- */
-void
-adjust_font(struct ws_win *win)
-{
-       if (!(win->quirks & SWM_Q_XTERM_FONTADJ) ||
-           win->floating || win->transient)
-               return;
-
-       if (win->sh.width_inc && win->last_inc != win->sh.width_inc &&
-           WIDTH(win) / win->sh.width_inc < term_width &&
-           win->font_steps < SWM_MAX_FONT_STEPS) {
-               win->font_size_boundary[win->font_steps] =
-                   (win->sh.width_inc * term_width) + win->sh.base_width;
-               win->font_steps++;
-               font_adjusted++;
-               win->last_inc = win->sh.width_inc;
-               fake_keypress(win, XK_KP_Subtract, ShiftMask);
-       } else if (win->font_steps && win->last_inc != win->sh.width_inc &&
-           WIDTH(win) > win->font_size_boundary[win->font_steps - 1]) {
-               win->font_steps--;
-               font_adjusted++;
-               win->last_inc = win->sh.width_inc;
-               fake_keypress(win, XK_KP_Add, ShiftMask);
-       }
-}
-
-#define SWAPXY(g)      do {                            \
-       int tmp;                                        \
-       tmp = (g)->y; (g)->y = (g)->x; (g)->x = tmp;    \
-       tmp = (g)->h; (g)->h = (g)->w; (g)->w = tmp;    \
-} while (0)
-void
-stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
-{
-       XWindowChanges          wc;
-       XWindowAttributes       wa;
-       struct swm_geometry     win_g, r_g = *g;
-       struct ws_win           *win, *fs_win = 0;
-       int                     i, j, s, stacks;
-       int                     w_inc = 1, h_inc, w_base = 1, h_base;
-       int                     hrh, extra = 0, h_slice, last_h = 0;
-       int                     split, colno, winno, mwin, msize, mscale;
-       int                     remain, missing, v_slice, reconfigure;
-       unsigned int            mask;
-
-       DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d, rot: %s, "
-           "flip: %s\n", ws->idx, YESNO(rot), YESNO(flip));
-
-       winno = count_win(ws, 0);
-       if (winno == 0 && count_win(ws, 1) == 0)
-               return;
-
-       TAILQ_FOREACH(win, &ws->winlist, entry)
-               if (win->transient == 0 && win->floating == 0
-                   && win->iconic == 0)
-                       break;
-
-       if (win == NULL)
-               goto notiles;
-
-       if (rot) {
-               w_inc = win->sh.width_inc;
-               w_base = win->sh.base_width;
-               mwin = ws->l_state.horizontal_mwin;
-               mscale = ws->l_state.horizontal_msize;
-               stacks = ws->l_state.horizontal_stacks;
-               SWAPXY(&r_g);
-       } else {
-               w_inc = win->sh.height_inc;
-               w_base = win->sh.base_height;
-               mwin = ws->l_state.vertical_mwin;
-               mscale = ws->l_state.vertical_msize;
-               stacks = ws->l_state.vertical_stacks;
-       }
-       win_g = r_g;
-
-       if (stacks > winno - mwin)
-               stacks = winno - mwin;
-       if (stacks < 1)
-               stacks = 1;
-
-       h_slice = r_g.h / SWM_H_SLICE;
-       if (mwin && winno > mwin) {
-               v_slice = r_g.w / SWM_V_SLICE;
-
-               split = mwin;
-               colno = split;
-               win_g.w = v_slice * mscale;
-
-               if (w_inc > 1 && w_inc < v_slice) {
-                       /* adjust for window's requested size increment */
-                       remain = (win_g.w - w_base) % w_inc;
-                       missing = w_inc - remain;
-                       win_g.w -= remain;
-                       extra += remain;
-               }
-
-               msize = win_g.w;
-               if (flip)
-                       win_g.x += r_g.w - msize;
-       } else {
-               msize = -2;
-               colno = split = winno / stacks;
-               win_g.w = ((r_g.w - (stacks * 2 * border_width) +
-                   2 * border_width) / stacks);
-       }
-       hrh = r_g.h / colno;
-       extra = r_g.h - (colno * hrh);
-       win_g.h = hrh - 2 * border_width;
-
-       /*  stack all the tiled windows */
-       i = j = 0, s = stacks;
-       TAILQ_FOREACH(win, &ws->winlist, entry) {
-               if (win->transient != 0 || win->floating != 0)
-                       continue;
-               if (win->iconic != 0)
-                       continue;
-
-               if (win->ewmh_flags & EWMH_F_FULLSCREEN) {
-                       fs_win = win;
-                       continue;
-               }
-
-               if (split && i == split) {
-                       colno = (winno - mwin) / stacks;
-                       if (s <= (winno - mwin) % stacks)
-                               colno++;
-                       split = split + colno;
-                       hrh = (r_g.h / colno);
-                       extra = r_g.h - (colno * hrh);
-                       if (flip)
-                               win_g.x = r_g.x;
-                       else
-                               win_g.x += win_g.w + 2 * border_width;
-                       win_g.w = (r_g.w - msize -
-                           (stacks * 2 * border_width)) / stacks;
-                       if (s == 1)
-                               win_g.w += (r_g.w - msize -
-                                   (stacks * 2 * border_width)) % stacks;
-                       s--;
-                       j = 0;
-               }
-               win_g.h = hrh - 2 * border_width;
-               if (rot) {
-                       h_inc = win->sh.width_inc;
-                       h_base = win->sh.base_width;
-               } else {
-                       h_inc = win->sh.height_inc;
-                       h_base = win->sh.base_height;
-               }
-               if (j == colno - 1) {
-                       win_g.h = hrh + extra;
-               } else if (h_inc > 1 && h_inc < h_slice) {
-                       /* adjust for window's requested size increment */
-                       remain = (win_g.h - h_base) % h_inc;
-                       missing = h_inc - remain;
-
-                       if (missing <= extra || j == 0) {
-                               extra -= missing;
-                               win_g.h += missing;
-                       } else {
-                               win_g.h -= remain;
-                               extra += remain;
-                       }
-               }
-
-               if (j == 0)
-                       win_g.y = r_g.y;
-               else
-                       win_g.y += last_h + 2 * border_width;
-
-               bzero(&wc, sizeof wc);
-               if (disable_border && bar_enabled == 0 && winno == 1){
-                       wc.border_width = 0;
-                       win_g.w += 2 * border_width;
-                       win_g.h += 2 * border_width;
-               } else
-                       wc.border_width = border_width;
-               reconfigure = 0;
-               if (rot) {
-                       if (X(win) != win_g.y || Y(win) != win_g.x ||
-                           WIDTH(win) != win_g.h || HEIGHT(win) != win_g.w) {
-                               reconfigure = 1;
-                               X(win) = wc.x = win_g.y;
-                               Y(win) = wc.y = win_g.x;
-                               WIDTH(win) = wc.width = win_g.h;
-                               HEIGHT(win) = wc.height = win_g.w;
-                       }
-               } else {
-                       if (X(win) != win_g.x || Y(win) != win_g.y ||
-                           WIDTH(win) != win_g.w || HEIGHT(win) != win_g.h) {
-                               reconfigure = 1;
-                               X(win) = wc.x = win_g.x;
-                               Y(win) = wc.y = win_g.y;
-                               WIDTH(win) = wc.width = win_g.w;
-                               HEIGHT(win) = wc.height = win_g.h;
-                       }
-               }
-               if (reconfigure) {
-                       adjust_font(win);
-                       mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
-                       XConfigureWindow(display, win->id, mask, &wc);
-               }
-
-               if (XGetWindowAttributes(display, win->id, &wa))
-                       if (wa.map_state == IsUnmapped)
-                               XMapRaised(display, win->id);
-
-               last_h = win_g.h;
-               i++;
-               j++;
-       }
-
-notiles:
-       /* now, stack all the floaters and transients */
-       TAILQ_FOREACH(win, &ws->winlist, entry) {
-               if (win->transient == 0 && win->floating == 0)
-                       continue;
-               if (win->iconic == 1)
-                       continue;
-               if (win->ewmh_flags & EWMH_F_FULLSCREEN) {
-                       fs_win = win;
-                       continue;
-               }
-
-               stack_floater(win, ws->r);
-               XMapRaised(display, win->id);
-       }
-
-       if (fs_win) {
-               stack_floater(fs_win, ws->r);
-               XMapRaised(display, fs_win->id);
-       }
-}
-
-void
-vertical_config(struct workspace *ws, int id)
-{
-       DNPRINTF(SWM_D_STACK, "vertical_config: id: %d, workspace: %d\n",
-           id, ws->idx);
-
-       switch (id) {
-       case SWM_ARG_ID_STACKRESET:
-       case SWM_ARG_ID_STACKINIT:
-               ws->l_state.vertical_msize = SWM_V_SLICE / 2;
-               ws->l_state.vertical_mwin = 1;
-               ws->l_state.vertical_stacks = 1;
-               break;
-       case SWM_ARG_ID_MASTERSHRINK:
-               if (ws->l_state.vertical_msize > 1)
-                       ws->l_state.vertical_msize--;
-               break;
-       case SWM_ARG_ID_MASTERGROW:
-               if (ws->l_state.vertical_msize < SWM_V_SLICE - 1)
-                       ws->l_state.vertical_msize++;
-               break;
-       case SWM_ARG_ID_MASTERADD:
-               ws->l_state.vertical_mwin++;
-               break;
-       case SWM_ARG_ID_MASTERDEL:
-               if (ws->l_state.vertical_mwin > 0)
-                       ws->l_state.vertical_mwin--;
-               break;
-       case SWM_ARG_ID_STACKINC:
-               ws->l_state.vertical_stacks++;
-               break;
-       case SWM_ARG_ID_STACKDEC:
-               if (ws->l_state.vertical_stacks > 1)
-                       ws->l_state.vertical_stacks--;
-               break;
-       case SWM_ARG_ID_FLIPLAYOUT:
-               ws->l_state.vertical_flip = !ws->l_state.vertical_flip;
-               break;
-       default:
-               return;
-       }
-}
-
-void
-vertical_stack(struct workspace *ws, struct swm_geometry *g)
-{
-       DNPRINTF(SWM_D_STACK, "vertical_stack: workspace: %d\n", ws->idx);
-
-       stack_master(ws, g, 0, ws->l_state.vertical_flip);
-}
-
-void
-horizontal_config(struct workspace *ws, int id)
-{
-       DNPRINTF(SWM_D_STACK, "horizontal_config: workspace: %d\n", ws->idx);
-
-       switch (id) {
-       case SWM_ARG_ID_STACKRESET:
-       case SWM_ARG_ID_STACKINIT:
-               ws->l_state.horizontal_mwin = 1;
-               ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
-               ws->l_state.horizontal_stacks = 1;
-               break;
-       case SWM_ARG_ID_MASTERSHRINK:
-               if (ws->l_state.horizontal_msize > 1)
-                       ws->l_state.horizontal_msize--;
-               break;
-       case SWM_ARG_ID_MASTERGROW:
-               if (ws->l_state.horizontal_msize < SWM_H_SLICE - 1)
-                       ws->l_state.horizontal_msize++;
-               break;
-       case SWM_ARG_ID_MASTERADD:
-               ws->l_state.horizontal_mwin++;
-               break;
-       case SWM_ARG_ID_MASTERDEL:
-               if (ws->l_state.horizontal_mwin > 0)
-                       ws->l_state.horizontal_mwin--;
-               break;
-       case SWM_ARG_ID_STACKINC:
-               ws->l_state.horizontal_stacks++;
-               break;
-       case SWM_ARG_ID_STACKDEC:
-               if (ws->l_state.horizontal_stacks > 1)
-                       ws->l_state.horizontal_stacks--;
-               break;
-       case SWM_ARG_ID_FLIPLAYOUT:
-               ws->l_state.horizontal_flip = !ws->l_state.horizontal_flip;
-               break;
-       default:
-               return;
-       }
-}
-
-void
-horizontal_stack(struct workspace *ws, struct swm_geometry *g)
-{
-       DNPRINTF(SWM_D_STACK, "horizontal_stack: workspace: %d\n", ws->idx);
-
-       stack_master(ws, g, 1, ws->l_state.horizontal_flip);
-}
-
-/* fullscreen view */
-void
-max_stack(struct workspace *ws, struct swm_geometry *g)
-{
-       XWindowChanges          wc;
-       struct swm_geometry     gg = *g;
-       struct ws_win           *win, *wintrans = NULL, *parent = NULL;
-       unsigned int            mask;
-       int                     winno;
-
-       DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
-
-       if (ws == NULL)
-               return;
-
-       winno = count_win(ws, 0);
-       if (winno == 0 && count_win(ws, 1) == 0)
-               return;
-
-       TAILQ_FOREACH(win, &ws->winlist, entry) {
-               if (win->transient) {
-                       wintrans = win;
-                       parent = find_window(win->transient);
-                       continue;
-               }
-
-               if (win->floating && win->floatmaxed == 0 ) {
-                       /*
-                        * retain geometry for retrieval on exit from
-                        * max_stack mode
-                        */
-                       store_float_geom(win, ws->r);
-                       win->floatmaxed = 1;
-               }
-
-               /* only reconfigure if necessary */
-               if (X(win) != gg.x || Y(win) != gg.y || WIDTH(win) != gg.w ||
-                   HEIGHT(win) != gg.h) {
-                       bzero(&wc, sizeof wc);
-                       X(win) = wc.x = gg.x;
-                       Y(win) = wc.y = gg.y;
-                       if (bar_enabled){
-                               wc.border_width = border_width;
-                               WIDTH(win) = wc.width = gg.w;
-                               HEIGHT(win) = wc.height = gg.h;
-                       } else {
-                               wc.border_width = 0;
-                               WIDTH(win) = wc.width = gg.w + 2 * border_width;
-                               HEIGHT(win) = wc.height = gg.h +
-                                   2 * border_width;
-                       }
-                       mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
-                       XConfigureWindow(display, win->id, mask, &wc);
-               }
-               /* unmap only if we don't have multi screen */
-               if (win != ws->focus)
-                       if (!(ScreenCount(display) > 1 || outputs > 1))
-                               unmap_window(win);
-       }
-
-       /* put the last transient on top */
-       if (wintrans) {
-               if (parent)
-                       XMapRaised(display, parent->id);
-               stack_floater(wintrans, ws->r);
-               focus_magic(wintrans);
-       }
-}
-
-void
-send_to_ws(struct swm_region *r, union arg *args)
-{
-       int                     wsid = args->id;
-       struct ws_win           *win = NULL, *parent;
-       struct workspace        *ws, *nws;
-       Atom                    ws_idx_atom = 0;
-       unsigned char           ws_idx_str[SWM_PROPLEN];
-       union arg               a;
-
-       if (r && r->ws && r->ws->focus)
-               win = r->ws->focus;
-       else
-               return;
-       if (win == NULL)
-               return;
-       if (win->ws->idx == wsid)
-               return;
-
-       DNPRINTF(SWM_D_MOVE, "send_to_ws: window: 0x%lx\n", win->id);
-
-       ws = win->ws;
-       nws = &win->s->ws[wsid];
-
-       a.id = SWM_ARG_ID_FOCUSPREV;
-       focus(r, &a);
-       if (win->transient) {
-               parent = find_window(win->transient);
-               if (parent) {
-                       unmap_window(parent);
-                       TAILQ_REMOVE(&ws->winlist, parent, entry);
-                       TAILQ_INSERT_TAIL(&nws->winlist, parent, entry);
-                       parent->ws = nws;
-               }
-       }
-       unmap_window(win);
-       TAILQ_REMOVE(&ws->winlist, win, entry);
-       TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
-       if (TAILQ_EMPTY(&ws->winlist))
-               r->ws->focus = NULL;
-       win->ws = nws;
-
-       /* Try to update the window's workspace property */
-       ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
-       if (ws_idx_atom &&
-           snprintf((char *)ws_idx_str, SWM_PROPLEN, "%d", nws->idx) <
-               SWM_PROPLEN) {
-               DNPRINTF(SWM_D_PROP, "send_to_ws: set property: _SWM_WS: %s\n",
-                   ws_idx_str);
-               XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
-                   PropModeReplace, ws_idx_str, strlen((char *)ws_idx_str));
-       }
-
-       stack();
-}
-
-void
-pressbutton(struct swm_region *r, union arg *args)
-{
-       XTestFakeButtonEvent(display, args->id, True, CurrentTime);
-       XTestFakeButtonEvent(display, args->id, False, CurrentTime);
-}
-
-void
-raise_toggle(struct swm_region *r, union arg *args)
-{
-       if (r && r->ws == NULL)
-               return;
-
-       r->ws->always_raise = !r->ws->always_raise;
-
-       /* bring floaters back to top */
-       if (r->ws->always_raise == 0)
-               stack();
-}
-
-void
-iconify(struct swm_region *r, union arg *args)
-{
-       union arg a;
-
-       if (r->ws->focus == NULL)
-               return;
-       unmap_window(r->ws->focus);
-       update_iconic(r->ws->focus, 1);
-       stack();
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-       r->ws->focus = NULL;
-       a.id = SWM_ARG_ID_FOCUSCUR;
-       focus(r, &a);
-}
-
-unsigned char *
-get_win_name(Window win)
-{
-       unsigned char           *prop = NULL;
-       unsigned long           nbytes, nitems;
-
-       /* try _NET_WM_NAME first */
-       if (get_property(win, a_netwmname, 0L, a_utf8_string, NULL, &nbytes,
-           &prop)) {
-               XFree(prop);
-               if (get_property(win, a_netwmname, nbytes, a_utf8_string,
-                   &nitems, NULL, &prop))
-                       return (prop);
-       }
-
-       /* fallback to WM_NAME */
-       if (!get_property(win, a_wmname, 0L, a_string, NULL, &nbytes, &prop))
-               return (NULL);
-       XFree(prop);
-       if (get_property(win, a_wmname, nbytes, a_string, &nitems, NULL, &prop))
-               return (prop);
-
-       return (NULL);
-}
-
-void
-uniconify(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *win;
-       FILE                    *lfile;
-       unsigned char           *name;
-       int                     count = 0;
-
-       DNPRINTF(SWM_D_MISC, "uniconify\n");
-
-       if (r && r->ws == NULL)
-               return;
-
-       /* make sure we have anything to uniconify */
-       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
-               if (win->ws == NULL)
-                       continue; /* should never happen */
-               if (win->iconic == 0)
-                       continue;
-               count++;
-       }
-       if (count == 0)
-               return;
-
-       search_r = r;
-       search_resp_action = SWM_SEARCH_UNICONIFY;
-
-       spawn_select(r, args, "search", &searchpid);
-
-       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
-               return;
-
-       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
-               if (win->ws == NULL)
-                       continue; /* should never happen */
-               if (win->iconic == 0)
-                       continue;
-
-               name = get_win_name(win->id);
-               if (name == NULL)
-                       continue;
-               fprintf(lfile, "%s.%lu\n", name, win->id);
-               XFree(name);
-       }
-
-       fclose(lfile);
-}
-
-void
-name_workspace(struct swm_region *r, union arg *args)
-{
-       FILE                    *lfile;
-
-       DNPRINTF(SWM_D_MISC, "name_workspace\n");
-
-       if (r == NULL)
-               return;
-
-       search_r = r;
-       search_resp_action = SWM_SEARCH_NAME_WORKSPACE;
-
-       spawn_select(r, args, "name_workspace", &searchpid);
-
-       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
-               return;
-
-       fprintf(lfile, "%s", "");
-       fclose(lfile);
-}
-
-void
-search_workspace(struct swm_region *r, union arg *args)
-{
-       int                     i;
-       struct workspace        *ws;
-       FILE                    *lfile;
-
-       DNPRINTF(SWM_D_MISC, "search_workspace\n");
-
-       if (r == NULL)
-               return;
-
-       search_r = r;
-       search_resp_action = SWM_SEARCH_SEARCH_WORKSPACE;
-
-       spawn_select(r, args, "search", &searchpid);
-
-       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
-               return;
-
-       for (i = 0; i < SWM_WS_MAX; i++) {
-               ws = &r->s->ws[i];
-               if (ws == NULL)
-                       continue;
-               fprintf(lfile, "%d%s%s\n", ws->idx + 1,
-                   (ws->name ? ":" : ""), (ws->name ? ws->name : ""));
-       }
-
-       fclose(lfile);
-}
-
-void
-search_win_cleanup(void)
-{
-       struct search_window    *sw = NULL;
-
-       while ((sw = TAILQ_FIRST(&search_wl)) != NULL) {
-               XDestroyWindow(display, sw->indicator);
-               XFreeGC(display, sw->gc);
-               TAILQ_REMOVE(&search_wl, sw, entry);
-               free(sw);
-       }
-}
-
-void
-search_win(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *win = NULL;
-       struct search_window    *sw = NULL;
-       Window                  w;
-       XGCValues               gcv;
-       int                     i;
-       char                    s[8];
-       FILE                    *lfile;
-       size_t                  len;
-       XRectangle              ibox, lbox;
-
-       DNPRINTF(SWM_D_MISC, "search_win\n");
-
-       search_r = r;
-       search_resp_action = SWM_SEARCH_SEARCH_WINDOW;
-
-       spawn_select(r, args, "search", &searchpid);
-
-       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
-               return;
-
-       TAILQ_INIT(&search_wl);
-
-       i = 1;
-       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
-               if (win->iconic == 1)
-                       continue;
-
-               sw = calloc(1, sizeof(struct search_window));
-               if (sw == NULL) {
-                       warn("search_win: calloc");
-                       fclose(lfile);
-                       search_win_cleanup();
-                       return;
-               }
-               sw->idx = i;
-               sw->win = win;
-
-               snprintf(s, sizeof s, "%d", i);
-               len = strlen(s);
-
-               XmbTextExtents(bar_fs, s, len, &ibox, &lbox);
-
-               w = XCreateSimpleWindow(display,
-                   win->id, 0, 0,lbox.width + 4,
-                   bar_fs_extents->max_logical_extent.height, 1,
-                   r->s->c[SWM_S_COLOR_UNFOCUS].color,
-                   r->s->c[SWM_S_COLOR_FOCUS].color);
-
-               sw->indicator = w;
-               TAILQ_INSERT_TAIL(&search_wl, sw, entry);
-
-               sw->gc = XCreateGC(display, w, 0, &gcv);
-               XMapRaised(display, w);
-               XSetForeground(display, sw->gc, r->s->c[SWM_S_COLOR_BAR].color);
-
-               DRAWSTRING(display, w, bar_fs, sw->gc, 2,
-                   (bar_fs_extents->max_logical_extent.height -
-                   lbox.height) / 2 - lbox.y, s, len);
-
-               fprintf(lfile, "%d\n", i);
-               i++;
-       }
-
-       fclose(lfile);
-}
-
-void
-search_resp_uniconify(char *resp, unsigned long len)
-{
-       unsigned char           *name;
-       struct ws_win           *win;
-       char                    *s;
-
-       DNPRINTF(SWM_D_MISC, "search_resp_uniconify: resp: %s\n", resp);
-
-       TAILQ_FOREACH(win, &search_r->ws->winlist, entry) {
-               if (win->iconic == 0)
-                       continue;
-               name = get_win_name(win->id);
-               if (name == NULL)
-                       continue;
-               if (asprintf(&s, "%s.%lu", name, win->id) == -1) {
-                       XFree(name);
-                       continue;
-               }
-               XFree(name);
-               if (strncmp(s, resp, len) == 0) {
-                       /* XXX this should be a callback to generalize */
-                       update_iconic(win, 0);
-                       free(s);
-                       break;
-               }
-               free(s);
-       }
-}
-
-void
-search_resp_name_workspace(char *resp, unsigned long len)
-{
-       struct workspace        *ws;
-
-       DNPRINTF(SWM_D_MISC, "search_resp_name_workspace: resp: %s\n", resp);
-
-       if (search_r->ws == NULL)
-               return;
-       ws = search_r->ws;
-
-       if (ws->name) {
-               free(search_r->ws->name);
-               search_r->ws->name = NULL;
-       }
-
-       if (len > 1) {
-               ws->name = strdup(resp);
-               if (ws->name == NULL) {
-                       DNPRINTF(SWM_D_MISC, "search_resp_name_workspace: "
-                           "strdup: %s", strerror(errno));
-                       return;
-               }
-       }
-}
-
-void
-search_resp_search_workspace(char *resp, unsigned long len)
-{
-       char                    *p, *q;
-       int                     ws_idx;
-       const char              *errstr;
-       union arg               a;
-
-       DNPRINTF(SWM_D_MISC, "search_resp_search_workspace: resp: %s\n", resp);
-
-       q = strdup(resp);
-       if (!q) {
-               DNPRINTF(SWM_D_MISC, "search_resp_search_workspace: strdup: %s",
-                   strerror(errno));
-               return;
-       }
-       p = strchr(q, ':');
-       if (p != NULL)
-               *p = '\0';
-       ws_idx = strtonum(q, 1, SWM_WS_MAX, &errstr);
-       if (errstr) {
-               DNPRINTF(SWM_D_MISC, "workspace idx is %s: %s",
-                   errstr, q);
-               free(q);
-               return;
-       }
-       free(q);
-       a.id = ws_idx - 1;
-       switchws(search_r, &a);
-}
-
-void
-search_resp_search_window(char *resp, unsigned long len)
-{
-       char                    *s;
-       int                     idx;
-       const char              *errstr;
-       struct search_window    *sw;
-
-       DNPRINTF(SWM_D_MISC, "search_resp_search_window: resp: %s\n", resp);
-
-       s = strdup(resp);
-       if (!s) {
-               DNPRINTF(SWM_D_MISC, "search_resp_search_window: strdup: %s",
-                   strerror(errno));
-               return;
-       }
-
-       idx = strtonum(s, 1, INT_MAX, &errstr);
-       if (errstr) {
-               DNPRINTF(SWM_D_MISC, "window idx is %s: %s",
-                   errstr, s);
-               free(s);
-               return;
-       }
-       free(s);
-
-       TAILQ_FOREACH(sw, &search_wl, entry)
-               if (idx == sw->idx) {
-                       focus_win(sw->win);
-                       break;
-               }
-}
-
-#define MAX_RESP_LEN   1024
-
-void
-search_do_resp(void)
-{
-       ssize_t                 rbytes;
-       char                    *resp;
-       unsigned long           len;
-
-       DNPRINTF(SWM_D_MISC, "search_do_resp:\n");
-
-       search_resp = 0;
-       searchpid = 0;
-
-       if ((resp = calloc(1, MAX_RESP_LEN + 1)) == NULL) {
-               warn("search: calloc");
-               goto done;
-       }
-
-       rbytes = read(select_resp_pipe[0], resp, MAX_RESP_LEN);
-       if (rbytes <= 0) {
-               warn("search: read error");
-               goto done;
-       }
-       resp[rbytes] = '\0';
-
-       /* XXX:
-        * Older versions of dmenu (Atleast pre 4.4.1) do not send a
-        * newline, so work around that by sanitizing the resp now.
-        */
-       resp[strcspn(resp, "\n")] = '\0';
-       len = strlen(resp);
-
-       switch (search_resp_action) {
-       case SWM_SEARCH_UNICONIFY:
-               search_resp_uniconify(resp, len);
-               break;
-       case SWM_SEARCH_NAME_WORKSPACE:
-               search_resp_name_workspace(resp, len);
-               break;
-       case SWM_SEARCH_SEARCH_WORKSPACE:
-               search_resp_search_workspace(resp, len);
-               break;
-       case SWM_SEARCH_SEARCH_WINDOW:
-               search_resp_search_window(resp, len);
-               break;
-       }
-
-done:
-       if (search_resp_action == SWM_SEARCH_SEARCH_WINDOW)
-               search_win_cleanup();
-
-       search_resp_action = SWM_SEARCH_NONE;
-       close(select_resp_pipe[0]);
-       free(resp);
-}
-
-void
-wkill(struct swm_region *r, union arg *args)
-{
-       DNPRINTF(SWM_D_MISC, "wkill: id: %d\n", args->id);
-
-       if (r->ws->focus == NULL)
-               return;
-
-       if (args->id == SWM_ARG_ID_KILLWINDOW)
-               XKillClient(display, r->ws->focus->id);
-       else
-               if (r->ws->focus->can_delete)
-                       client_msg(r->ws->focus, adelete);
-}
-
-
-int
-floating_toggle_win(struct ws_win *win)
-{
-       struct swm_region       *r;
-
-       if (win == NULL)
-               return 0;
-
-       if (!win->ws->r)
-               return 0;
-
-       r = win->ws->r;
-
-       /* reject floating toggles in max stack mode */
-       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK])
-               return 0;
-
-       if (win->floating) {
-               if (!win->floatmaxed) {
-                       /* retain position for refloat */
-                       store_float_geom(win, r);
-               }
-               win->floating = 0;
-       } else {
-               if (win->g_floatvalid) {
-                       /* refloat at last floating relative position */
-                       X(win) = win->g_float.x - win->rg_float.x + X(r);
-                       Y(win) = win->g_float.y - win->rg_float.y + Y(r);
-                       WIDTH(win) = win->g_float.w;
-                       HEIGHT(win) = win->g_float.h;
-               }
-               win->floating = 1;
-       }
-
-       ewmh_update_actions(win);
-
-       return 1;
-}
-
-void
-floating_toggle(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *win = r->ws->focus;
-       union arg               a;
-
-       if (win == NULL)
-               return;
-
-       ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
-           _NET_WM_STATE_TOGGLE);
-
-       stack();
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-
-       if (win == win->ws->focus) {
-               a.id = SWM_ARG_ID_FOCUSCUR;
-               focus(win->ws->r, &a);
-       }
-}
-
-void
-constrain_window(struct ws_win *win, struct swm_region *r, int resizable)
-{
-       if (X(win) + WIDTH(win) > X(r) + WIDTH(r) - border_width) {
-               if (resizable)
-                       WIDTH(win) = X(r) + WIDTH(r) - X(win) - border_width;
-               else
-                       X(win) = X(r) + WIDTH(r) - WIDTH(win) - border_width;
-       }
-
-       if (X(win) < X(r) - border_width) {
-               if (resizable)
-                       WIDTH(win) -= X(r) - X(win) - border_width;
-
-               X(win) = X(r) - border_width;
-       }
-
-       if (Y(win) + HEIGHT(win) > Y(r) + HEIGHT(r) - border_width) {
-               if (resizable)
-                       HEIGHT(win) = Y(r) + HEIGHT(r) - Y(win) - border_width;
-               else
-                       Y(win) = Y(r) + HEIGHT(r) - HEIGHT(win) - border_width;
-       }
-
-       if (Y(win) < Y(r) - border_width) {
-               if (resizable)
-                       HEIGHT(win) -= Y(r) - Y(win) - border_width;
-
-               Y(win) = Y(r) - border_width;
-       }
-
-       if (WIDTH(win) < 1)
-               WIDTH(win) = 1;
-       if (HEIGHT(win) < 1)
-               HEIGHT(win) = 1;
-}
-
-void
-update_window(struct ws_win *win)
-{
-       unsigned int            mask;
-       XWindowChanges          wc;
-
-       bzero(&wc, sizeof wc);
-       mask = CWBorderWidth | CWWidth | CWHeight | CWX | CWY;
-       wc.border_width = border_width;
-       wc.x = X(win);
-       wc.y = Y(win);
-       wc.width = WIDTH(win);
-       wc.height = HEIGHT(win);
-
-       DNPRINTF(SWM_D_MISC, "update_window: window: 0x%lx, (x,y) w x h: "
-           "(%d,%d) %d x %d\n", win->id, wc.x, wc.y, wc.width, wc.height);
-
-       XConfigureWindow(display, win->id, mask, &wc);
-}
-
-#define SWM_RESIZE_STEPS       (50)
-
-void
-resize(struct ws_win *win, union arg *args)
-{
-       XEvent                  ev;
-       Time                    time = 0;
-       struct swm_region       *r = NULL;
-       int                     resize_step = 0;
-       Window                  rr, cr;
-       int                     x, y, wx, wy;
-       unsigned int            mask;
-       struct swm_geometry     g;
-       int                     top = 0, left = 0;
-       int                     dx, dy;
-       Cursor                  cursor;
-       unsigned int            shape; /* cursor style */
-
-       if (win == NULL)
-               return;
-       r = win->ws->r;
-
-       DNPRINTF(SWM_D_MOUSE, "resize: window: 0x%lx, floating: %s, "
-           "transient: 0x%lx\n", win->id, YESNO(win->floating),
-           win->transient);
-
-       if (!(win->transient != 0 || win->floating != 0))
-               return;
-
-       /* reject resizes in max mode for floaters (transient ok) */
-       if (win->floatmaxed)
-               return;
-
-       win->manual = 1;
-       ewmh_update_win_state(win, ewmh[_SWM_WM_STATE_MANUAL].atom,
-           _NET_WM_STATE_ADD);
-
-       stack();
-
-       switch (args->id) {
-       case SWM_ARG_ID_WIDTHSHRINK:
-               WIDTH(win) -= SWM_RESIZE_STEPS;
-               resize_step = 1;
-               break;
-       case SWM_ARG_ID_WIDTHGROW:
-               WIDTH(win) += SWM_RESIZE_STEPS;
-               resize_step = 1;
-               break;
-       case SWM_ARG_ID_HEIGHTSHRINK:
-               HEIGHT(win) -= SWM_RESIZE_STEPS;
-               resize_step = 1;
-               break;
-       case SWM_ARG_ID_HEIGHTGROW:
-               HEIGHT(win) += SWM_RESIZE_STEPS;
-               resize_step = 1;
-               break;
-       default:
-               break;
-       }
-       if (resize_step) {
-               constrain_window(win, r, 1);
-               update_window(win);
-               store_float_geom(win,r);
-               return;
-       }
-
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-
-       /* get cursor offset from window root */
-       if (!XQueryPointer(display, win->id, &rr, &cr, &x, &y, &wx, &wy, &mask))
-           return;
-
-       g = win->g;
-
-       if (wx < WIDTH(win) / 2)
-               left = 1;
-
-       if (wy < HEIGHT(win) / 2)
-               top = 1;
-
-       if (args->id == SWM_ARG_ID_CENTER)
-               shape = XC_sizing;
-       else if (top)
-               shape = (left) ? XC_top_left_corner : XC_top_right_corner;
-       else
-               shape = (left) ? XC_bottom_left_corner : XC_bottom_right_corner;
-
-       cursor = XCreateFontCursor(display, shape);
-
-       if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
-           GrabModeAsync, None, cursor, CurrentTime) != GrabSuccess) {
-               XFreeCursor(display, cursor);
-               return;
-       }
-
-       do {
-               XMaskEvent(display, MOUSEMASK | ExposureMask |
-                   SubstructureRedirectMask, &ev);
-               switch (ev.type) {
-               case ConfigureRequest:
-               case Expose:
-               case MapRequest:
-                       handler[ev.type](&ev);
-                       break;
-               case MotionNotify:
-                       /* cursor offset/delta from start of the operation */
-                       dx = ev.xmotion.x_root - x;
-                       dy = ev.xmotion.y_root - y;
-
-                       /* vertical */
-                       if (top)
-                               dy = -dy;
-
-                       if (args->id == SWM_ARG_ID_CENTER) {
-                               if (g.h / 2 + dy < 1)
-                                       dy = 1 - g.h / 2;
-
-                               Y(win) = g.y - dy;
-                               HEIGHT(win) = g.h + 2 * dy;
-                       } else {
-                               if (g.h + dy < 1)
-                                       dy = 1 - g.h;
-
-                               if (top)
-                                       Y(win) = g.y - dy;
-
-                               HEIGHT(win) = g.h + dy;
-                       }
-
-                       /* horizontal */
-                       if (left)
-                               dx = -dx;
-
-                       if (args->id == SWM_ARG_ID_CENTER) {
-                               if (g.w / 2 + dx < 1)
-                                       dx = 1 - g.w / 2;
-
-                               X(win) = g.x - dx;
-                               WIDTH(win) = g.w + 2 * dx;
-                       } else {
-                               if (g.w + dx < 1)
-                                       dx = 1 - g.w;
-
-                               if (left)
-                                       X(win) = g.x - dx;
-
-                               WIDTH(win) = g.w + dx;
-                       }
-
-                       constrain_window(win, r, 1);
-
-                       /* not free, don't sync more than 120 times / second */
-                       if ((ev.xmotion.time - time) > (1000 / 120) ) {
-                               time = ev.xmotion.time;
-                               XSync(display, False);
-                               update_window(win);
-                       }
-                       break;
-               }
-       } while (ev.type != ButtonRelease);
-       if (time) {
-               XSync(display, False);
-               update_window(win);
-       }
-       store_float_geom(win,r);
-
-       XUngrabPointer(display, CurrentTime);
-       XFreeCursor(display, cursor);
-
-       /* drain events */
-       drain_enter_notify();
-}
-
-void
-resize_step(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *win = NULL;
-
-       if (r && r->ws && r->ws->focus)
-               win = r->ws->focus;
-       else
-               return;
-
-       resize(win, args);
-}
-
-#define SWM_MOVE_STEPS (50)
-
-void
-move(struct ws_win *win, union arg *args)
-{
-       XEvent                  ev;
-       Time                    time = 0;
-       int                     move_step = 0;
-       struct swm_region       *r = NULL;
-
-       Window                  rr, cr;
-       int                     x, y, wx, wy;
-       unsigned int            mask;
-
-       if (win == NULL)
-               return;
-       r = win->ws->r;
-
-       DNPRINTF(SWM_D_MOUSE, "move: window: 0x%lx, floating: %s, transient: "
-           "0x%lx\n", win->id, YESNO(win->floating), win->transient);
-
-       /* in max_stack mode should only move transients */
-       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK] && !win->transient)
-               return;
-
-       win->manual = 1;
-       if (win->floating == 0 && !win->transient) {
-               store_float_geom(win,r);
-               ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
-                   _NET_WM_STATE_ADD);
-       }
-       ewmh_update_win_state(win, ewmh[_SWM_WM_STATE_MANUAL].atom,
-           _NET_WM_STATE_ADD);
-
-       stack();
-
-       move_step = 0;
-       switch (args->id) {
-       case SWM_ARG_ID_MOVELEFT:
-               X(win) -= (SWM_MOVE_STEPS - border_width);
-               move_step = 1;
-               break;
-       case SWM_ARG_ID_MOVERIGHT:
-               X(win) += (SWM_MOVE_STEPS - border_width);
-               move_step = 1;
-               break;
-       case SWM_ARG_ID_MOVEUP:
-               Y(win) -= (SWM_MOVE_STEPS - border_width);
-               move_step = 1;
-               break;
-       case SWM_ARG_ID_MOVEDOWN:
-               Y(win) += (SWM_MOVE_STEPS - border_width);
-               move_step = 1;
-               break;
-       default:
-               break;
-       }
-       if (move_step) {
-               constrain_window(win, r, 0);
-               update_window(win);
-               store_float_geom(win, r);
-               return;
-       }
-
-       if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
-           GrabModeAsync, None, XCreateFontCursor(display, XC_fleur),
-           CurrentTime) != GrabSuccess)
-               return;
-
-       /* get cursor offset from window root */
-       if (!XQueryPointer(display, win->id, &rr, &cr, &x, &y, &wx, &wy, &mask))
-           return;
-
-       do {
-               XMaskEvent(display, MOUSEMASK | ExposureMask |
-                   SubstructureRedirectMask, &ev);
-               switch (ev.type) {
-               case ConfigureRequest:
-               case Expose:
-               case MapRequest:
-                       handler[ev.type](&ev);
-                       break;
-               case MotionNotify:
-                       X(win) = ev.xmotion.x_root - wx - border_width;
-                       Y(win) = ev.xmotion.y_root - wy - border_width;
-
-                       constrain_window(win, r, 0);
-
-                       /* not free, don't sync more than 120 times / second */
-                       if ((ev.xmotion.time - time) > (1000 / 120) ) {
-                               time = ev.xmotion.time;
-                               XSync(display, False);
-                               update_window(win);
-                       }
-                       break;
-               }
-       } while (ev.type != ButtonRelease);
-       if (time) {
-               XSync(display, False);
-               update_window(win);
-       }
-       store_float_geom(win,r);
-       XUngrabPointer(display, CurrentTime);
-
-       /* drain events */
-       drain_enter_notify();
-}
-
-void
-move_step(struct swm_region *r, union arg *args)
-{
-       struct ws_win           *win = NULL;
-
-       if (r && r->ws && r->ws->focus)
-               win = r->ws->focus;
-       else
-               return;
-
-       if (!(win->transient != 0 || win->floating != 0))
-               return;
-
-       move(win, args);
-}
-
-
-/* user/key callable function IDs */
-enum keyfuncid {
-       kf_cycle_layout,
-       kf_flip_layout,
-       kf_stack_reset,
-       kf_master_shrink,
-       kf_master_grow,
-       kf_master_add,
-       kf_master_del,
-       kf_stack_inc,
-       kf_stack_dec,
-       kf_swap_main,
-       kf_focus_next,
-       kf_focus_prev,
-       kf_swap_next,
-       kf_swap_prev,
-       kf_spawn_term,
-       kf_spawn_menu,
-       kf_quit,
-       kf_restart,
-       kf_focus_main,
-       kf_ws_1,
-       kf_ws_2,
-       kf_ws_3,
-       kf_ws_4,
-       kf_ws_5,
-       kf_ws_6,
-       kf_ws_7,
-       kf_ws_8,
-       kf_ws_9,
-       kf_ws_10,
-       kf_ws_next,
-       kf_ws_prev,
-       kf_ws_next_all,
-       kf_ws_prev_all,
-       kf_ws_prior,
-       kf_screen_next,
-       kf_screen_prev,
-       kf_mvws_1,
-       kf_mvws_2,
-       kf_mvws_3,
-       kf_mvws_4,
-       kf_mvws_5,
-       kf_mvws_6,
-       kf_mvws_7,
-       kf_mvws_8,
-       kf_mvws_9,
-       kf_mvws_10,
-       kf_bar_toggle,
-       kf_wind_kill,
-       kf_wind_del,
-       kf_screenshot_all,
-       kf_screenshot_wind,
-       kf_float_toggle,
-       kf_version,
-       kf_spawn_lock,
-       kf_spawn_initscr,
-       kf_spawn_custom,
-       kf_iconify,
-       kf_uniconify,
-       kf_raise_toggle,
-       kf_button2,
-       kf_width_shrink,
-       kf_width_grow,
-       kf_height_shrink,
-       kf_height_grow,
-       kf_move_left,
-       kf_move_right,
-       kf_move_up,
-       kf_move_down,
-       kf_name_workspace,
-       kf_search_workspace,
-       kf_search_win,
-       kf_dumpwins, /* MUST BE LAST */
-       kf_invalid
-};
-
-/* key definitions */
-void
-dummykeyfunc(struct swm_region *r, union arg *args)
-{
-};
-
-void
-legacyfunc(struct swm_region *r, union arg *args)
-{
-};
-
-struct keyfunc {
-       char                    name[SWM_FUNCNAME_LEN];
-       void                    (*func)(struct swm_region *r, union arg *);
-       union arg               args;
-} keyfuncs[kf_invalid + 1] = {
-       /* name                 function        argument */
-       { "cycle_layout",       cycle_layout,   {0} },
-       { "flip_layout",        stack_config,   {.id = SWM_ARG_ID_FLIPLAYOUT} },
-       { "stack_reset",        stack_config,   {.id = SWM_ARG_ID_STACKRESET} },
-       { "master_shrink",      stack_config,   {.id = SWM_ARG_ID_MASTERSHRINK} },
-       { "master_grow",        stack_config,   {.id = SWM_ARG_ID_MASTERGROW} },
-       { "master_add",         stack_config,   {.id = SWM_ARG_ID_MASTERADD} },
-       { "master_del",         stack_config,   {.id = SWM_ARG_ID_MASTERDEL} },
-       { "stack_inc",          stack_config,   {.id = SWM_ARG_ID_STACKINC} },
-       { "stack_dec",          stack_config,   {.id = SWM_ARG_ID_STACKDEC} },
-       { "swap_main",          swapwin,        {.id = SWM_ARG_ID_SWAPMAIN} },
-       { "focus_next",         focus,          {.id = SWM_ARG_ID_FOCUSNEXT} },
-       { "focus_prev",         focus,          {.id = SWM_ARG_ID_FOCUSPREV} },
-       { "swap_next",          swapwin,        {.id = SWM_ARG_ID_SWAPNEXT} },
-       { "swap_prev",          swapwin,        {.id = SWM_ARG_ID_SWAPPREV} },
-       { "spawn_term",         spawnterm,      {.argv = spawn_term} },
-       { "spawn_menu",         legacyfunc,     {0} },
-       { "quit",               quit,           {0} },
-       { "restart",            restart,        {0} },
-       { "focus_main",         focus,          {.id = SWM_ARG_ID_FOCUSMAIN} },
-       { "ws_1",               switchws,       {.id = 0} },
-       { "ws_2",               switchws,       {.id = 1} },
-       { "ws_3",               switchws,       {.id = 2} },
-       { "ws_4",               switchws,       {.id = 3} },
-       { "ws_5",               switchws,       {.id = 4} },
-       { "ws_6",               switchws,       {.id = 5} },
-       { "ws_7",               switchws,       {.id = 6} },
-       { "ws_8",               switchws,       {.id = 7} },
-       { "ws_9",               switchws,       {.id = 8} },
-       { "ws_10",              switchws,       {.id = 9} },
-       { "ws_next",            cyclews,        {.id = SWM_ARG_ID_CYCLEWS_UP} },
-       { "ws_prev",            cyclews,        {.id = SWM_ARG_ID_CYCLEWS_DOWN} },
-       { "ws_next_all",        cyclews,        {.id = SWM_ARG_ID_CYCLEWS_UP_ALL} },
-       { "ws_prev_all",        cyclews,        {.id = SWM_ARG_ID_CYCLEWS_DOWN_ALL} },
-       { "ws_prior",           priorws,        {0} },
-       { "screen_next",        cyclescr,       {.id = SWM_ARG_ID_CYCLESC_UP} },
-       { "screen_prev",        cyclescr,       {.id = SWM_ARG_ID_CYCLESC_DOWN} },
-       { "mvws_1",             send_to_ws,     {.id = 0} },
-       { "mvws_2",             send_to_ws,     {.id = 1} },
-       { "mvws_3",             send_to_ws,     {.id = 2} },
-       { "mvws_4",             send_to_ws,     {.id = 3} },
-       { "mvws_5",             send_to_ws,     {.id = 4} },
-       { "mvws_6",             send_to_ws,     {.id = 5} },
-       { "mvws_7",             send_to_ws,     {.id = 6} },
-       { "mvws_8",             send_to_ws,     {.id = 7} },
-       { "mvws_9",             send_to_ws,     {.id = 8} },
-       { "mvws_10",            send_to_ws,     {.id = 9} },
-       { "bar_toggle",         bar_toggle,     {0} },
-       { "wind_kill",          wkill,          {.id = SWM_ARG_ID_KILLWINDOW} },
-       { "wind_del",           wkill,          {.id = SWM_ARG_ID_DELETEWINDOW} },
-       { "screenshot_all",     legacyfunc,     {0} },
-       { "screenshot_wind",    legacyfunc,     {0} },
-       { "float_toggle",       floating_toggle,{0} },
-       { "version",            version,        {0} },
-       { "spawn_lock",         legacyfunc,     {0} },
-       { "spawn_initscr",      legacyfunc,     {0} },
-       { "spawn_custom",       dummykeyfunc,   {0} },
-       { "iconify",            iconify,        {0} },
-       { "uniconify",          uniconify,      {0} },
-       { "raise_toggle",       raise_toggle,   {0} },
-       { "button2",            pressbutton,    {2} },
-       { "width_shrink",       resize_step,    {.id = SWM_ARG_ID_WIDTHSHRINK} },
-       { "width_grow",         resize_step,    {.id = SWM_ARG_ID_WIDTHGROW} },
-       { "height_shrink",      resize_step,    {.id = SWM_ARG_ID_HEIGHTSHRINK} },
-       { "height_grow",        resize_step,    {.id = SWM_ARG_ID_HEIGHTGROW} },
-       { "move_left",          move_step,      {.id = SWM_ARG_ID_MOVELEFT} },
-       { "move_right",         move_step,      {.id = SWM_ARG_ID_MOVERIGHT} },
-       { "move_up",            move_step,      {.id = SWM_ARG_ID_MOVEUP} },
-       { "move_down",          move_step,      {.id = SWM_ARG_ID_MOVEDOWN} },
-       { "name_workspace",     name_workspace, {0} },
-       { "search_workspace",   search_workspace,       {0} },
-       { "search_win",         search_win,     {0} },
-       { "dumpwins",           dumpwins,       {0} }, /* MUST BE LAST */
-       { "invalid key func",   NULL,           {0} },
-};
-struct key {
-       RB_ENTRY(key)           entry;
-       unsigned int            mod;
-       KeySym                  keysym;
-       enum keyfuncid          funcid;
-       char                    *spawn_name;
-};
-RB_HEAD(key_list, key);
-
-int
-key_cmp(struct key *kp1, struct key *kp2)
-{
-       if (kp1->keysym < kp2->keysym)
-               return (-1);
-       if (kp1->keysym > kp2->keysym)
-               return (1);
-
-       if (kp1->mod < kp2->mod)
-               return (-1);
-       if (kp1->mod > kp2->mod)
-               return (1);
-
-       return (0);
-}
-
-RB_GENERATE_STATIC(key_list, key, entry, key_cmp);
-struct key_list                        keys;
-
-/* mouse */
-enum { client_click, root_click };
-struct button {
-       unsigned int            action;
-       unsigned int            mask;
-       unsigned int            button;
-       void                    (*func)(struct ws_win *, union arg *);
-       union arg               args;
-} buttons[] = {
-         /* action     key             mouse button    func    args */
-       { client_click, MODKEY,         Button3,        resize, {.id = SWM_ARG_ID_DONTCENTER} },
-       { client_click, MODKEY | ShiftMask, Button3,    resize, {.id = SWM_ARG_ID_CENTER} },
-       { client_click, MODKEY,         Button1,        move,   {0} },
-};
-
-void
-update_modkey(unsigned int mod)
-{
-       int                     i;
-       struct key              *kp;
-
-       mod_key = mod;
-       RB_FOREACH(kp, key_list, &keys)
-               if (kp->mod & ShiftMask)
-                       kp->mod = mod | ShiftMask;
-               else
-                       kp->mod = mod;
-
-       for (i = 0; i < LENGTH(buttons); i++)
-               if (buttons[i].mask & ShiftMask)
-                       buttons[i].mask = mod | ShiftMask;
-               else
-                       buttons[i].mask = mod;
-}
-
-/* spawn */
-struct spawn_prog {
-       TAILQ_ENTRY(spawn_prog) entry;
-       char                    *name;
-       int                     argc;
-       char                    **argv;
-};
-TAILQ_HEAD(spawn_list, spawn_prog);
-struct spawn_list              spawns = TAILQ_HEAD_INITIALIZER(spawns);
-
-int
-spawn_expand(struct swm_region *r, union arg *args, char *spawn_name,
-    char ***ret_args)
-{
-       struct spawn_prog       *prog = NULL;
-       int                     i;
-       char                    *ap, **real_args;
-
-       DNPRINTF(SWM_D_SPAWN, "spawn_expand: %s\n", spawn_name);
-
-       /* find program */
-       TAILQ_FOREACH(prog, &spawns, entry) {
-               if (!strcasecmp(spawn_name, prog->name))
-                       break;
-       }
-       if (prog == NULL) {
-               warnx("spawn_custom: program %s not found", spawn_name);
-               return (-1);
-       }
-
-       /* make room for expanded args */
-       if ((real_args = calloc(prog->argc + 1, sizeof(char *))) == NULL)
-               err(1, "spawn_custom: calloc real_args");
-
-       /* expand spawn_args into real_args */
-       for (i = 0; i < prog->argc; i++) {
-               ap = prog->argv[i];
-               DNPRINTF(SWM_D_SPAWN, "spawn_custom: raw arg: %s\n", ap);
-               if (!strcasecmp(ap, "$bar_border")) {
-                       if ((real_args[i] =
-                           strdup(r->s->c[SWM_S_COLOR_BAR_BORDER].name))
-                           == NULL)
-                               err(1,  "spawn_custom border color");
-               } else if (!strcasecmp(ap, "$bar_color")) {
-                       if ((real_args[i] =
-                           strdup(r->s->c[SWM_S_COLOR_BAR].name))
-                           == NULL)
-                               err(1, "spawn_custom bar color");
-               } else if (!strcasecmp(ap, "$bar_font")) {
-                       if ((real_args[i] = strdup(bar_fonts))
-                           == NULL)
-                               err(1, "spawn_custom bar fonts");
-               } else if (!strcasecmp(ap, "$bar_font_color")) {
-                       if ((real_args[i] =
-                           strdup(r->s->c[SWM_S_COLOR_BAR_FONT].name))
-                           == NULL)
-                               err(1, "spawn_custom color font");
-               } else if (!strcasecmp(ap, "$color_focus")) {
-                       if ((real_args[i] =
-                           strdup(r->s->c[SWM_S_COLOR_FOCUS].name))
-                           == NULL)
-                               err(1, "spawn_custom color focus");
-               } else if (!strcasecmp(ap, "$color_unfocus")) {
-                       if ((real_args[i] =
-                           strdup(r->s->c[SWM_S_COLOR_UNFOCUS].name))
-                           == NULL)
-                               err(1, "spawn_custom color unfocus");
-               } else {
-                       /* no match --> copy as is */
-                       if ((real_args[i] = strdup(ap)) == NULL)
-                               err(1, "spawn_custom strdup(ap)");
-               }
-               DNPRINTF(SWM_D_SPAWN, "spawn_custom: cooked arg: %s\n",
-                   real_args[i]);
-       }
-
-#ifdef SWM_DEBUG
-       DNPRINTF(SWM_D_SPAWN, "spawn_custom: result: ");
-       for (i = 0; i < prog->argc; i++)
-               DNPRINTF(SWM_D_SPAWN, "\"%s\" ", real_args[i]);
-       DNPRINTF(SWM_D_SPAWN, "\n");
-#endif
-       *ret_args = real_args;
-       return (prog->argc);
-}
-
-void
-spawn_custom(struct swm_region *r, union arg *args, char *spawn_name)
-{
-       union arg               a;
-       char                    **real_args;
-       int                     spawn_argc, i;
-
-       if ((spawn_argc = spawn_expand(r, args, spawn_name, &real_args)) < 0)
-               return;
-       a.argv = real_args;
-       if (fork() == 0)
-               spawn(r->ws->idx, &a, 1);
-
-       for (i = 0; i < spawn_argc; i++)
-               free(real_args[i]);
-       free(real_args);
-}
-
-void
-spawn_select(struct swm_region *r, union arg *args, char *spawn_name, int *pid)
-{
-       union arg               a;
-       char                    **real_args;
-       int                     i, spawn_argc;
-
-       if ((spawn_argc = spawn_expand(r, args, spawn_name, &real_args)) < 0)
-               return;
-       a.argv = real_args;
-
-       if (pipe(select_list_pipe) == -1)
-               err(1, "pipe error");
-       if (pipe(select_resp_pipe) == -1)
-               err(1, "pipe error");
-
-       if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
-               err(1, "could not disable SIGPIPE");
-       switch (*pid = fork()) {
-       case -1:
-               err(1, "cannot fork");
-               break;
-       case 0: /* child */
-               if (dup2(select_list_pipe[0], 0) == -1)
-                       err(1, "dup2");
-               if (dup2(select_resp_pipe[1], 1) == -1)
-                       err(1, "dup2");
-               close(select_list_pipe[1]);
-               close(select_resp_pipe[0]);
-               spawn(r->ws->idx, &a, 0);
-               break;
-       default: /* parent */
-               close(select_list_pipe[0]);
-               close(select_resp_pipe[1]);
-               break;
-       }
-
-       for (i = 0; i < spawn_argc; i++)
-               free(real_args[i]);
-       free(real_args);
-}
-
-void
-spawn_insert(char *name, char *args)
-{
-       char                    *arg, *cp, *ptr;
-       struct spawn_prog       *sp;
-
-       DNPRINTF(SWM_D_SPAWN, "spawn_insert: %s\n", name);
-
-       if ((sp = calloc(1, sizeof *sp)) == NULL)
-               err(1, "spawn_insert: malloc");
-       if ((sp->name = strdup(name)) == NULL)
-               err(1, "spawn_insert: strdup");
-
-       /* convert the arguments to an argument list */
-       if ((ptr = cp = strdup(args)) == NULL)
-               err(1, "spawn_insert: strdup");
-       while ((arg = strsep(&ptr, " \t")) != NULL) {
-               /* empty field; skip it */
-               if (*arg == '\0')
-                       continue;
-
-               sp->argc++;
-               if ((sp->argv = realloc(sp->argv, sp->argc *
-                   sizeof *sp->argv)) == NULL)
-                       err(1, "spawn_insert: realloc");
-               if ((sp->argv[sp->argc - 1] = strdup(arg)) == NULL)
-                       err(1, "spawn_insert: strdup");
-       }
-       free(cp);
-
-       TAILQ_INSERT_TAIL(&spawns, sp, entry);
-       DNPRINTF(SWM_D_SPAWN, "spawn_insert: leave\n");
-}
-
-void
-spawn_remove(struct spawn_prog *sp)
-{
-       int                     i;
-
-       DNPRINTF(SWM_D_SPAWN, "spawn_remove: %s\n", sp->name);
-
-       TAILQ_REMOVE(&spawns, sp, entry);
-       for (i = 0; i < sp->argc; i++)
-               free(sp->argv[i]);
-       free(sp->argv);
-       free(sp->name);
-       free(sp);
-
-       DNPRINTF(SWM_D_SPAWN, "spawn_remove: leave\n");
-}
-
-void
-spawn_replace(struct spawn_prog *sp, char *name, char *args)
-{
-       DNPRINTF(SWM_D_SPAWN, "spawn_replace: %s [%s]\n", sp->name, name);
-
-       spawn_remove(sp);
-       spawn_insert(name, args);
-
-       DNPRINTF(SWM_D_SPAWN, "spawn_replace: leave\n");
-}
-
-void
-setspawn(char *name, char *args)
-{
-       struct spawn_prog       *sp;
-
-       DNPRINTF(SWM_D_SPAWN, "setspawn: %s\n", name);
-
-       if (name == NULL)
-               return;
-
-       TAILQ_FOREACH(sp, &spawns, entry) {
-               if (!strcmp(sp->name, name)) {
-                       if (*args == '\0')
-                               spawn_remove(sp);
-                       else
-                               spawn_replace(sp, name, args);
-                       DNPRINTF(SWM_D_SPAWN, "setspawn: leave\n");
-                       return;
-               }
-       }
-       if (*args == '\0') {
-               warnx("error: setspawn: cannot find program: %s", name);
-               return;
-       }
-
-       spawn_insert(name, args);
-       DNPRINTF(SWM_D_SPAWN, "setspawn: leave\n");
-}
-
-int
-setconfspawn(char *selector, char *value, int flags)
-{
-       DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, value);
-
-       setspawn(selector, value);
-
-       DNPRINTF(SWM_D_SPAWN, "setconfspawn: done\n");
-       return (0);
-}
-
-void
-setup_spawn(void)
-{
-       setconfspawn("term",            "xterm",                0);
-       setconfspawn("screenshot_all",  "screenshot.sh full",   0);
-       setconfspawn("screenshot_wind", "screenshot.sh window", 0);
-       setconfspawn("lock",            "xlock",                0);
-       setconfspawn("initscr",         "initscreen.sh",        0);
-       setconfspawn("menu",            "dmenu_run"
-                                       " -fn $bar_font"
-                                       " -nb $bar_color"
-                                       " -nf $bar_font_color"
-                                       " -sb $bar_border"
-                                       " -sf $bar_color",      0);
-       setconfspawn("search",          "dmenu"
-                                       " -i"
-                                       " -fn $bar_font"
-                                       " -nb $bar_color"
-                                       " -nf $bar_font_color"
-                                       " -sb $bar_border"
-                                       " -sf $bar_color",      0);
-       setconfspawn("name_workspace",  "dmenu"
-                                       " -p Workspace"
-                                       " -fn $bar_font"
-                                       " -nb $bar_color"
-                                       " -nf $bar_font_color"
-                                       " -sb $bar_border"
-                                       " -sf $bar_color",      0);
-}
-
-/* key bindings */
-#define SWM_MODNAME_SIZE       32
-#define        SWM_KEY_WS              "\n+ \t"
-int
-parsekeys(char *keystr, unsigned int currmod, unsigned int *mod, KeySym *ks)
-{
-       char                    *cp, *name;
-       KeySym                  uks;
-       DNPRINTF(SWM_D_KEY, "parsekeys: enter [%s]\n", keystr);
-       if (mod == NULL || ks == NULL) {
-               DNPRINTF(SWM_D_KEY, "parsekeys: no mod or key vars\n");
-               return (1);
-       }
-       if (keystr == NULL || strlen(keystr) == 0) {
-               DNPRINTF(SWM_D_KEY, "parsekeys: no keystr\n");
-               return (1);
-       }
-       cp = keystr;
-       *ks = NoSymbol;
-       *mod = 0;
-       while ((name = strsep(&cp, SWM_KEY_WS)) != NULL) {
-               DNPRINTF(SWM_D_KEY, "parsekeys: key [%s]\n", name);
-               if (cp)
-                       cp += (long)strspn(cp, SWM_KEY_WS);
-               if (strncasecmp(name, "MOD", SWM_MODNAME_SIZE) == 0)
-                       *mod |= currmod;
-               else if (!strncasecmp(name, "Mod1", SWM_MODNAME_SIZE))
-                       *mod |= Mod1Mask;
-               else if (!strncasecmp(name, "Mod2", SWM_MODNAME_SIZE))
-                       *mod += Mod2Mask;
-               else if (!strncmp(name, "Mod3", SWM_MODNAME_SIZE))
-                       *mod |= Mod3Mask;
-               else if (!strncmp(name, "Mod4", SWM_MODNAME_SIZE))
-                       *mod |= Mod4Mask;
-               else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0)
-                       *mod |= ShiftMask;
-               else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0)
-                       *mod |= ControlMask;
-               else {
-                       *ks = XStringToKeysym(name);
-                       XConvertCase(*ks, ks, &uks);
-                       if (ks == NoSymbol) {
-                               DNPRINTF(SWM_D_KEY,
-                                   "parsekeys: invalid key %s\n",
-                                   name);
-                               return (1);
-                       }
-               }
-       }
-       DNPRINTF(SWM_D_KEY, "parsekeys: leave ok\n");
-       return (0);
-}
-
-char *
-strdupsafe(char *str)
-{
-       if (str == NULL)
-               return (NULL);
-       else
-               return (strdup(str));
-}
-
-void
-key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid, char *spawn_name)
-{
-       struct key              *kp;
-
-       DNPRINTF(SWM_D_KEY, "key_insert: enter %s [%s]\n",
-           keyfuncs[kfid].name, spawn_name);
-
-       if ((kp = malloc(sizeof *kp)) == NULL)
-               err(1, "key_insert: malloc");
-
-       kp->mod = mod;
-       kp->keysym = ks;
-       kp->funcid = kfid;
-       kp->spawn_name = strdupsafe(spawn_name);
-       RB_INSERT(key_list, &keys, kp);
-
-       DNPRINTF(SWM_D_KEY, "key_insert: leave\n");
-}
-
-struct key *
-key_lookup(unsigned int mod, KeySym ks)
-{
-       struct key              kp;
-
-       kp.keysym = ks;
-       kp.mod = mod;
-
-       return (RB_FIND(key_list, &keys, &kp));
-}
-
-void
-key_remove(struct key *kp)
-{
-       DNPRINTF(SWM_D_KEY, "key_remove: %s\n", keyfuncs[kp->funcid].name);
-
-       RB_REMOVE(key_list, &keys, kp);
-       free(kp->spawn_name);
-       free(kp);
-
-       DNPRINTF(SWM_D_KEY, "key_remove: leave\n");
-}
-
-void
-key_replace(struct key *kp, unsigned int mod, KeySym ks, enum keyfuncid kfid,
-    char *spawn_name)
-{
-       DNPRINTF(SWM_D_KEY, "key_replace: %s [%s]\n", keyfuncs[kp->funcid].name,
-           spawn_name);
-
-       key_remove(kp);
-       key_insert(mod, ks, kfid, spawn_name);
-
-       DNPRINTF(SWM_D_KEY, "key_replace: leave\n");
-}
-
-void
-setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid,
-    char *spawn_name)
-{
-       struct key              *kp;
-
-       DNPRINTF(SWM_D_KEY, "setkeybinding: enter %s [%s]\n",
-           keyfuncs[kfid].name, spawn_name);
-
-       if ((kp = key_lookup(mod, ks)) != NULL) {
-               if (kfid == kf_invalid)
-                       key_remove(kp);
-               else
-                       key_replace(kp, mod, ks, kfid, spawn_name);
-               DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
-               return;
-       }
-       if (kfid == kf_invalid) {
-               warnx("error: setkeybinding: cannot find mod/key combination");
-               DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
-               return;
-       }
-
-       key_insert(mod, ks, kfid, spawn_name);
-       DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
-}
-
-int
-setconfbinding(char *selector, char *value, int flags)
-{
-       enum keyfuncid          kfid;
-       unsigned int            mod;
-       KeySym                  ks;
-       struct spawn_prog       *sp;
-       DNPRINTF(SWM_D_KEY, "setconfbinding: enter\n");
-       if (selector == NULL) {
-               DNPRINTF(SWM_D_KEY, "setconfbinding: unbind %s\n", value);
-               if (parsekeys(value, mod_key, &mod, &ks) == 0) {
-                       kfid = kf_invalid;
-                       setkeybinding(mod, ks, kfid, NULL);
-                       return (0);
-               } else
-                       return (1);
-       }
-       /* search by key function name */
-       for (kfid = 0; kfid < kf_invalid; (kfid)++) {
-               if (strncasecmp(selector, keyfuncs[kfid].name,
-                   SWM_FUNCNAME_LEN) == 0) {
-                       DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match\n",
-                           selector);
-                       if (parsekeys(value, mod_key, &mod, &ks) == 0) {
-                               setkeybinding(mod, ks, kfid, NULL);
-                               return (0);
-                       } else
-                               return (1);
-               }
-       }
-       /* search by custom spawn name */
-       TAILQ_FOREACH(sp, &spawns, entry) {
-               if (strcasecmp(selector, sp->name) == 0) {
-                       DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match\n",
-                           selector);
-                       if (parsekeys(value, mod_key, &mod, &ks) == 0) {
-                               setkeybinding(mod, ks, kf_spawn_custom,
-                                   sp->name);
-                               return (0);
-                       } else
-                               return (1);
-               }
-       }
-       DNPRINTF(SWM_D_KEY, "setconfbinding: no match\n");
-       return (1);
-}
-
-void
-setup_keys(void)
-{
-       setkeybinding(MODKEY,           XK_space,       kf_cycle_layout,NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_backslash,   kf_flip_layout, NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_space,       kf_stack_reset, NULL);
-       setkeybinding(MODKEY,           XK_h,           kf_master_shrink,NULL);
-       setkeybinding(MODKEY,           XK_l,           kf_master_grow, NULL);
-       setkeybinding(MODKEY,           XK_comma,       kf_master_add,  NULL);
-       setkeybinding(MODKEY,           XK_period,      kf_master_del,  NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_comma,       kf_stack_inc,   NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_period,      kf_stack_dec,   NULL);
-       setkeybinding(MODKEY,           XK_Return,      kf_swap_main,   NULL);
-       setkeybinding(MODKEY,           XK_j,           kf_focus_next,  NULL);
-       setkeybinding(MODKEY,           XK_k,           kf_focus_prev,  NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_j,           kf_swap_next,   NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_k,           kf_swap_prev,   NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_Return,      kf_spawn_term,  NULL);
-       setkeybinding(MODKEY,           XK_p,           kf_spawn_custom,"menu");
-       setkeybinding(MODKEY|ShiftMask, XK_q,           kf_quit,        NULL);
-       setkeybinding(MODKEY,           XK_q,           kf_restart,     NULL);
-       setkeybinding(MODKEY,           XK_m,           kf_focus_main,  NULL);
-       setkeybinding(MODKEY,           XK_1,           kf_ws_1,        NULL);
-       setkeybinding(MODKEY,           XK_2,           kf_ws_2,        NULL);
-       setkeybinding(MODKEY,           XK_3,           kf_ws_3,        NULL);
-       setkeybinding(MODKEY,           XK_4,           kf_ws_4,        NULL);
-       setkeybinding(MODKEY,           XK_5,           kf_ws_5,        NULL);
-       setkeybinding(MODKEY,           XK_6,           kf_ws_6,        NULL);
-       setkeybinding(MODKEY,           XK_7,           kf_ws_7,        NULL);
-       setkeybinding(MODKEY,           XK_8,           kf_ws_8,        NULL);
-       setkeybinding(MODKEY,           XK_9,           kf_ws_9,        NULL);
-       setkeybinding(MODKEY,           XK_0,           kf_ws_10,       NULL);
-       setkeybinding(MODKEY,           XK_Right,       kf_ws_next,     NULL);
-       setkeybinding(MODKEY,           XK_Left,        kf_ws_prev,     NULL);
-       setkeybinding(MODKEY,           XK_Up,          kf_ws_next_all, NULL);
-       setkeybinding(MODKEY,           XK_Down,        kf_ws_prev_all, NULL);
-       setkeybinding(MODKEY,           XK_a,           kf_ws_prior,    NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_Right,       kf_screen_next, NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_Left,        kf_screen_prev, NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_1,           kf_mvws_1,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_2,           kf_mvws_2,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_3,           kf_mvws_3,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_4,           kf_mvws_4,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_5,           kf_mvws_5,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_6,           kf_mvws_6,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_7,           kf_mvws_7,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_8,           kf_mvws_8,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_9,           kf_mvws_9,      NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_0,           kf_mvws_10,     NULL);
-       setkeybinding(MODKEY,           XK_b,           kf_bar_toggle,  NULL);
-       setkeybinding(MODKEY,           XK_Tab,         kf_focus_next,  NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_Tab,         kf_focus_prev,  NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_x,           kf_wind_kill,   NULL);
-       setkeybinding(MODKEY,           XK_x,           kf_wind_del,    NULL);
-       setkeybinding(MODKEY,           XK_s,           kf_spawn_custom,"screenshot_all");
-       setkeybinding(MODKEY|ShiftMask, XK_s,           kf_spawn_custom,"screenshot_wind");
-       setkeybinding(MODKEY,           XK_t,           kf_float_toggle,NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_v,           kf_version,     NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_Delete,      kf_spawn_custom,"lock");
-       setkeybinding(MODKEY|ShiftMask, XK_i,           kf_spawn_custom,"initscr");
-       setkeybinding(MODKEY,           XK_w,           kf_iconify,     NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_w,           kf_uniconify,   NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_r,           kf_raise_toggle,NULL);
-       setkeybinding(MODKEY,           XK_v,           kf_button2,     NULL);
-       setkeybinding(MODKEY,           XK_equal,       kf_width_grow,  NULL);
-       setkeybinding(MODKEY,           XK_minus,       kf_width_shrink,NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_equal,       kf_height_grow, NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_minus,       kf_height_shrink,NULL);
-       setkeybinding(MODKEY,           XK_bracketleft, kf_move_left,   NULL);
-       setkeybinding(MODKEY,           XK_bracketright,kf_move_right,  NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_bracketleft, kf_move_up,     NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_bracketright,kf_move_down,   NULL);
-       setkeybinding(MODKEY|ShiftMask, XK_slash,       kf_name_workspace,NULL);
-       setkeybinding(MODKEY,           XK_slash,       kf_search_workspace,NULL);
-       setkeybinding(MODKEY,           XK_f,           kf_search_win,  NULL);
-#ifdef SWM_DEBUG
-       setkeybinding(MODKEY|ShiftMask, XK_d,           kf_dumpwins,    NULL);
-#endif
-}
-
-void
-clear_keys(void)
-{
-       struct key              *kp;
-
-       while (RB_EMPTY(&keys) == 0) {
-               kp = RB_ROOT(&keys);
-               key_remove(kp);
-       }
-}
-
-int
-setkeymapping(char *selector, char *value, int flags)
-{
-       char                    keymapping_file[PATH_MAX];
-       DNPRINTF(SWM_D_KEY, "setkeymapping: enter\n");
-       if (value[0] == '~')
-               snprintf(keymapping_file, sizeof keymapping_file, "%s/%s",
-                   pwd->pw_dir, &value[1]);
-       else
-               strlcpy(keymapping_file, value, sizeof keymapping_file);
-       clear_keys();
-       /* load new key bindings; if it fails, revert to default bindings */
-       if (conf_load(keymapping_file, SWM_CONF_KEYMAPPING)) {
-               clear_keys();
-               setup_keys();
-       }
-       DNPRINTF(SWM_D_KEY, "setkeymapping: leave\n");
-       return (0);
-}
-
-void
-updatenumlockmask(void)
-{
-       unsigned int            i, j;
-       XModifierKeymap         *modmap;
-
-       DNPRINTF(SWM_D_MISC, "updatenumlockmask\n");
-       numlockmask = 0;
-       modmap = XGetModifierMapping(display);
-       for (i = 0; i < 8; i++)
-               for (j = 0; j < modmap->max_keypermod; j++)
-                       if (modmap->modifiermap[i * modmap->max_keypermod + j]
-                           == XKeysymToKeycode(display, XK_Num_Lock))
-                               numlockmask = (1 << i);
-
-       XFreeModifiermap(modmap);
-}
-
-void
-grabkeys(void)
-{
-       unsigned int            j, k;
-       KeyCode                 code;
-       unsigned int            modifiers[] =
-           { 0, LockMask, numlockmask, numlockmask | LockMask };
-       struct key              *kp;
-
-       DNPRINTF(SWM_D_MISC, "grabkeys\n");
-       updatenumlockmask();
-
-       for (k = 0; k < ScreenCount(display); k++) {
-               if (TAILQ_EMPTY(&screens[k].rl))
-                       continue;
-               XUngrabKey(display, AnyKey, AnyModifier, screens[k].root);
-               RB_FOREACH(kp, key_list, &keys) {
-                       if ((code = XKeysymToKeycode(display, kp->keysym)))
-                               for (j = 0; j < LENGTH(modifiers); j++)
-                                       XGrabKey(display, code,
-                                           kp->mod | modifiers[j],
-                                           screens[k].root, True,
-                                           GrabModeAsync, GrabModeAsync);
-               }
-       }
-}
-
-void
-grabbuttons(struct ws_win *win, int focused)
-{
-       unsigned int            i, j;
-       unsigned int            modifiers[] =
-           { 0, LockMask, numlockmask, numlockmask|LockMask };
-
-       updatenumlockmask();
-       XUngrabButton(display, AnyButton, AnyModifier, win->id);
-       if (focused) {
-               for (i = 0; i < LENGTH(buttons); i++)
-                       if (buttons[i].action == client_click)
-                               for (j = 0; j < LENGTH(modifiers); j++)
-                                       XGrabButton(display, buttons[i].button,
-                                           buttons[i].mask | modifiers[j],
-                                           win->id, False, BUTTONMASK,
-                                           GrabModeAsync, GrabModeSync, None,
-                                           None);
-       } else
-               XGrabButton(display, AnyButton, AnyModifier, win->id, False,
-                   BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
-}
-
-const char *quirkname[] = {
-       "NONE",         /* config string for "no value" */
-       "FLOAT",
-       "TRANSSZ",
-       "ANYWHERE",
-       "XTERM_FONTADJ",
-       "FULLSCREEN",
-       "FOCUSPREV",
-};
-
-/* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */
-#define        SWM_Q_WS                "\n|+ \t"
-int
-parsequirks(char *qstr, unsigned long *quirk)
-{
-       char                    *cp, *name;
-       int                     i;
-
-       if (quirk == NULL)
-               return (1);
-
-       cp = qstr;
-       *quirk = 0;
-       while ((name = strsep(&cp, SWM_Q_WS)) != NULL) {
-               if (cp)
-                       cp += (long)strspn(cp, SWM_Q_WS);
-               for (i = 0; i < LENGTH(quirkname); i++) {
-                       if (!strncasecmp(name, quirkname[i], SWM_QUIRK_LEN)) {
-                               DNPRINTF(SWM_D_QUIRK,
-                                   "parsequirks: %s\n", name);
-                               if (i == 0) {
-                                       *quirk = 0;
-                                       return (0);
-                               }
-                               *quirk |= 1 << (i-1);
-                               break;
-                       }
-               }
-               if (i >= LENGTH(quirkname)) {
-                       DNPRINTF(SWM_D_QUIRK,
-                           "parsequirks: invalid quirk [%s]\n", name);
-                       return (1);
-               }
-       }
-       return (0);
-}
-
-void
-quirk_insert(const char *class, const char *name, unsigned long quirk)
-{
-       struct quirk            *qp;
-
-       DNPRINTF(SWM_D_QUIRK, "quirk_insert: %s:%s [%lu]\n", class, name,
-           quirk);
-
-       if ((qp = malloc(sizeof *qp)) == NULL)
-               err(1, "quirk_insert: malloc");
-       if ((qp->class = strdup(class)) == NULL)
-               err(1, "quirk_insert: strdup");
-       if ((qp->name = strdup(name)) == NULL)
-               err(1, "quirk_insert: strdup");
-
-       qp->quirk = quirk;
-       TAILQ_INSERT_TAIL(&quirks, qp, entry);
-
-       DNPRINTF(SWM_D_QUIRK, "quirk_insert: leave\n");
-}
-
-void
-quirk_remove(struct quirk *qp)
-{
-       DNPRINTF(SWM_D_QUIRK, "quirk_remove: %s:%s [%lu]\n", qp->class,
-           qp->name, qp->quirk);
-
-       TAILQ_REMOVE(&quirks, qp, entry);
-       free(qp->class);
-       free(qp->name);
-       free(qp);
-
-       DNPRINTF(SWM_D_QUIRK, "quirk_remove: leave\n");
-}
-
-void
-quirk_replace(struct quirk *qp, const char *class, const char *name,
-    unsigned long quirk)
-{
-       DNPRINTF(SWM_D_QUIRK, "quirk_replace: %s:%s [%lu]\n", qp->class,
-           qp->name, qp->quirk);
-
-       quirk_remove(qp);
-       quirk_insert(class, name, quirk);
-
-       DNPRINTF(SWM_D_QUIRK, "quirk_replace: leave\n");
-}
-
-void
-setquirk(const char *class, const char *name, unsigned long quirk)
-{
-       struct quirk            *qp;
-
-       DNPRINTF(SWM_D_QUIRK, "setquirk: enter %s:%s [%lu]\n", class, name,
-          quirk);
-
-       TAILQ_FOREACH(qp, &quirks, entry) {
-               if (!strcmp(qp->class, class) && !strcmp(qp->name, name)) {
-                       if (!quirk)
-                               quirk_remove(qp);
-                       else
-                               quirk_replace(qp, class, name, quirk);
-                       DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
-                       return;
-               }
-       }
-       if (!quirk) {
-               warnx("error: setquirk: cannot find class/name combination");
-               return;
-       }
-
-       quirk_insert(class, name, quirk);
-       DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
-}
-
-int
-setconfquirk(char *selector, char *value, int flags)
-{
-       char                    *cp, *class, *name;
-       int                     retval;
-       unsigned long           quirks;
-       if (selector == NULL)
-               return (0);
-       if ((cp = strchr(selector, ':')) == NULL)
-               return (0);
-       *cp = '\0';
-       class = selector;
-       name = cp + 1;
-       if ((retval = parsequirks(value, &quirks)) == 0)
-               setquirk(class, name, quirks);
-       return (retval);
-}
-
-void
-setup_quirks(void)
-{
-       setquirk("MPlayer",             "xv",           SWM_Q_FLOAT | SWM_Q_FULLSCREEN | SWM_Q_FOCUSPREV);
-       setquirk("OpenOffice.org 3.2",  "VCLSalFrame",  SWM_Q_FLOAT);
-       setquirk("Firefox-bin",         "firefox-bin",  SWM_Q_TRANSSZ);
-       setquirk("Firefox",             "Dialog",       SWM_Q_FLOAT);
-       setquirk("Gimp",                "gimp",         SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("XTerm",               "xterm",        SWM_Q_XTERM_FONTADJ);
-       setquirk("xine",                "Xine Window",  SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("Xitk",                "Xitk Combo",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("xine",                "xine Panel",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("Xitk",                "Xine Window",  SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("xine",                "xine Video Fullscreen Window", SWM_Q_FULLSCREEN | SWM_Q_FLOAT);
-       setquirk("pcb",                 "pcb",          SWM_Q_FLOAT);
-       setquirk("SDL_App",             "SDL_App",      SWM_Q_FLOAT | SWM_Q_FULLSCREEN);
-}
-
-/* conf file stuff */
-#define SWM_CONF_FILE  "scrotwm.conf"
-
-enum   { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_BAR_BORDER_WIDTH,
-         SWM_S_STACK_ENABLED, SWM_S_CLOCK_ENABLED, SWM_S_CLOCK_FORMAT,
-         SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, SWM_S_SS_ENABLED,
-         SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED,
-         SWM_S_TITLE_NAME_ENABLED, SWM_S_WINDOW_NAME_ENABLED, SWM_S_URGENT_ENABLED,
-         SWM_S_FOCUS_MODE, SWM_S_DISABLE_BORDER, SWM_S_BORDER_WIDTH,
-         SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM,
-         SWM_S_SS_APP, SWM_S_DIALOG_RATIO, SWM_S_BAR_AT_BOTTOM,
-         SWM_S_VERBOSE_LAYOUT, SWM_S_BAR_JUSTIFY
-       };
-
-int
-setconfvalue(char *selector, char *value, int flags)
-{
-       int     i;
-       char    *b;
-
-       switch (flags) {
-       case SWM_S_BAR_DELAY:
-               bar_delay = atoi(value);
-               break;
-       case SWM_S_BAR_ENABLED:
-               bar_enabled = atoi(value);
-               break;
-       case SWM_S_BAR_BORDER_WIDTH:
-               bar_border_width = atoi(value);
-               break;
-       case SWM_S_BAR_AT_BOTTOM:
-               bar_at_bottom = atoi(value);
-               break;
-       case SWM_S_BAR_JUSTIFY:
-               if (!strcmp(value, "left"))
-                       bar_justify = SWM_BAR_JUSTIFY_LEFT;
-               else if (!strcmp(value, "center"))
-                       bar_justify = SWM_BAR_JUSTIFY_CENTER;
-               else if (!strcmp(value, "right"))
-                       bar_justify = SWM_BAR_JUSTIFY_RIGHT;
-               else
-                       errx(1, "invalid bar_justify");
-               break;
-       case SWM_S_STACK_ENABLED:
-               stack_enabled = atoi(value);
-               break;
-       case SWM_S_CLOCK_ENABLED:
-               clock_enabled = atoi(value);
-               break;
-       case SWM_S_CLOCK_FORMAT:
-#ifndef SWM_DENY_CLOCK_FORMAT
-               free(clock_format);
-               if ((clock_format = strdup(value)) == NULL)
-                       err(1, "setconfvalue: clock_format");
-#endif
-               break;
-       case SWM_S_CYCLE_EMPTY:
-               cycle_empty = atoi(value);
-               break;
-       case SWM_S_CYCLE_VISIBLE:
-               cycle_visible = atoi(value);
-               break;
-       case SWM_S_SS_ENABLED:
-               ss_enabled = atoi(value);
-               break;
-       case SWM_S_TERM_WIDTH:
-               term_width = atoi(value);
-               break;
-       case SWM_S_TITLE_CLASS_ENABLED:
-               title_class_enabled = atoi(value);
-               break;
-       case SWM_S_WINDOW_NAME_ENABLED:
-               window_name_enabled = atoi(value);
-               break;
-       case SWM_S_TITLE_NAME_ENABLED:
-               title_name_enabled = atoi(value);
-               break;
-       case SWM_S_URGENT_ENABLED:
-               urgent_enabled = atoi(value);
-               break;
-       case SWM_S_FOCUS_MODE:
-               if (!strcmp(value, "default"))
-                       focus_mode = SWM_FOCUS_DEFAULT;
-               else if (!strcmp(value, "follow_cursor"))
-                       focus_mode = SWM_FOCUS_FOLLOW;
-               else if (!strcmp(value, "synergy"))
-                       focus_mode = SWM_FOCUS_SYNERGY;
-               else
-                       errx(1, "focus_mode");
-               break;
-       case SWM_S_DISABLE_BORDER:
-               disable_border = atoi(value);
-               break;
-       case SWM_S_BORDER_WIDTH:
-               border_width = atoi(value);
-               break;
-       case SWM_S_BAR_FONT:
-               b = bar_fonts;
-               if (asprintf(&bar_fonts, "%s,%s", value, bar_fonts) == -1)
-                       err(1, "setconfvalue: asprintf: failed to allocate "
-                               "memory for bar_fonts.");
-
-               free(b);
-               break;
-       case SWM_S_BAR_ACTION:
-               free(bar_argv[0]);
-               if ((bar_argv[0] = strdup(value)) == NULL)
-                       err(1, "setconfvalue: bar_action");
-               break;
-       case SWM_S_SPAWN_TERM:
-               free(spawn_term[0]);
-               if ((spawn_term[0] = strdup(value)) == NULL)
-                       err(1, "setconfvalue: spawn_term");
-               break;
-       case SWM_S_SS_APP:
-               break;
-       case SWM_S_DIALOG_RATIO:
-               dialog_ratio = atof(value);
-               if (dialog_ratio > 1.0 || dialog_ratio <= .3)
-                       dialog_ratio = .6;
-               break;
-       case SWM_S_VERBOSE_LAYOUT:
-               verbose_layout = atoi(value);
-               for (i = 0; layouts[i].l_stack != NULL; i++) {
-                       if (verbose_layout)
-                               layouts[i].l_string = fancy_stacker;
-                       else
-                               layouts[i].l_string = plain_stacker;
-               }
-               break;
-       default:
-               return (1);
-       }
-       return (0);
-}
-
-int
-setconfmodkey(char *selector, char *value, int flags)
-{
-       if (!strncasecmp(value, "Mod1", strlen("Mod1")))
-               update_modkey(Mod1Mask);
-       else if (!strncasecmp(value, "Mod2", strlen("Mod2")))
-               update_modkey(Mod2Mask);
-       else if (!strncasecmp(value, "Mod3", strlen("Mod3")))
-               update_modkey(Mod3Mask);
-       else if (!strncasecmp(value, "Mod4", strlen("Mod4")))
-               update_modkey(Mod4Mask);
-       else
-               return (1);
-       return (0);
-}
-
-int
-setconfcolor(char *selector, char *value, int flags)
-{
-       setscreencolor(value, ((selector == NULL)?-1:atoi(selector)), flags);
-       return (0);
-}
-
-int
-setconfregion(char *selector, char *value, int flags)
-{
-       custom_region(value);
-       return (0);
-}
-
-int
-setautorun(char *selector, char *value, int flags)
-{
-       int                     ws_id;
-       char                    s[1024];
-       char                    *ap, *sp = s;
-       union arg               a;
-       int                     argc = 0;
-       long                    pid;
-       struct pid_e            *p;
-
-       if (getenv("SWM_STARTED"))
-               return (0);
-
-       bzero(s, sizeof s);
-       if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2)
-               errx(1, "invalid autorun entry, should be 'ws[<idx>]:command'");
-       ws_id--;
-       if (ws_id < 0 || ws_id >= SWM_WS_MAX)
-               errx(1, "autorun: invalid workspace %d", ws_id + 1);
-
-       /*
-        * This is a little intricate
-        *
-        * If the pid already exists we simply reuse it because it means it was
-        * used before AND not claimed by manage_window.  We get away with
-        * altering it in the parent after INSERT because this can not be a race
-        */
-       a.argv = NULL;
-       while ((ap = strsep(&sp, " \t")) != NULL) {
-               if (*ap == '\0')
-                       continue;
-               DNPRINTF(SWM_D_SPAWN, "setautorun: arg [%s]\n", ap);
-               argc++;
-               if ((a.argv = realloc(a.argv, argc * sizeof(char *))) == NULL)
-                       err(1, "setautorun: realloc");
-               a.argv[argc - 1] = ap;
-       }
-
-       if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL)
-               err(1, "setautorun: realloc");
-       a.argv[argc] = NULL;
-
-       if ((pid = fork()) == 0) {
-               spawn(ws_id, &a, 1);
-               /* NOTREACHED */
-               _exit(1);
-       }
-       free(a.argv);
-
-       /* parent */
-       p = find_pid(pid);
-       if (p == NULL) {
-               p = calloc(1, sizeof *p);
-               if (p == NULL)
-                       return (1);
-               TAILQ_INSERT_TAIL(&pidlist, p, entry);
-       }
-
-       p->pid = pid;
-       p->ws = ws_id;
-
-       return (0);
-}
-
-int
-setlayout(char *selector, char *value, int flags)
-{
-       int                     ws_id, i, x, mg, ma, si, raise;
-       int                     st = SWM_V_STACK;
-       char                    s[1024];
-       struct workspace        *ws;
-
-       if (getenv("SWM_STARTED"))
-               return (0);
-
-       bzero(s, sizeof s);
-       if (sscanf(value, "ws[%d]:%d:%d:%d:%d:%1023c",
-           &ws_id, &mg, &ma, &si, &raise, s) != 6)
-               errx(1, "invalid layout entry, should be 'ws[<idx>]:"
-                   "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
-                   "<type>'");
-       ws_id--;
-       if (ws_id < 0 || ws_id >= SWM_WS_MAX)
-               errx(1, "layout: invalid workspace %d", ws_id + 1);
-
-       if (!strcasecmp(s, "vertical"))
-               st = SWM_V_STACK;
-       else if (!strcasecmp(s, "horizontal"))
-               st = SWM_H_STACK;
-       else if (!strcasecmp(s, "fullscreen"))
-               st = SWM_MAX_STACK;
-       else
-               errx(1, "invalid layout entry, should be 'ws[<idx>]:"
-                   "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
-                   "<type>'");
-
-       for (i = 0; i < ScreenCount(display); i++) {
-               ws = (struct workspace *)&screens[i].ws;
-               ws[ws_id].cur_layout = &layouts[st];
-
-               ws[ws_id].always_raise = raise;
-               if (st == SWM_MAX_STACK)
-                       continue;
-
-               /* master grow */
-               for (x = 0; x < abs(mg); x++) {
-                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
-                           mg >= 0 ?  SWM_ARG_ID_MASTERGROW :
-                           SWM_ARG_ID_MASTERSHRINK);
-                       stack();
-               }
-               /* master add */
-               for (x = 0; x < abs(ma); x++) {
-                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
-                           ma >= 0 ?  SWM_ARG_ID_MASTERADD :
-                           SWM_ARG_ID_MASTERDEL);
-                       stack();
-               }
-               /* stack inc */
-               for (x = 0; x < abs(si); x++) {
-                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
-                           si >= 0 ?  SWM_ARG_ID_STACKINC :
-                           SWM_ARG_ID_STACKDEC);
-                       stack();
-               }
-       }
-
-       return (0);
-}
-
-/* config options */
-struct config_option {
-       char                    *optname;
-       int                     (*func)(char*, char*, int);
-       int                     funcflags;
-};
-struct config_option configopt[] = {
-       { "bar_enabled",                setconfvalue,   SWM_S_BAR_ENABLED },
-       { "bar_at_bottom",              setconfvalue,   SWM_S_BAR_AT_BOTTOM },
-       { "bar_border",                 setconfcolor,   SWM_S_COLOR_BAR_BORDER },
-       { "bar_border_width",           setconfvalue,   SWM_S_BAR_BORDER_WIDTH },
-       { "bar_color",                  setconfcolor,   SWM_S_COLOR_BAR },
-       { "bar_font_color",             setconfcolor,   SWM_S_COLOR_BAR_FONT },
-       { "bar_font",                   setconfvalue,   SWM_S_BAR_FONT },
-       { "bar_action",                 setconfvalue,   SWM_S_BAR_ACTION },
-       { "bar_delay",                  setconfvalue,   SWM_S_BAR_DELAY },
-       { "bar_justify",                setconfvalue,   SWM_S_BAR_JUSTIFY },
-       { "keyboard_mapping",           setkeymapping,  0 },
-       { "bind",                       setconfbinding, 0 },
-       { "stack_enabled",              setconfvalue,   SWM_S_STACK_ENABLED },
-       { "clock_enabled",              setconfvalue,   SWM_S_CLOCK_ENABLED },
-       { "clock_format",               setconfvalue,   SWM_S_CLOCK_FORMAT },
-       { "color_focus",                setconfcolor,   SWM_S_COLOR_FOCUS },
-       { "color_unfocus",              setconfcolor,   SWM_S_COLOR_UNFOCUS },
-       { "cycle_empty",                setconfvalue,   SWM_S_CYCLE_EMPTY },
-       { "cycle_visible",              setconfvalue,   SWM_S_CYCLE_VISIBLE },
-       { "dialog_ratio",               setconfvalue,   SWM_S_DIALOG_RATIO },
-       { "verbose_layout",             setconfvalue,   SWM_S_VERBOSE_LAYOUT },
-       { "modkey",                     setconfmodkey,  0 },
-       { "program",                    setconfspawn,   0 },
-       { "quirk",                      setconfquirk,   0 },
-       { "region",                     setconfregion,  0 },
-       { "spawn_term",                 setconfvalue,   SWM_S_SPAWN_TERM },
-       { "screenshot_enabled",         setconfvalue,   SWM_S_SS_ENABLED },
-       { "screenshot_app",             setconfvalue,   SWM_S_SS_APP },
-       { "window_name_enabled",        setconfvalue,   SWM_S_WINDOW_NAME_ENABLED },
-       { "urgent_enabled",             setconfvalue,   SWM_S_URGENT_ENABLED },
-       { "term_width",                 setconfvalue,   SWM_S_TERM_WIDTH },
-       { "title_class_enabled",        setconfvalue,   SWM_S_TITLE_CLASS_ENABLED },
-       { "title_name_enabled",         setconfvalue,   SWM_S_TITLE_NAME_ENABLED },
-       { "focus_mode",                 setconfvalue,   SWM_S_FOCUS_MODE },
-       { "disable_border",             setconfvalue,   SWM_S_DISABLE_BORDER },
-       { "border_width",               setconfvalue,   SWM_S_BORDER_WIDTH },
-       { "autorun",                    setautorun,     0 },
-       { "layout",                     setlayout,      0 },
-};
-
-
-int
-conf_load(char *filename, int keymapping)
-{
-       FILE                    *config;
-       char                    *line, *cp, *optsub, *optval;
-       size_t                  linelen, lineno = 0;
-       int                     wordlen, i, optind;
-       struct config_option    *opt;
-
-       DNPRINTF(SWM_D_CONF, "conf_load: begin\n");
-
-       if (filename == NULL) {
-               warnx("conf_load: no filename");
-               return (1);
-       }
-       if ((config = fopen(filename, "r")) == NULL) {
-               warn("conf_load: fopen: %s", filename);
-               return (1);
-       }
-
-       while (!feof(config)) {
-               if ((line = fparseln(config, &linelen, &lineno, NULL, 0))
-                   == NULL) {
-                       if (ferror(config))
-                               err(1, "%s", filename);
-                       else
-                               continue;
-               }
-               cp = line;
-               cp += strspn(cp, " \t\n"); /* eat whitespace */
-               if (cp[0] == '\0') {
-                       /* empty line */
-                       free(line);
-                       continue;
-               }
-               /* get config option */
-               wordlen = strcspn(cp, "=[ \t\n");
-               if (wordlen == 0) {
-                       warnx("%s: line %zd: no option found",
-                           filename, lineno);
-                       goto out;
-               }
-               optind = -1;
-               for (i = 0; i < LENGTH(configopt); i++) {
-                       opt = &configopt[i];
-                       if (!strncasecmp(cp, opt->optname, wordlen) &&
-                           strlen(opt->optname) == wordlen) {
-                               optind = i;
-                               break;
-                       }
-               }
-               if (optind == -1) {
-                       warnx("%s: line %zd: unknown option %.*s",
-                           filename, lineno, wordlen, cp);
-                       goto out;
-               }
-               if (keymapping && strcmp(opt->optname, "bind")) {
-                       warnx("%s: line %zd: invalid option %.*s",
-                           filename, lineno, wordlen, cp);
-                       goto out;
-               }
-               cp += wordlen;
-               cp += strspn(cp, " \t\n"); /* eat whitespace */
-               /* get [selector] if any */
-               optsub = NULL;
-               if (*cp == '[') {
-                       cp++;
-                       wordlen = strcspn(cp, "]");
-                       if (*cp != ']') {
-                               if (wordlen == 0) {
-                                       warnx("%s: line %zd: syntax error",
-                                           filename, lineno);
-                                       goto out;
-                               }
-
-                               if (asprintf(&optsub, "%.*s", wordlen, cp) ==
-                                   -1) {
-                                       warnx("%s: line %zd: unable to allocate"
-                                           "memory for selector", filename,
-                                           lineno);
-                                       goto out;
-                               }
-                       }
-                       cp += wordlen;
-                       cp += strspn(cp, "] \t\n"); /* eat trailing */
-               }
-               cp += strspn(cp, "= \t\n"); /* eat trailing */
-               /* get RHS value */
-               optval = strdup(cp);
-               /* call function to deal with it all */
-               if (configopt[optind].func(optsub, optval,
-                   configopt[optind].funcflags) != 0)
-                       errx(1, "%s: line %zd: invalid data for %s",
-                           filename, lineno, configopt[optind].optname);
-               free(optval);
-               free(optsub);
-               free(line);
-       }
-
-       fclose(config);
-       DNPRINTF(SWM_D_CONF, "conf_load: end\n");
-
-       return (0);
-
-out:
-       free(line);
-       fclose(config);
-       DNPRINTF(SWM_D_CONF, "conf_load: end with error.\n");
-
-       return (1);
-}
-
-void
-set_child_transient(struct ws_win *win, Window *trans)
-{
-       struct ws_win           *parent, *w;
-       XWMHints                *wmh = NULL;
-       struct swm_region       *r;
-       struct workspace        *ws;
-
-       parent = find_window(win->transient);
-       if (parent)
-               parent->child_trans = win;
-       else {
-               DNPRINTF(SWM_D_MISC, "set_child_transient: parent doesn't exist"
-                   " for 0x%lx trans 0x%lx\n", win->id, win->transient);
-
-               if (win->hints == NULL) {
-                       warnx("no hints for 0x%lx", win->id);
-                       return;
-               }
-
-               r = root_to_region(win->wa.root);
-               ws = r->ws;
-               /* parent doen't exist in our window list */
-               TAILQ_FOREACH(w, &ws->winlist, entry) {
-                       if (wmh)
-                               XFree(wmh);
-
-                       if ((wmh = XGetWMHints(display, w->id)) == NULL) {
-                               warnx("can't get hints for 0x%lx", w->id);
-                               continue;
-                       }
-
-                       if (win->hints->window_group != wmh->window_group)
-                               continue;
-
-                       w->child_trans = win;
-                       win->transient = w->id;
-                       *trans = w->id;
-                       DNPRINTF(SWM_D_MISC, "set_child_transient: asjusting "
-                           "transient to 0x%lx\n", win->transient);
-                       break;
-               }
-       }
-
-       if (wmh)
-               XFree(wmh);
-}
-
-long
-window_get_pid(Window win)
-{
-       Atom                    actual_type_return;
-       int                     actual_format_return = 0;
-       unsigned long           nitems_return = 0;
-       unsigned long           bytes_after_return = 0;
-       long                    *pid = NULL;
-       long                    ret = 0;
-       const char              *errstr;
-       unsigned char           *prop = NULL;
-
-       if (XGetWindowProperty(display, win,
-           XInternAtom(display, "_NET_WM_PID", False), 0, 1, False,
-           XA_CARDINAL, &actual_type_return, &actual_format_return,
-           &nitems_return, &bytes_after_return,
-           (unsigned char**)(void*)&pid) != Success)
-               goto tryharder;
-       if (actual_type_return != XA_CARDINAL)
-               goto tryharder;
-       if (pid == NULL)
-               goto tryharder;
-
-       ret = *pid;
-       XFree(pid);
-
-       return (ret);
-
-tryharder:
-       if (XGetWindowProperty(display, win,
-           XInternAtom(display, "_SWM_PID", False), 0, SWM_PROPLEN, False,
-           XA_STRING, &actual_type_return, &actual_format_return,
-           &nitems_return, &bytes_after_return, &prop) != Success)
-               return (0);
-       if (actual_type_return != XA_STRING)
-               return (0);
-       if (prop == NULL)
-               return (0);
-
-       ret = strtonum((const char *)prop, 0, UINT_MAX, &errstr);
-       /* ignore error because strtonum returns 0 anyway */
-       XFree(prop);
-
-       return (ret);
-}
-
-struct ws_win *
-manage_window(Window id)
-{
-       Window                  trans = 0;
-       struct workspace        *ws;
-       struct ws_win           *win, *ww;
-       int                     format, i, ws_idx, n, border_me = 0;
-       unsigned long           nitems, bytes;
-       Atom                    ws_idx_atom = 0, type;
-       Atom                    *prot = NULL, *pp;
-       unsigned char           ws_idx_str[SWM_PROPLEN], *prop = NULL;
-       struct swm_region       *r;
-       long                    mask;
-       const char              *errstr;
-       XWindowChanges          wc;
-       struct pid_e            *p;
-       struct quirk            *qp;
-
-       if ((win = find_window(id)) != NULL)
-               return (win);   /* already being managed */
-
-       /* see if we are on the unmanaged list */
-       if ((win = find_unmanaged_window(id)) != NULL) {
-               DNPRINTF(SWM_D_MISC, "manage_window: previously unmanaged "
-                   "window: 0x%lx\n", win->id);
-               TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
-               if (win->transient) {
-                       set_child_transient(win, &trans);
-               } if (trans && (ww = find_window(trans)))
-                       TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
-               else
-                       TAILQ_INSERT_TAIL(&win->ws->winlist, win, entry);
-               ewmh_update_actions(win);
-               return (win);
-       }
-
-       if ((win = calloc(1, sizeof(struct ws_win))) == NULL)
-               err(1, "manage_window: calloc: failed to allocate memory for "
-                   "new window");
-
-       win->id = id;
-
-       /* see if we need to override the workspace */
-       p = find_pid(window_get_pid(id));
-
-       /* Get all the window data in one shot */
-       ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
-       if (ws_idx_atom) {
-               XGetWindowProperty(display, id, ws_idx_atom, 0, SWM_PROPLEN,
-                   False, XA_STRING, &type, &format, &nitems, &bytes, &prop);
-       }
-       XGetWindowAttributes(display, id, &win->wa);
-       XGetWMNormalHints(display, id, &win->sh, &win->sh_mask);
-       win->hints = XGetWMHints(display, id);
-       XGetTransientForHint(display, id, &trans);
-       if (trans) {
-               win->transient = trans;
-               set_child_transient(win, &trans);
-               DNPRINTF(SWM_D_MISC, "manage_window: window: 0x%lx, "
-                   "transient: 0x%lx\n", win->id, win->transient);
-       }
-
-       /* get supported protocols */
-       if (XGetWMProtocols(display, id, &prot, &n)) {
-               for (i = 0, pp = prot; i < n; i++, pp++) {
-                       if (*pp == takefocus)
-                               win->take_focus = 1;
-                       if (*pp == adelete)
-                               win->can_delete = 1;
-               }
-               if (prot)
-                       XFree(prot);
-       }
-
-       win->iconic = get_iconic(win);
-
-       /*
-        * Figure out where to put the window. If it was previously assigned to
-        * a workspace (either by spawn() or manually moving), and isn't
-        * transient, * put it in the same workspace
-        */
-       r = root_to_region(win->wa.root);
-       if (p) {
-               ws = &r->s->ws[p->ws];
-               TAILQ_REMOVE(&pidlist, p, entry);
-               free(p);
-               p = NULL;
-       } else if (prop && win->transient == 0) {
-               DNPRINTF(SWM_D_PROP, "manage_window: get _SWM_WS: %s\n", prop);
-               ws_idx = strtonum((const char *)prop, 0, 9, &errstr);
-               if (errstr) {
-                       DNPRINTF(SWM_D_EVENT, "manage_window: window: #%s: %s",
-                           errstr, prop);
-               }
-               ws = &r->s->ws[ws_idx];
-       } else {
-               ws = r->ws;
-               /* this should launch transients in the same ws as parent */
-               if (id && trans)
-                       if ((ww = find_window(trans)) != NULL)
-                               if (ws->r) {
-                                       ws = ww->ws;
-                                       if (ww->ws->r)
-                                               r = ww->ws->r;
-                                       else
-                                               warnx("manage_window: fix this "
-                                                   "bug mcbride");
-                                       border_me = 1;
-                               }
-       }
-
-       /* set up the window layout */
-       win->id = id;
-       win->ws = ws;
-       win->s = r->s;  /* this never changes */
-       if (trans && (ww = find_window(trans)))
-               TAILQ_INSERT_AFTER(&ws->winlist, ww, win, entry);
-       else
-               TAILQ_INSERT_TAIL(&ws->winlist, win, entry);
-
-       WIDTH(win) = win->wa.width;
-       HEIGHT(win) = win->wa.height;
-       X(win) = win->wa.x;
-       Y(win) = win->wa.y;
-       win->g_floatvalid = 0;
-       win->floatmaxed = 0;
-       win->ewmh_flags = 0;
-
-       /* Set window properties so we can remember this after reincarnation */
-       if (ws_idx_atom && prop == NULL &&
-           snprintf((char *)ws_idx_str, SWM_PROPLEN, "%d", ws->idx) <
-               SWM_PROPLEN) {
-               DNPRINTF(SWM_D_PROP, "manage_window: set _SWM_WS: %s\n",
-                   ws_idx_str);
-               XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
-                   PropModeReplace, ws_idx_str, strlen((char *)ws_idx_str));
-       }
-       if (prop)
-               XFree(prop);
-
-       ewmh_autoquirk(win);
-
-       if (XGetClassHint(display, win->id, &win->ch)) {
-               DNPRINTF(SWM_D_CLASS, "manage_window: class: %s, name: %s\n",
-                   win->ch.res_class, win->ch.res_name);
-
-               /* java is retarded so treat it special */
-               if (strstr(win->ch.res_name, "sun-awt")) {
-                       win->java = 1;
-                       border_me = 1;
-               }
-
-               TAILQ_FOREACH(qp, &quirks, entry) {
-                       if (!strcmp(win->ch.res_class, qp->class) &&
-                           !strcmp(win->ch.res_name, qp->name)) {
-                               DNPRINTF(SWM_D_CLASS, "manage_window: found: "
-                                   "class: %s, name: %s\n", win->ch.res_class,
-                                   win->ch.res_name);
-                               if (qp->quirk & SWM_Q_FLOAT) {
-                                       win->floating = 1;
-                                       border_me = 1;
-                               }
-                               win->quirks = qp->quirk;
-                       }
-               }
-       }
-
-       /* alter window position if quirky */
-       if (win->quirks & SWM_Q_ANYWHERE) {
-               win->manual = 1; /* don't center the quirky windows */
-               bzero(&wc, sizeof wc);
-               mask = 0;
-               if (bar_enabled && Y(win) < bar_height) {
-                       Y(win) = wc.y = bar_height;
-                       mask |= CWY;
-               }
-               if (WIDTH(win) + X(win) > WIDTH(r)) {
-                       X(win) = wc.x = WIDTH(r) - WIDTH(win) - 2;
-                       mask |= CWX;
-               }
-               border_me = 1;
-       }
-
-       /* Reset font sizes (the bruteforce way; no default keybinding). */
-       if (win->quirks & SWM_Q_XTERM_FONTADJ) {
-               for (i = 0; i < SWM_MAX_FONT_STEPS; i++)
-                       fake_keypress(win, XK_KP_Subtract, ShiftMask);
-               for (i = 0; i < SWM_MAX_FONT_STEPS; i++)
-                       fake_keypress(win, XK_KP_Add, ShiftMask);
-       }
-
-       ewmh_get_win_state(win);
-       ewmh_update_actions(win);
-       ewmh_update_win_state(win, None, _NET_WM_STATE_REMOVE);
-
-       /* border me */
-       if (border_me) {
-               bzero(&wc, sizeof wc);
-               wc.border_width = border_width;
-               mask = CWBorderWidth;
-               XConfigureWindow(display, win->id, mask, &wc);
-       }
-
-       XSelectInput(display, id, EnterWindowMask | FocusChangeMask |
-           PropertyChangeMask | StructureNotifyMask);
-
-       /* floaters need to be mapped if they are in the current workspace */
-       if ((win->floating || win->transient) && (ws->idx == r->ws->idx))
-               XMapRaised(display, win->id);
-
-       return (win);
-}
-
-void
-free_window(struct ws_win *win)
-{
-       DNPRINTF(SWM_D_MISC, "free_window: window: 0x%lx\n", win->id);
-
-       if (win == NULL)
-               return;
-
-       /* needed for restart wm */
-       set_win_state(win, WithdrawnState);
-
-       TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
-
-       if (win->ch.res_class)
-               XFree(win->ch.res_class);
-       if (win->ch.res_name)
-               XFree(win->ch.res_name);
-
-       kill_refs(win);
-
-       /* paint memory */
-       memset(win, 0xff, sizeof *win); /* XXX kill later */
-
-       free(win);
-}
-
-void
-unmanage_window(struct ws_win *win)
-{
-       struct ws_win           *parent;
-
-       if (win == NULL)
-               return;
-
-       DNPRINTF(SWM_D_MISC, "unmanage_window: window: 0x%lx\n", win->id);
-
-       if (win->transient) {
-               parent = find_window(win->transient);
-               if (parent)
-                       parent->child_trans = NULL;
-       }
-
-       /* focus on root just in case */
-       XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
-
-       focus_prev(win);
-
-       if (win->hints) {
-               XFree(win->hints);
-               win->hints = NULL;
-       }
-
-       TAILQ_REMOVE(&win->ws->winlist, win, entry);
-       TAILQ_INSERT_TAIL(&win->ws->unmanagedlist, win, entry);
-
-       kill_refs(win);
-}
-
-void
-focus_magic(struct ws_win *win)
-{
-       DNPRINTF(SWM_D_FOCUS, "focus_magic: window: 0x%lx\n", WINID(win));
-
-       if (win == NULL) {
-               /* if there are no windows clear the status-bar */
-               bar_check_opts();
-               return;
-       }
-
-       if (win->child_trans) {
-               /* win = parent & has a transient so focus on that */
-               if (win->java) {
-                       focus_win(win->child_trans);
-                       if (win->child_trans->take_focus)
-                               client_msg(win, takefocus);
-               } else {
-                       /* make sure transient hasn't disappeared */
-                       if (validate_win(win->child_trans) == 0) {
-                               focus_win(win->child_trans);
-                               if (win->child_trans->take_focus)
-                                       client_msg(win->child_trans, takefocus);
-                       } else {
-                               win->child_trans = NULL;
-                               focus_win(win);
-                               if (win->take_focus)
-                                       client_msg(win, takefocus);
-                       }
-               }
-       } else {
-               /* regular focus */
-               focus_win(win);
-               if (win->take_focus)
-                       client_msg(win, takefocus);
-       }
-}
-
-void
-expose(XEvent *e)
-{
-       DNPRINTF(SWM_D_EVENT, "expose: window: 0x%lx\n", e->xexpose.window);
-}
-
-void
-keypress(XEvent *e)
-{
-       KeySym                  keysym;
-       XKeyEvent               *ev = &e->xkey;
-       struct key              *kp;
-       struct swm_region       *r;
-
-       keysym = XKeycodeToKeysym(display, (KeyCode)ev->keycode, 0);
-       if ((kp = key_lookup(CLEANMASK(ev->state), keysym)) == NULL)
-               return;
-       if (keyfuncs[kp->funcid].func == NULL)
-               return;
-
-       r = root_to_region(ev->root);
-       if (kp->funcid == kf_spawn_custom)
-               spawn_custom(r, &(keyfuncs[kp->funcid].args), kp->spawn_name);
-       else
-               keyfuncs[kp->funcid].func(r, &(keyfuncs[kp->funcid].args));
-}
-
-void
-buttonpress(XEvent *e)
-{
-       struct ws_win           *win;
-       int                     i, action;
-       XButtonPressedEvent     *ev = &e->xbutton;
-
-       if ((win = find_window(ev->window)) == NULL)
-               return;
-
-       focus_magic(win);
-       action = client_click;
-
-       for (i = 0; i < LENGTH(buttons); i++)
-               if (action == buttons[i].action && buttons[i].func &&
-                   buttons[i].button == ev->button &&
-                   CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
-                       buttons[i].func(win, &buttons[i].args);
-}
-
-void
-configurerequest(XEvent *e)
-{
-       XConfigureRequestEvent  *ev = &e->xconfigurerequest;
-       struct ws_win           *win;
-       int                     new = 0;
-       XWindowChanges          wc;
-
-       if ((win = find_window(ev->window)) == NULL)
-               if ((win = find_unmanaged_window(ev->window)) == NULL)
-                       new = 1;
-
-       DNPRINTF(SWM_D_EVENT, "configurerequest: window: 0x%lx, new: %s\n",
-           ev->window, YESNO(new));
-
-       if (new) {
-               bzero(&wc, sizeof wc);
-               wc.x = ev->x;
-               wc.y = ev->y;
-               wc.width = ev->width;
-               wc.height = ev->height;
-               wc.border_width = ev->border_width;
-               wc.sibling = ev->above;
-               wc.stack_mode = ev->detail;
-               XConfigureWindow(display, ev->window, ev->value_mask, &wc);
-       } else {
-               config_win(win, ev);
-       }
-}
-
-void
-configurenotify(XEvent *e)
-{
-       struct ws_win           *win;
-
-       DNPRINTF(SWM_D_EVENT, "configurenotify: window: 0x%lx\n",
-           e->xconfigure.window);
-
-       win = find_window(e->xconfigure.window);
-       if (win) {
-               XGetWMNormalHints(display, win->id, &win->sh, &win->sh_mask);
-               adjust_font(win);
-               if (font_adjusted)
-                       stack();
-               if (focus_mode == SWM_FOCUS_DEFAULT)
-                       drain_enter_notify();
-       }
-}
-
-void
-destroynotify(XEvent *e)
-{
-       struct ws_win           *win;
-       XDestroyWindowEvent     *ev = &e->xdestroywindow;
-
-       DNPRINTF(SWM_D_EVENT, "destroynotify: window: 0x%lx\n", ev->window);
-
-       if ((win = find_window(ev->window)) == NULL) {
-               if ((win = find_unmanaged_window(ev->window)) == NULL)
-                       return;
-               free_window(win);
-               return;
-       }
-
-       /* make sure we focus on something */
-       win->floating = 0;
-
-       unmanage_window(win);
-       stack();
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-       free_window(win);
-}
-
-void
-enternotify(XEvent *e)
-{
-       XCrossingEvent          *ev = &e->xcrossing;
-       XEvent                  cne;
-       struct ws_win           *win;
-#if 0
-       struct ws_win           *w;
-       Window                  focus_return;
-       int                     revert_to_return;
-#endif
-       DNPRINTF(SWM_D_FOCUS, "enternotify: window: 0x%lx, mode: %d, detail: "
-           "%d, root: 0x%lx, subwindow: 0x%lx, same_screen: %s, focus: %s, "
-           "state: %d\n", ev->window, ev->mode, ev->detail, ev->root,
-           ev->subwindow, YESNO(ev->same_screen), YESNO(ev->focus), ev->state);
-
-       if (ev->mode != NotifyNormal) {
-               DNPRINTF(SWM_D_EVENT, "skip enternotify: generated by "
-                   "cursor grab.\n");
-               return;
-       }
-
-       switch (focus_mode) {
-       case SWM_FOCUS_DEFAULT:
-               break;
-       case SWM_FOCUS_FOLLOW:
-               break;
-       case SWM_FOCUS_SYNERGY:
-#if 0
-       /*
-        * all these checks need to be in this order because the
-        * XCheckTypedWindowEvent relies on weeding out the previous events
-        *
-        * making this code an option would enable a follow mouse for focus
-        * feature
-        */
-
-       /*
-        * state is set when we are switching workspaces and focus is set when
-        * the window or a subwindow already has focus (occurs during restart).
-        *
-        * Only honor the focus flag if last_focus_event is not FocusOut,
-        * this allows scrotwm to continue to control focus when another
-        * program is also playing with it.
-        */
-       if (ev->state || (ev->focus && last_focus_event != FocusOut)) {
-               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: focus\n");
-               return;
-       }
-
-       /*
-        * happens when a window is created or destroyed and the border
-        * crosses the mouse pointer and when switching ws
-        *
-        * we need the subwindow test to see if we came from root in order
-        * to give focus to floaters
-        */
-       if (ev->mode == NotifyNormal && ev->detail == NotifyVirtual &&
-           ev->subwindow == 0) {
-               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: NotifyVirtual\n");
-               return;
-       }
-
-       /* this window already has focus */
-       if (ev->mode == NotifyNormal && ev->detail == NotifyInferior) {
-               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: win has focus\n");
-               return;
-       }
-
-       /* this window is being deleted or moved to another ws */
-       if (XCheckTypedWindowEvent(display, ev->window, ConfigureNotify,
-           &cne) == True) {
-               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: configurenotify\n");
-               XPutBackEvent(display, &cne);
-               return;
-       }
-
-       if ((win = find_window(ev->window)) == NULL) {
-               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: win == NULL\n");
-               return;
-       }
-
-       /*
-        * In fullstack kill all enters unless they come from a different ws
-        * (i.e. another region) or focus has been grabbed externally.
-        */
-       if (win->ws->cur_layout->flags & SWM_L_FOCUSPREV &&
-           last_focus_event != FocusOut) {
-               XGetInputFocus(display, &focus_return, &revert_to_return);
-               if ((w = find_window(focus_return)) == NULL ||
-                   w->ws == win->ws) {
-                       DNPRINTF(SWM_D_EVENT, "ignoring event: fullstack\n");
-                       return;
-               }
-       }
-#endif
-               break;
-       }
-
-       if ((win = find_window(ev->window)) == NULL) {
-               DNPRINTF(SWM_D_EVENT, "skip enternotify: window is NULL\n");
-               return;
-       }
-
-       /*
-        * if we have more enternotifies let them handle it in due time
-        */
-       if (XCheckTypedEvent(display, EnterNotify, &cne) == True) {
-               DNPRINTF(SWM_D_EVENT,
-                   "ignoring enternotify: got more enternotify\n");
-               XPutBackEvent(display, &cne);
-               return;
-       }
-
-       focus_magic(win);
-}
-
-/* lets us use one switch statement for arbitrary mode/detail combinations */
-#define MERGE_MEMBERS(a,b)     (((a & 0xffff) << 16) | (b & 0xffff))
-
-void
-focusevent(XEvent *e)
-{
-#if 0
-       struct ws_win           *win;
-       u_int32_t               mode_detail;
-       XFocusChangeEvent       *ev = &e->xfocus;
-
-       DNPRINTF(SWM_D_EVENT, "focusevent: %s window: 0x%lx mode: %d "
-           "detail: %d\n", ev->type == FocusIn ? "entering" : "leaving",
-           ev->window, ev->mode, ev->detail);
-
-       if (last_focus_event == ev->type) {
-               DNPRINTF(SWM_D_FOCUS, "ignoring focusevent: bad ordering\n");
-               return;
-       }
-
-       last_focus_event = ev->type;
-       mode_detail = MERGE_MEMBERS(ev->mode, ev->detail);
-
-       switch (mode_detail) {
-       /* synergy client focus operations */
-       case MERGE_MEMBERS(NotifyNormal, NotifyNonlinear):
-       case MERGE_MEMBERS(NotifyNormal, NotifyNonlinearVirtual):
-
-       /* synergy server focus operations */
-       case MERGE_MEMBERS(NotifyWhileGrabbed, NotifyNonlinear):
-
-       /* Entering applications like rdesktop that mangle the pointer */
-       case MERGE_MEMBERS(NotifyNormal, NotifyPointer):
-
-               if ((win = find_window(e->xfocus.window)) != NULL && win->ws->r)
-                       XSetWindowBorder(display, win->id,
-                           win->ws->r->s->c[ev->type == FocusIn ?
-                           SWM_S_COLOR_FOCUS : SWM_S_COLOR_UNFOCUS].color);
-               break;
-       default:
-               warnx("ignoring focusevent");
-               DNPRINTF(SWM_D_FOCUS, "ignoring focusevent\n");
-               break;
-       }
-#endif
-}
-
-void
-mapnotify(XEvent *e)
-{
-       struct ws_win           *win;
-       XMapEvent               *ev = &e->xmap;
-
-       DNPRINTF(SWM_D_EVENT, "mapnotify: window: 0x%lx\n", ev->window);
-
-       win = manage_window(ev->window);
-       if (win)
-               set_win_state(win, NormalState);
-}
-
-void
-mappingnotify(XEvent *e)
-{
-       XMappingEvent           *ev = &e->xmapping;
-
-       XRefreshKeyboardMapping(ev);
-       if (ev->request == MappingKeyboard)
-               grabkeys();
-}
-
-void
-maprequest(XEvent *e)
-{
-       struct ws_win           *win;
-       struct swm_region       *r;
-       XWindowAttributes       wa;
-       XMapRequestEvent        *ev = &e->xmaprequest;
-
-       DNPRINTF(SWM_D_EVENT, "maprequest: window: 0x%lx\n",
-           e->xmaprequest.window);
-
-       if (!XGetWindowAttributes(display, ev->window, &wa))
-               return;
-       if (wa.override_redirect)
-               return;
-
-       win = manage_window(e->xmaprequest.window);
-       if (win == NULL)
-               return; /* can't happen */
-
-       stack();
-
-       /* make new win focused */
-       r = root_to_region(win->wa.root);
-       if (win->ws == r->ws)
-               focus_magic(win);
-}
-
-void
-propertynotify(XEvent *e)
-{
-       struct ws_win           *win;
-       XPropertyEvent          *ev = &e->xproperty;
-#ifdef SWM_DEBUG
-       char                    *name;
-       name = XGetAtomName(display, ev->atom);
-       DNPRINTF(SWM_D_EVENT, "propertynotify: window: 0x%lx, atom: %s\n",
-           ev->window, name);
-       XFree(name);
-#endif
-
-       win = find_window(ev->window);
-       if (win == NULL)
-               return;
-
-       if (ev->state == PropertyDelete && ev->atom == a_swm_iconic) {
-               update_iconic(win, 0);
-               XMapRaised(display, win->id);
-               stack();
-               focus_win(win);
-               return;
-       }
-
-       switch (ev->atom) {
-#if 0
-       case XA_WM_NORMAL_HINTS:
-               long            mask;
-               XGetWMNormalHints(display, win->id, &win->sh, &mask);
-               warnx("normal hints: flag 0x%x", win->sh.flags);
-               if (win->sh.flags & PMinSize) {
-                       WIDTH(win) = win->sh.min_width;
-                       HEIGHT(win) = win->sh.min_height;
-                       warnx("min %d %d", WIDTH(win), HEIGHT(win));
-               }
-               XMoveResizeWindow(display, win->id,
-                   X(win), Y(win), WIDTH(win), HEIGHT(win));
-#endif
-       case XA_WM_CLASS:
-               if (title_name_enabled || title_class_enabled)
-                       bar_update();
-               break;
-       case XA_WM_NAME:
-               if (window_name_enabled)
-                       bar_update();
-               break;
-       default:
-               break;
-       }
-}
-
-void
-unmapnotify(XEvent *e)
-{
-       struct ws_win           *win;
-
-       DNPRINTF(SWM_D_EVENT, "unmapnotify: window: 0x%lx\n", e->xunmap.window);
-
-       /* determine if we need to help unmanage this window */
-       win = find_window(e->xunmap.window);
-       if (win == NULL)
-               return;
-
-       if (getstate(e->xunmap.window) == NormalState) {
-               unmanage_window(win);
-               stack();
-
-               /* giant hack for apps that don't destroy transient windows */
-               /* eat a bunch of events to prevent remanaging the window */
-               XEvent                  cne;
-               while (XCheckWindowEvent(display, e->xunmap.window,
-                   EnterWindowMask, &cne))
-                       ;
-               while (XCheckWindowEvent(display, e->xunmap.window,
-                   StructureNotifyMask, &cne))
-                       ;
-               while (XCheckWindowEvent(display, e->xunmap.window,
-                   SubstructureNotifyMask, &cne))
-                       ;
-               /* resend unmap because we ated it */
-               XUnmapWindow(display, e->xunmap.window);
-       }
-
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-}
-
-void
-visibilitynotify(XEvent *e)
-{
-       int                     i;
-       struct swm_region       *r;
-
-       DNPRINTF(SWM_D_EVENT, "visibilitynotify: window: 0x%lx\n",
-           e->xvisibility.window);
-       if (e->xvisibility.state == VisibilityUnobscured)
-               for (i = 0; i < ScreenCount(display); i++)
-                       TAILQ_FOREACH(r, &screens[i].rl, entry)
-                               if (e->xvisibility.window == r->bar_window)
-                                       bar_update();
-}
-
-void
-clientmessage(XEvent *e)
-{
-       XClientMessageEvent *ev;
-       struct ws_win *win;
-
-       ev = &e->xclient;
-
-       win = find_window(ev->window);
-       if (win == NULL)
-               return;
-
-       DNPRINTF(SWM_D_EVENT, "clientmessage: window: 0x%lx, type: %ld\n",
-           ev->window, ev->message_type);
-
-       if (ev->message_type == ewmh[_NET_ACTIVE_WINDOW].atom) {
-               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW\n");
-               focus_win(win);
-       }
-       if (ev->message_type == ewmh[_NET_CLOSE_WINDOW].atom) {
-               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_CLOSE_WINDOW\n");
-               if (win->can_delete)
-                       client_msg(win, adelete);
-               else
-                       XKillClient(display, win->id);
-       }
-       if (ev->message_type == ewmh[_NET_MOVERESIZE_WINDOW].atom) {
-               DNPRINTF(SWM_D_EVENT,
-                   "clientmessage: _NET_MOVERESIZE_WINDOW\n");
-               if (win->floating) {
-                       if (ev->data.l[0] & (1<<8)) /* x */
-                               X(win) = ev->data.l[1];
-                       if (ev->data.l[0] & (1<<9)) /* y */
-                               Y(win) = ev->data.l[2];
-                       if (ev->data.l[0] & (1<<10)) /* width */
-                               WIDTH(win) = ev->data.l[3];
-                       if (ev->data.l[0] & (1<<11)) /* height */
-                               HEIGHT(win) = ev->data.l[4];
-
-                       update_window(win);
-               }
-               else {
-                       /* TODO: Change stack sizes */
-                       /* notify no change was made. */
-                       config_win(win, NULL);
-               }
-       }
-       if (ev->message_type == ewmh[_NET_WM_STATE].atom) {
-               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_WM_STATE\n");
-               ewmh_update_win_state(win, ev->data.l[1], ev->data.l[0]);
-               if (ev->data.l[2])
-                       ewmh_update_win_state(win, ev->data.l[2],
-                           ev->data.l[0]);
-
-               stack();
-       }
-}
-
-int
-xerror_start(Display *d, XErrorEvent *ee)
-{
-       other_wm = 1;
-       return (-1);
-}
-
-int
-xerror(Display *d, XErrorEvent *ee)
-{
-       /* warnx("error: %p %p", display, ee); */
-       return (-1);
-}
-
-int
-active_wm(void)
-{
-       other_wm = 0;
-       xerrorxlib = XSetErrorHandler(xerror_start);
-
-       /* this causes an error if some other window manager is running */
-       XSelectInput(display, DefaultRootWindow(display),
-           SubstructureRedirectMask);
-       XSync(display, False);
-       if (other_wm)
-               return (1);
-
-       XSetErrorHandler(xerror);
-       XSync(display, False);
-       return (0);
-}
-
-void
-new_region(struct swm_screen *s, int x, int y, int w, int h)
-{
-       struct swm_region       *r, *n;
-       struct workspace        *ws = NULL;
-       int                     i;
-
-       DNPRINTF(SWM_D_MISC, "new region: screen[%d]:%dx%d+%d+%d\n",
-            s->idx, w, h, x, y);
-
-       /* remove any conflicting regions */
-       n = TAILQ_FIRST(&s->rl);
-       while (n) {
-               r = n;
-               n = TAILQ_NEXT(r, entry);
-               if (X(r) < (x + w) &&
-                   (X(r) + WIDTH(r)) > x &&
-                   Y(r) < (y + h) &&
-                   (Y(r) + HEIGHT(r)) > y) {
-                       if (r->ws->r != NULL)
-                               r->ws->old_r = r->ws->r;
-                       r->ws->r = NULL;
-                       XDestroyWindow(display, r->bar_window);
-                       TAILQ_REMOVE(&s->rl, r, entry);
-                       TAILQ_INSERT_TAIL(&s->orl, r, entry);
-               }
-       }
-
-       /* search old regions for one to reuse */
-
-       /* size + location match */
-       TAILQ_FOREACH(r, &s->orl, entry)
-               if (X(r) == x && Y(r) == y &&
-                   HEIGHT(r) == h && WIDTH(r) == w)
-                       break;
-
-       /* size match */
-       TAILQ_FOREACH(r, &s->orl, entry)
-               if (HEIGHT(r) == h && WIDTH(r) == w)
-                       break;
-
-       if (r != NULL) {
-               TAILQ_REMOVE(&s->orl, r, entry);
-               /* try to use old region's workspace */
-               if (r->ws->r == NULL)
-                       ws = r->ws;
-       } else
-               if ((r = calloc(1, sizeof(struct swm_region))) == NULL)
-                       err(1, "new_region: calloc: failed to allocate memory "
-                           "for screen");
-
-       /* if we don't have a workspace already, find one */
-       if (ws == NULL) {
-               for (i = 0; i < SWM_WS_MAX; i++)
-                       if (s->ws[i].r == NULL) {
-                               ws = &s->ws[i];
-                               break;
-                       }
-       }
-
-       if (ws == NULL)
-               errx(1, "new_region: no free workspaces");
-
-       X(r) = x;
-       Y(r) = y;
-       WIDTH(r) = w;
-       HEIGHT(r) = h;
-       r->s = s;
-       r->ws = ws;
-       r->ws_prior = NULL;
-       ws->r = r;
-       outputs++;
-       TAILQ_INSERT_TAIL(&s->rl, r, entry);
-}
-
-void
-scan_xrandr(int i)
-{
-#ifdef SWM_XRR_HAS_CRTC
-       XRRCrtcInfo             *ci;
-       XRRScreenResources      *sr;
-       int                     c;
-       int                     ncrtc = 0;
-#endif /* SWM_XRR_HAS_CRTC */
-       struct swm_region       *r;
-
-
-       if (i >= ScreenCount(display))
-               errx(1, "scan_xrandr: invalid screen");
-
-       /* remove any old regions */
-       while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) {
-               r->ws->old_r = r->ws->r = NULL;
-               XDestroyWindow(display, r->bar_window);
-               TAILQ_REMOVE(&screens[i].rl, r, entry);
-               TAILQ_INSERT_TAIL(&screens[i].orl, r, entry);
-       }
-       outputs = 0;
-
-       /* map virtual screens onto physical screens */
-#ifdef SWM_XRR_HAS_CRTC
-       if (xrandr_support) {
-               sr = XRRGetScreenResources(display, screens[i].root);
-               if (sr == NULL)
-                       new_region(&screens[i], 0, 0,
-                           DisplayWidth(display, i),
-                           DisplayHeight(display, i));
-               else
-                       ncrtc = sr->ncrtc;
-
-               for (c = 0, ci = NULL; c < ncrtc; c++) {
-                       ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]);
-                       if (ci->noutput == 0)
-                               continue;
-
-                       if (ci != NULL && ci->mode == None)
-                               new_region(&screens[i], 0, 0,
-                                   DisplayWidth(display, i),
-                                   DisplayHeight(display, i));
-                       else
-                               new_region(&screens[i],
-                                   ci->x, ci->y, ci->width, ci->height);
-               }
-               if (ci)
-                       XRRFreeCrtcInfo(ci);
-               XRRFreeScreenResources(sr);
-       } else
-#endif /* SWM_XRR_HAS_CRTC */
-       {
-               new_region(&screens[i], 0, 0, DisplayWidth(display, i),
-                   DisplayHeight(display, i));
-       }
-}
-
-void
-screenchange(XEvent *e) {
-       XRRScreenChangeNotifyEvent      *xe = (XRRScreenChangeNotifyEvent *)e;
-       struct swm_region               *r;
-       int                             i;
-
-       DNPRINTF(SWM_D_EVENT, "screenchange: root: 0x%lx\n", xe->root);
-
-       if (!XRRUpdateConfiguration(e))
-               return;
-
-       /* silly event doesn't include the screen index */
-       for (i = 0; i < ScreenCount(display); i++)
-               if (screens[i].root == xe->root)
-                       break;
-       if (i >= ScreenCount(display))
-               errx(1, "screenchange: screen not found");
-
-       /* brute force for now, just re-enumerate the regions */
-       scan_xrandr(i);
-
-       /* add bars to all regions */
-       for (i = 0; i < ScreenCount(display); i++)
-               TAILQ_FOREACH(r, &screens[i].rl, entry)
-                       bar_setup(r);
-       stack();
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-}
-
-void
-grab_windows(void)
-{
-       Window                  d1, d2, *wins = NULL;
-       XWindowAttributes       wa;
-       unsigned int            no;
-       int                     i, j;
-       long                    state, manage;
-
-       for (i = 0; i < ScreenCount(display); i++) {
-               if (!XQueryTree(display, screens[i].root, &d1, &d2, &wins, &no))
-                       continue;
-
-               /* attach windows to a region */
-               /* normal windows */
-               for (j = 0; j < no; j++) {
-                       if (!XGetWindowAttributes(display, wins[j], &wa) ||
-                           wa.override_redirect ||
-                           XGetTransientForHint(display, wins[j], &d1))
-                               continue;
-
-                       state = getstate(wins[j]);
-                       manage = state == IconicState;
-                       if (wa.map_state == IsViewable || manage)
-                               manage_window(wins[j]);
-               }
-               /* transient windows */
-               for (j = 0; j < no; j++) {
-                       if (!XGetWindowAttributes(display, wins[j], &wa) ||
-                           wa.override_redirect)
-                               continue;
-
-                       state = getstate(wins[j]);
-                       manage = state == IconicState;
-                       if (XGetTransientForHint(display, wins[j], &d1) &&
-                           manage)
-                               manage_window(wins[j]);
-               }
-               if (wins) {
-                       XFree(wins);
-                       wins = NULL;
-               }
-       }
-}
-
-void
-setup_screens(void)
-{
-       int                     i, j, k;
-       int                     errorbase, major, minor;
-       struct workspace        *ws;
-       XGCValues               gcv;
-
-       if ((screens = calloc(ScreenCount(display),
-            sizeof(struct swm_screen))) == NULL)
-               err(1, "setup_screens: calloc: failed to allocate memory for "
-                   "screens");
-
-       /* initial Xrandr setup */
-       xrandr_support = XRRQueryExtension(display,
-           &xrandr_eventbase, &errorbase);
-       if (xrandr_support)
-               if (XRRQueryVersion(display, &major, &minor) && major < 1)
-                       xrandr_support = 0;
-
-       /* map physical screens */
-       for (i = 0; i < ScreenCount(display); i++) {
-               DNPRINTF(SWM_D_WS, "setup_screens: init screen: %d\n", i);
-               screens[i].idx = i;
-               TAILQ_INIT(&screens[i].rl);
-               TAILQ_INIT(&screens[i].orl);
-               screens[i].root = RootWindow(display, i);
-
-               /* set default colors */
-               setscreencolor("red", i + 1, SWM_S_COLOR_FOCUS);
-               setscreencolor("rgb:88/88/88", i + 1, SWM_S_COLOR_UNFOCUS);
-               setscreencolor("rgb:00/80/80", i + 1, SWM_S_COLOR_BAR_BORDER);
-               setscreencolor("black", i + 1, SWM_S_COLOR_BAR);
-               setscreencolor("rgb:a0/a0/a0", i + 1, SWM_S_COLOR_BAR_FONT);
-
-               /* create graphics context on screen with default font color */
-               screens[i].bar_gc = XCreateGC(display, screens[i].root, 0,
-                   &gcv);
-
-               XSetForeground(display, screens[i].bar_gc,
-                   screens[i].c[SWM_S_COLOR_BAR_FONT].color);
-
-               /* set default cursor */
-               XDefineCursor(display, screens[i].root,
-                   XCreateFontCursor(display, XC_left_ptr));
-
-               /* init all workspaces */
-               /* XXX these should be dynamically allocated too */
-               for (j = 0; j < SWM_WS_MAX; j++) {
-                       ws = &screens[i].ws[j];
-                       ws->idx = j;
-                       ws->name = NULL;
-                       ws->focus = NULL;
-                       ws->r = NULL;
-                       ws->old_r = NULL;
-                       TAILQ_INIT(&ws->winlist);
-                       TAILQ_INIT(&ws->unmanagedlist);
-
-                       for (k = 0; layouts[k].l_stack != NULL; k++)
-                               if (layouts[k].l_config != NULL)
-                                       layouts[k].l_config(ws,
-                                           SWM_ARG_ID_STACKINIT);
-                       ws->cur_layout = &layouts[0];
-                       ws->cur_layout->l_string(ws);
-               }
-
-               scan_xrandr(i);
-
-               if (xrandr_support)
-                       XRRSelectInput(display, screens[i].root,
-                           RRScreenChangeNotifyMask);
-       }
-}
-
-void
-setup_globals(void)
-{
-       if ((bar_fonts = strdup(SWM_BAR_FONTS)) == NULL)
-               err(1, "setup_globals: strdup: failed to allocate memory.");
-
-       if ((spawn_term[0] = strdup("xterm")) == NULL)
-               err(1, "setup_globals: strdup: failed to allocate memory.");
-
-       if ((clock_format = strdup("%a %b %d %R %Z %Y")) == NULL)
-               err(1, "setup_globals: strdup: failed to allocate memory.");
-}
-
-void
-workaround(void)
-{
-       int                     i;
-       Atom                    netwmcheck, netwmname, utf8_string;
-       Window                  root, win;
-
-       /* work around sun jdk bugs, code from wmname */
-       netwmcheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
-       netwmname = XInternAtom(display, "_NET_WM_NAME", False);
-       utf8_string = XInternAtom(display, "UTF8_STRING", False);
-       for (i = 0; i < ScreenCount(display); i++) {
-               root = screens[i].root;
-               win = XCreateSimpleWindow(display,root, 0, 0, 1, 1, 0,
-                   screens[i].c[SWM_S_COLOR_UNFOCUS].color,
-                   screens[i].c[SWM_S_COLOR_UNFOCUS].color);
-
-               XChangeProperty(display, root, netwmcheck, XA_WINDOW, 32,
-                   PropModeReplace, (unsigned char *)&win,1);
-               XChangeProperty(display, win, netwmcheck, XA_WINDOW, 32,
-                   PropModeReplace, (unsigned char *)&win,1);
-               XChangeProperty(display, win, netwmname, utf8_string, 8,
-                   PropModeReplace, (unsigned char*)"LG3D", strlen("LG3D"));
-       }
-}
-
-int
-main(int argc, char *argv[])
-{
-       struct swm_region       *r, *rr;
-       struct ws_win           *winfocus = NULL;
-       struct timeval          tv;
-       union arg               a;
-       char                    conf[PATH_MAX], *cfile = NULL;
-       struct stat             sb;
-       XEvent                  e;
-       int                     xfd, i;
-       fd_set                  rd;
-       struct sigaction        sact;
-
-       start_argv = argv;
-       warnx("Welcome to scrotwm V%s Build: %s", SCROTWM_VERSION, buildstr);
-       if (!setlocale(LC_CTYPE, "") || !setlocale(LC_TIME, "") ||
-           !XSupportsLocale())
-               warnx("no locale support");
-
-       if (!X_HAVE_UTF8_STRING)
-               warnx("no UTF-8 support");
-
-       if (!(display = XOpenDisplay(0)))
-               errx(1, "can not open display");
-
-       if (active_wm())
-               errx(1, "other wm running");
-
-       /* handle some signals */
-       bzero(&sact, sizeof(sact));
-       sigemptyset(&sact.sa_mask);
-       sact.sa_flags = 0;
-       sact.sa_handler = sighdlr;
-       sigaction(SIGINT, &sact, NULL);
-       sigaction(SIGQUIT, &sact, NULL);
-       sigaction(SIGTERM, &sact, NULL);
-       sigaction(SIGHUP, &sact, NULL);
-
-       sact.sa_handler = sighdlr;
-       sact.sa_flags = SA_NOCLDSTOP;
-       sigaction(SIGCHLD, &sact, NULL);
-
-       astate = XInternAtom(display, "WM_STATE", False);
-       aprot = XInternAtom(display, "WM_PROTOCOLS", False);
-       adelete = XInternAtom(display, "WM_DELETE_WINDOW", False);
-       takefocus = XInternAtom(display, "WM_TAKE_FOCUS", False);
-       a_wmname = XInternAtom(display, "WM_NAME", False);
-       a_netwmname = XInternAtom(display, "_NET_WM_NAME", False);
-       a_utf8_string = XInternAtom(display, "UTF8_STRING", False);
-       a_string = XInternAtom(display, "STRING", False);
-       a_swm_iconic = XInternAtom(display, "_SWM_ICONIC", False);
-
-       /* look for local and global conf file */
-       pwd = getpwuid(getuid());
-       if (pwd == NULL)
-               errx(1, "invalid user: %d", getuid());
-
-       setup_globals();
-       setup_screens();
-       setup_keys();
-       setup_quirks();
-       setup_spawn();
-
-       /* load config */
-       snprintf(conf, sizeof conf, "%s/.%s", pwd->pw_dir, SWM_CONF_FILE);
-       if (stat(conf, &sb) != -1) {
-               if (S_ISREG(sb.st_mode))
-                       cfile = conf;
-       } else {
-               /* try global conf file */
-               snprintf(conf, sizeof conf, "/etc/%s", SWM_CONF_FILE);
-               if (!stat(conf, &sb))
-                       if (S_ISREG(sb.st_mode))
-                               cfile = conf;
-       }
-
-       /* load conf (if any) and refresh font color in bar graphics contexts */
-       if (cfile && conf_load(cfile, SWM_CONF_DEFAULT) == 0)
-               for (i = 0; i < ScreenCount(display); ++i)
-                       XSetForeground(display, screens[i].bar_gc,
-                           screens[i].c[SWM_S_COLOR_BAR_FONT].color);
-
-       setup_ewmh();
-       /* set some values to work around bad programs */
-       workaround();
-       /* grab existing windows (before we build the bars) */
-       grab_windows();
-
-       if (getenv("SWM_STARTED") == NULL)
-               setenv("SWM_STARTED", "YES", 1);
-
-       /* setup all bars */
-       for (i = 0; i < ScreenCount(display); i++)
-               TAILQ_FOREACH(r, &screens[i].rl, entry) {
-                       if (winfocus == NULL)
-                               winfocus = TAILQ_FIRST(&r->ws->winlist);
-                       bar_setup(r);
-               }
-
-       unfocus_all();
-
-       grabkeys();
-       stack();
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               drain_enter_notify();
-
-       xfd = ConnectionNumber(display);
-       while (running) {
-               while (XPending(display)) {
-                       XNextEvent(display, &e);
-                       if (running == 0)
-                               goto done;
-                       if (e.type < LASTEvent) {
-                               DNPRINTF(SWM_D_EVENTQ ,"XEvent: handled: %s, "
-                                   "window: 0x%lx, type: %s (%d), %d remaining"
-                                   "\n", YESNO(handler[e.type]),
-                                   e.xany.window, geteventname(&e),
-                                   e.type, QLength(display));
-
-                               if (handler[e.type])
-                                       handler[e.type](&e);
-                       } else {
-                               DNPRINTF(SWM_D_EVENTQ, "XRandr Event: window: "
-                                   "0x%lx, type: %s (%d)\n", e.xany.window,
-                                   xrandr_geteventname(&e), e.type);
-
-                               switch (e.type - xrandr_eventbase) {
-                               case RRScreenChangeNotify:
-                                       screenchange(&e);
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
-               }
-
-               /* if we are being restarted go focus on first window */
-               if (winfocus) {
-                       rr = winfocus->ws->r;
-                       if (rr == NULL) {
-                               /* not a visible window */
-                               winfocus = NULL;
-                               continue;
-                       }
-                       /* move pointer to first screen if multi screen */
-                       if (ScreenCount(display) > 1 || outputs > 1)
-                               XWarpPointer(display, None, rr->s[0].root,
-                                   0, 0, 0, 0, X(rr),
-                                   Y(rr) + (bar_enabled ? bar_height : 0));
-
-                       a.id = SWM_ARG_ID_FOCUSCUR;
-                       focus(rr, &a);
-                       winfocus = NULL;
-                       continue;
-               }
-
-               FD_ZERO(&rd);
-               FD_SET(xfd, &rd);
-               tv.tv_sec = 1;
-               tv.tv_usec = 0;
-               if (select(xfd + 1, &rd, NULL, NULL, &tv) == -1)
-                       if (errno != EINTR)
-                               DNPRINTF(SWM_D_MISC, "select failed");
-               if (restart_wm == 1)
-                       restart(NULL, NULL);
-               if (search_resp == 1)
-                       search_do_resp();
-               if (running == 0)
-                       goto done;
-               if (bar_alarm) {
-                       bar_alarm = 0;
-                       bar_update();
-               }
-       }
-done:
-       teardown_ewmh();
-       bar_extra_stop();
-
-       for (i = 0; i < ScreenCount(display); ++i)
-               if (screens[i].bar_gc != NULL)
-                       XFreeGC(display, screens[i].bar_gc);
-
-       XFreeFontSet(display, bar_fs);
-       XCloseDisplay(display);
-
-       return (0);
-}
diff --git a/scrotwm.conf b/scrotwm.conf
deleted file mode 100644 (file)
index caca87e..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-# PLEASE READ THE MAN PAGE BEFORE EDITING THIS FILE!
-# http://opensource.conformal.com/cgi-bin/man-cgi?scrotwm
-
-# colors for focussed and unfocussed window borders
-# NOTE: all colors in this file are in hex! see XQueryColor for examples
-color_focus            = red
-color_unfocus          = rgb:88/88/88
-
-# bar settings
-bar_enabled            = 1
-bar_border_width       = 1
-bar_border[1]          = rgb:00/80/80
-bar_color[1]           = black
-bar_font_color[1]      = rgb:a0/a0/a0
-bar_font               = -*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*
-#bar_action            = baraction.sh
-#bar_delay             = 1
-#bar_justify           = left
-#bar_at_bottom         = 1
-stack_enabled          = 1
-clock_enabled          = 1
-#clock_format          = %a %b %d %R %Z %Y
-title_name_enabled     = 0
-title_class_enabled    = 0
-window_name_enabled    = 0
-#verbose_layout                = 1
-#focus_mode            = default
-#disable_border                = 1
-#border_width          = 1
-#urgent_enabled                = 1
-
-# spawn app
-# program[term]                = xterm
-# program[screenshot_all]      = screenshot.sh full
-# program[screenshot_wind]     = screenshot.sh window
-# program[lock]                = xlock
-# program[initscr]     = initscreen.sh
-# program[menu]                = dmenu_run -fn $bar_font -nb $bar_color -nf $bar_font_color -sb $bar_border -sf $bar_color
-spawn_term             = xterm
-
-# dialog box size ratio .3 >= r < 1
-dialog_ratio           = 0.6
-
-# Split a non-Xrandr dual head setup into one region per monitor
-# (non-standard driver-based multihead is not seen by scrotwm)
-# region               = screen[1]:1280x1024+0+0
-# region               = screen[1]:1280x1024+1280+0
-
-# Launch applications in a workspace of choice
-# autorun              = ws[1]:xterm
-# autorun              = ws[2]:xxxterm http://www.openbsd.org
-
-# workspace layout
-# layout               = ws[1]:4:0:0:0:vertical
-# layout               = ws[2]:0:0:0:0:horizontal
-# layout               = ws[3]:0:0:0:0:fullscreen
-
-# mod key, (windows key is Mod4) (apple key on OSX is Mod2)
-# modkey = Mod1
-
-# Clear key bindings and load new key bindings from the specified file.
-# This allows you to load pre-defined key bindings for your keyboard layout.
-# keyboard_mapping = ~/.scrotwm_us.conf
-
-# quirks
-# remove with: quirk[class:name] = NONE
-#quirk[MPlayer:xv]                     = FLOAT + FULLSCREEN + FOCUSPREV
-#quirk[OpenOffice.org 2.4:VCLSalFrame] = FLOAT
-#quirk[OpenOffice.org 3.0:VCLSalFrame] = FLOAT
-#quirk[OpenOffice.org 3.1:VCLSalFrame] = FLOAT
-#quirk[Firefox-bin:firefox-bin]                = TRANSSZ
-#quirk[Firefox:Dialog]                 = FLOAT
-#quirk[Gimp:gimp]                      = FLOAT + ANYWHERE
-#quirk[XTerm:xterm]                    = XTERM_FONTADJ
-#quirk[xine:Xine Window]                       = FLOAT + ANYWHERE
-#quirk[Xitk:Xitk Combo]                        = FLOAT + ANYWHERE
-#quirk[xine:xine Panel]                        = FLOAT + ANYWHERE
-#quirk[Xitk:Xine Window]                       = FLOAT + ANYWHERE
-#quirk[xine:xine Video Fullscreen Window] = FULLSCREEN + FLOAT
-#quirk[pcb:pcb]                                = FLOAT
-
-# EXAMPLE: define firefox program and bind to key
-# program[firefox]     = firefox http://scrotwm.org/
-# bind[firefox]                = MOD+Shift+b
diff --git a/scrotwm_cz.conf b/scrotwm_cz.conf
deleted file mode 100644 (file)
index 37baeb7..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Key bindings for Czech Republic (cz) keyboards
-# unbind with: bind[] = <keys>
-bind[cycle_layout]     = MOD+space
-bind[flip_layout]      = MOD+Shift+backslash
-bind[stack_reset]      = MOD+Shift+space
-bind[master_shrink]    = MOD+h
-bind[master_grow]      = MOD+l
-bind[master_add]       = MOD+comma
-bind[master_del]       = MOD+period
-bind[stack_inc]                = MOD+Shift+comma
-bind[stack_dec]                = MOD+Shift+period
-bind[swap_main]                = MOD+Return
-bind[focus_next]       = MOD+j
-bind[focus_prev]       = MOD+k
-bind[swap_next]                = MOD+Shift+j
-bind[swap_prev]                = MOD+Shift+k
-bind[spawn_term]       = MOD+Shift+Return
-bind[menu]             = MOD+p
-bind[quit]             = MOD+Shift+q
-bind[restart]          = MOD+q
-bind[focus_main]       = MOD+m
-bind[ws_1]             = MOD+plus
-bind[ws_2]             = MOD+ecaron
-bind[ws_3]             = MOD+scaron
-bind[ws_4]             = MOD+ccaron
-bind[ws_5]             = MOD+rcaron
-bind[ws_6]             = MOD+zcaron
-bind[ws_7]             = MOD+yacute
-bind[ws_8]             = MOD+aacute
-bind[ws_9]             = MOD+iacute
-bind[ws_10]            = MOD+eacute
-bind[ws_next]          = MOD+Right
-bind[ws_prev]          = MOD+Left
-bind[ws_next_all]      = MOD+Up
-bind[ws_prev_all]      = MOD+Down
-bind[ws_prior]         = MOD+a
-bind[screen_next]      = MOD+Shift+Right
-bind[screen_prev]      = MOD+Shift+Left
-bind[mvws_1]           = MOD+Shift+plus
-bind[mvws_2]           = MOD+Shift+ecaron
-bind[mvws_3]           = MOD+Shift+scaron
-bind[mvws_4]           = MOD+Shift+ccaron
-bind[mvws_5]           = MOD+Shift+rcaron
-bind[mvws_6]           = MOD+Shift+zcaron
-bind[mvws_7]           = MOD+Shift+yacute
-bind[mvws_8]           = MOD+Shift+aacute
-bind[mvws_9]           = MOD+Shift+iacute
-bind[mvws_10]          = MOD+Shift+eacute
-bind[bar_toggle]       = MOD+b
-bind[focus_next]       = MOD+Tab
-bind[focus_prev]       = MOD+Shift+Tab
-bind[wind_kill]                = MOD+Shift+x
-bind[wind_del]         = MOD+x
-bind[screenshot_all]   = MOD+s
-bind[screenshot_wind]  = MOD+Shift+s
-bind[float_toggle]     = MOD+t
-bind[version]          = MOD+Shift+v
-bind[lock]             = MOD+Shift+Delete
-bind[initscr]          = MOD+Shift+i
-bind[iconify]          = MOD+w
-bind[uniconify]                = MOD+Shift+w
-bind[raise_toggle]     = MOD+Shift+r
-bind[button2]          = MOD+v
-bind[width_shrink]     = MOD+equal
-bind[width_grow]       = MOD+dead_acute
-bind[height_shrink]    = MOD+Shift+equal
-bind[height_grow]      = MOD+Shift+dead_acute
-bind[move_left]                = MOD+uacute
-bind[move_right]       = MOD+parenright
-bind[move_up]          = MOD+Shift+uacute
-bind[move_down]                = MOD+Shift+parenright
-bind[name_workspace]   = MOD+Shift+slash
-bind[search_workspace] = MOD+slash
-bind[search_win]       = MOD+f
diff --git a/scrotwm_es.1 b/scrotwm_es.1
deleted file mode 100644 (file)
index 9ae026f..0000000
+++ /dev/null
@@ -1,746 +0,0 @@
-.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
-.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate$
-.Dt SCROTWM 1
-.Os
-.Sh NOMBRE
-.Nm scrotwm
-.Nd es un manejador de ventanas para X11
-.Sh SYNOPSIS
-.Nm scrotwm
-.Sh DESCRIPCIÓN
-.Nm
-es un manejador de ventanas super minimalista para X11. Intenta no superponer 
-las ventanas para que las mismas puedan usarse de manera eficiente y para cosas mas importantes. 
-Tiene configuraciones normales y no requiere que sepas un lenguaje de 
-programacion para configurarlo. Esta escrito por hackers para hackers y apunta 
-a ser pequeño, compacto y rápido. 
-.Pp
-Cuando
-.Nm
-inicia, lo primero que hace es leer el archivo de configuracion,
-.Pa scrotwm.conf .
-Ver 
-.Sx ARCHIVOS DE CONFIGURACIÓN
-.
-.Pp
-La siguiente anotacion se usa a través de esta pagina:
-.Pp
-.Bl -tag -width Ds -offset indent -compact
-.It Cm M
-Meta
-.It Cm S
-Shift
-.It Aq Cm Name
-Nombre de tecla
-.It Cm M1
-Boton 1 del mouse
-.It Cm M3
-Boton 3 del mouse
-.El
-.Pp
-.Nm
-es muy simple de usar.
-La mayoria de las acciones se hacen con los mapeos (bindings) de mouse 
-o teclado.
-Ver la sección de
-.Sx BINDINGS
-para las personalizaciones y configuraciones por defecto.
-.Sh ARCHIVOS DE CONFIGURACIÓN
-.Nm
-primero trata de abrir el archivo por defecto en el directorio del usuario,
-.Pa ~/.scrotwm.conf .
-Si ese archivo no esta disponible,
-luego trata de abrir el archivo global de configuracion
-.Pa /etc/scrotwm.conf .
-.Pp
-El formato del archivo es \*(Lttecla\*(Gt = \*(Ltconfiguracion\*(Gt.
-Por ejemplo:
-.Pp
-.Dl color_focus = red
-.Pp
-Habilitamos o deshabilitamos la opción usando 1 o 0 respectivamente.
-.Pp
-El archivo soporta las siguientes palabras clave:
-.Pp
-.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
-.It Cm autorun
-Inicia una aplicacion en un escritorio en particular al primer inicio.
-Definido por el formato ws[<idx>]:aplicacion, ej. ws[2]:xterm lanza
-xterm en el escritorio 2.
-.It Cm color_focus
-Color del borde de la ventana en foco.
-.It Cm color_unfocus
-Color del borde de la ventana fuera de foco.
-.It Cm bar_enabled
-Habilitar o deshabilitar la barra de estado.
-.It Cm bar_border Ns Bq Ar x
-Color del borde de la barra de estado en pantalla.
-.Ar x .
-.It Cm bar_border_width
-Setea el grosor de la barra de estado en pixels.
-Deshabilitado seteando 0.
-.It Cm bar_color Ns Bq Ar x
-Color de la ventana de la barra de estado en pantalla.
-.Ar x .
-.It Cm bar_font_color Ns Bq Ar x
-Color de la fuente en la barra de estado en pantalla.
-.Ar x .
-.It Cm bar_font
-Fuente de la barra de estado.
-.It Cm bar_action
-Scripts externos con populares agregados de información para la barra 
-de estado, como la vida de la bateria.
-.It Cm bar_delay
-Frecuencia de actualización, en segundos, de los scripts de la barra de 
-estado.
-.It Cm bar_at_bottom
-Puedes posicionar la statusbar en la parte inferior de la pantalla.
-.It Cm stack_enabled
-Habilitar o deshabilitar mostrar el algoritmo de apilamiento en la barra
-de estado.
-.It Cm clock_enabled
-Habilitar o deshabilitar el reloj en la barra de estado, deshabilitado 
-por defecto con un 0, para usar el reloj de la barra de estado 
-(bar_action)
-.Pa bar_action
-script.
-.It Cm dialog_ratio
-Algunas aplicaciones tienen ventanas de dialogo muy pequeñas como para 
-ser usables. Este relación (ratio) es el tamaño de la pantalla, por 
-ejemplo 0.6 es 60% del tamaño físico de la pantalla.
-.It Cm layout
-Selecciona una disposicion para usar en el primer inicio.
-Definido con el formato
-ws[idx]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode, 
-ej.
-ws[2]:-4:0:1:0:horizontal setea el escritorio 2 en horizontal, el stack 
-principal y reduce 4 puntos agregando una ventana al stack, mientras
-mantiene el comportamiento de ventanas flotantes.
-Modos posible de stack_mode
-.Pa vertical ,
-.Pa horizontal
-and
-.Pa fullscreen .
-.Pp
-Ver
-.Pa master_grow ,
-.Pa master_shrink ,  
-.Pa master_add ,  
-.Pa master_del ,
-.Pa stack_inc ,
-.Pa stack_del ,
-y
-.Pa always_raise
-para mas informacion.
-Tenga en cuenta que las opciones de stack son complicados y tienen 
-efectos secundarios.
-Uno debe familiarizarse con estos comandos antes de experimentar con la
-opcion
-.Pa layout
-.Pp
-Esta opcion no necesita un reinicio.
-.It Cm region
-Acomodar una region personalizada, removiendo cualquier autodeteción de 
-regiones que ocupe el espacio en la pantalla. 
-Definiendo el formato screen[<idx>]:WIDTHxHEIGHT+X+Y,
-e.g.\& screen[1]:800x1200+0+0.
-.It Cm term_width
-Setear un ancho minimo preferido para la terminal.
-Si el valor es mayor que 0,
-.Nm
-intentará ajustar el tamaño de la fuente de la terminal para mantener 
-el ancho de la terminal por encima de este número cuando la ventana 
-cambia de tamaño.
-Actualmente solo es soportado por
-.Xr xterm 1
-El binario de
-.Xr xterm 1
-no debe ser un setuid o setgid, que no sea el que viene por defecto en 
-la mayoria de los sistemas.
-Los usuarios pueden necesitar setear program[term] (ver la sección
-.Sx PROGRAMAS
-) para usar una copia alternativa del binario de
-.Xr xterm 1
-sin el seteo del setgid.
-.It Cm title_class_enabled
-Habilitar o deshabilitar la clase de ventana en la barre de estado.
-Habilitado seteando 1
-.It Cm title_name_enabled
-Habilitar o deshabilita el titulo de la ventana en la barra de estado.
-Habilitado seteando 1
-.It Cm urgent_enabled
-Habilitar o deshabilitar el aviso de urgencia.
-Tenga en cuenta que muchos emuladores de terminal requieren de este
-parametro habilitado para que funcione.
-En xterm, por ejemplo, hay que agregar la siguiente linea
-.Pa xterm.urgentOnBell: true
-to
-.Pa .Xdefaults .
-.It Cm window_name_enabled
-Habilitar o deshabilita el nombre de la ventana en la barra de estado.
-Habilitado seteando 1
-.It Cm verbose_layout
-Habilitar o deshabilita la notificacion del area principal y el
-stack en la barra de estado.
-Habilitado seteandolo a 1.
-.It Cm modkey
-Cambiar mod key.
-Mod1 generalmente es la tecla ALT y Mod4 la tecla de windows en una PC.
-.It Cm focus_mode
-Usando el valor de 
-.Pa follow_cursor 
-puedes hacer que el manejador de ventanas
-se enfoque en la ventana cuando el cursor pase por arriba de las mismas o
-bien cambiando de estacion de trabajo.
-.It Cm disable_border
-Remueve el borde de una sola ventana cuando la barra de estado esta desactivada.
-.It Cm border_width
-Setea el grosor del borde de la ventana en pixels.
-Deshabilitar todos los bordes seteandolo a 0.
-.It Cm program Ns Bq Ar p
-Definir una nueva accion para ejecutar un programa.
-.Ar p .
-Ver la sección de
-.Sx PROGRAMAS
-.It Cm bind Ns Bq Ar x
-Combinación de teclas para una acción
-.Ar x .
-Ver la sección
-.Sx BINDINGS
-.It Cm quirk Ns Bq Ar c:n
-Agregar un "quirk" (o forzados) para ventanas con clase
-.Ar c
-y nombre
-.Ar n .
-Ver la sección
-.Sx QUIRKS
-.El
-.Pp
-Los colores deben ser especificados por la especificación
-.Xr XQueryColor 3
-y las fuentes por la especificación
-.Xr XQueryFont 3
-.Sh PROGRAMAS
-.Nm
-te permite definir acciones personales para lanzar los programas que 
-quieras y luego obligar a la misma con una función de acciones.
-Ver la sección
-.Sx BINDINGS
-.Pp
-Los programas por defecto se describen acá:
-.Pp
-.Bl -tag -width "screenshot_wind" -offset indent -compact
-.It Cm term
-xterm
-.It Cm screenshot_all
-screenshot.sh completo
-.It Cm screenshot_wind
-screenshot.sh por ventana
-.It Cm lock
-xlock
-.It Cm initscr
-initscreen.sh
-.It Cm menu
-dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
-.El
-.Pp
-Los programas en la configuración personal, se especifican aca:
-.Pp
-.Dl program[<nombre>] = <progpath> [<arg> [... <arg>]]
-.Pp
-.Aq nombre
-es un identificador, no genera conflictos con ninguna accion o palabra 
-clave,
-.Aq progpath
-es la ruta al programa, y
-.Aq arg
-es ninguno o mas de un argumento para el programa.
-.Pp
-Las siguientes variables de configuracion en
-.Nm
-(ver 
-.Sx ARCHIVOS DE CONFIGURACIÓN
-),
-y pueden ser usadas en los campos de
-.Aq arg
-como asi tambien sustituidas por valores al momento del inicio de un 
-programa:
-.Pp
-.Bl -tag -width "$bar_font_color" -offset indent -compact
-.It Cm $bar_border
-.It Cm $bar_color
-.It Cm $bar_font
-.It Cm $bar_font_color
-.It Cm $color_focus
-.It Cm $color_unfocus
-.El
-.Pp
-Ejemplo:
-.Bd -literal -offset indent
-program[ff] = /usr/local/bin/firefox http://scrotwm.com.ar/
-bind[ff] = Mod+f # Ahora Mod+F inicia firefox
-.Ed
-.Pp
-Para deshacer lo anterior:
-.Bd -literal -offset indent
-bind[] = Mod+f
-program[ff] =
-.Ed
-.Sh BINDINGS
-.Nm
-provee muchas funciones (o acciones) accesibles por medio de la 
-asignación (bindings) de teclas o el mouse.
-.Pp
-Las corrientes asignaciones (bindings) del mouse son:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M1
-Enfoco una ventana
-.It Cm M-M1
-Muevo una ventana
-.It Cm M-M3
-Redimenciono una ventana
-.It Cm M-S-M3
-Redimenciono una ventana hasta que quede centrada
-.El
-.Pp
-Las corrientes asignaciones (bindings) de teclas son:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M-S- Ns Aq Cm Return
-term
-.It Cm M-p
-menu
-.It Cm M-S-q
-quit
-.It Cm M-q
-restart
-.Nm
-.It Cm M- Ns Aq Cm Space
-cycle_layout
-.It Cm M-S- Ns Aq Cm Space
-reset_layout
-.It Cm M-h
-master_shrink
-.It Cm M-l
-master_grow
-.It Cm M-,
-master_add
-.It Cm M-.
-master_del
-.It Cm M-S-,
-stack_inc
-.It Cm M-S-.
-stack_del
-.It Cm M- Ns Aq Cm Return
-swap_main
-.It Xo
-.Cm M-j ,
-.Cm M- Ns Aq Cm TAB
-.Xc
-focus_next
-.It Xo
-.Cm M-k ,
-.Cm M-S- Ns Aq Cm TAB
-.Xc
-focus_prev
-.It Cm M-m
-focus_main
-.It Cm M-S-j
-swap_next
-.It Cm M-S-k
-swap_prev
-.It Cm M-b
-bar_toggle
-.It Cm M-x
-wind_del
-.It Cm M-S-x
-wind_kill
-.It Cm M- Ns Aq Ar n
-.Ns ws_ Ns Ar n
-.It Cm M-S- Ns Aq Ar n
-.Ns mvws_ Ns Ar n
-.It Cm M- Ns Aq Cm Right
-ws_next
-.It Cm M- Ns Aq Cm Left
-ws_prev
-.It Cm M-a
-ws_prior
-.It Cm M-S- Ns Aq Cm Right
-screen_next
-.It Cm M-S- Ns Aq Cm Left
-screen_prev
-.It Cm M-s
-screenshot_all
-.It Cm M-S-s
-screenshot_wind
-.It Cm M-S-v
-version
-.It Cm M-t
-float_toggle
-.It Cm M-S Aq Cm Delete
-lock
-.It Cm M-S-i
-initscr
-.It Cm M-w                    
-iconify
-.It Cm M-S-w
-uniconify
-.It Cm M-S-r
-always_raise
-.It Cm M-v
-button2
-.It Cm M--
-width_shrink
-.It Cm M-=
-width_grow
-.It Cm M-S-
-height_shrink
-.It Cm M-S-=
-height_grow
-.It Cm M-[
-move_left
-.It Cm M-]
-move_right
-.It Cm M-S-[
-move_up
-.It Cm M-S-]
-move_down
-.El
-.Pp
-El nombre de las acciónes descripta a continuación:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm term
-Ejecutar una terminal
-(ver
-.Sx PROGRAMAS
-)
-.It Cm menu
-Menu
-(ver
-.Sx PROGRAMAS
-)
-.It Cm quit
-Salir
-.Nm
-.It Cm restart
-Reiniciar
-.Nm
-.It Cm cycle_layout
-Disposición de las ventanas
-.It Cm reset_layout
-Reiniciar la disposición de las ventanas
-.It Cm master_shrink
-Achicar la region principal
-.It Cm master_grow
-Agrandar la region principal
-.It Cm master_add
-Agregar una ventana a la region principal
-.It Cm master_del
-Quitar una ventana de la region principal
-.It Cm stack_inc
-Agregar columnas/filas a las pilas
-.It Cm stack_del
-Quitar columnas/filas de las pilas
-.It Cm swap_main
-Mover la ventana corriente a la region principal
-.It Cm focus_next
-Enfocar la proxima ventana en la estación de trabajo
-.It Cm focus_prev
-Enfocar la anterior ventana en la estación de trabajo
-.It Cm focus_main
-Enfocar en la ventana principal de la estación de trabajo
-.It Cm swap_next
-Ejecutar con la siguiente ventana en la estación de trabajo
-.It Cm swap_prev
-Ejecutar con la anterior ventana en la estación de trabajo
-.It Cm bar_toggle
-Cambiar la barra de estado en todas las estaciones de trabajo
-.It Cm wind_del
-Borrar la ventana corriente en la estación de trabajo
-.It Cm wind_kill
-Destruir la ventana corriente en la estación de trabajo
-.It Cm ws_ Ns Ar n
-Cambiar entre estaciones de trabajo
-.Ar n ,
-donde
-.Ar n
-es 1 por 10
-.It Cm mvws_ Ns Ar n
-Mover la ventana corriente a una estación de trabajo
-.Ar n ,
-donde
-.Ar n
-es 1 por 10
-.It Cm ws_next
-Cambiar a la proxima estación de trabajo con una ventana en ella
-.It Cm ws_prev
-Cambiar a la anterior estación de trabajo con una ventana en ella
-.It Cm screen_next
-Mover el puntero a la proxima region
-.It Cm screen_prev
-Mover el puntero a la anterior region
-.It Cm screenshot_all
-Tomar una captura de pantalla de todo la pantalla (si esta habilitado)
-(ver
-.Sx PROGRAMAS
-)
-.It Cm screenshot_wind
-Tomar una captura de pantalla de la ventana seleccionada (si esta habilitado)
-(ver
-.Sx PROGRAMAS
-)
-.It Cm version
-Mostrar la version en la barra de estado
-.It Cm float_toggle
-Mostar la ventana en foco entre las flotantes y acomodadas
-.It Cm lock
-Bloquear pantalla
-(ver
-.Sx PROGRAMAS
-)
-.It Cm initscr
-Reiniciar la pantalla
-(ver
-.Sx PROGRAMAS
-)
-.It Cm iconify
-Minimiza (unmap) la ventana en foco.
-.It Cm uniconify
-Maximiza (map) la ventana seleccionada por dmenu.
-.It Cm always_raise
-Cuando se establece las ventanas en cascada se esconden las 
-ventanas flotantes.
-.It Cm button2
-Falsifica el boton del medio del mouse.
-.It Cm width_shrink
-Reducir el ancho de una ventana flotante.
-.It Cm width_grow  
-Agranda el ancho de una ventana flotante.
-.It Cm height_shrink
-Reducir la altura de una ventana flotante.
-.It Cm height_grow
-Agranda la altura de una ventana flotante.
-.It Cm move_left
-Mueve la ventana flotante un paso a la izquierda.
-.It Cm move_right
-Mueve la ventana flotante un paso a la derecha.
-.It Cm move_up
-Mueve la ventana flotante un paso arriba.
-.It Cm move_down
-Mueve la ventana flotante un paso abajo.
-.El
-.Pp
-Personalizar mapeos (bindings) en el archivo de configuración:
-.Pp
-.Dl bind[<accion>] = <teclas>
-.Pp
-.Aq accion
-una de las acciones listadas (o ninguna) y
-.Aq teclas
-una o mas teclas modificadas (puede ser ninguna tambien)
-(MOD, Mod1, Shift, etc.) y una o mas teclas normales
-(b, barra espaciadora, etc.), separadas por un "+".
-Por ejemplo:
-.Bd -literal -offset indent
-bind[reset] = Mod4+q # combinación Tecla de Windows + q reinicia
-bind[] = Mod1+q # des-hace la combinación Alt + q
-.Ed
-.Pp
-Multiples combinaciones de teclas pueden hacer lo mismo.
-.Sh QUIRKS
-.Nm
-te da "quirks" (o forzados) ventanas que tienen que ser tratas de manera especial,
-como por ejemplo, popups, aplicaciones de pantalla completa, etc.
-.Pp
-Los "quirks" (o forzados) por defecto son:
-.Pp
-.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
-.It Firefox\-bin:firefox\-bin
-TRANSSZ
-.It Firefox:Dialog
-FLOAT
-.It Gimp:gimp
-FLOAT + ANYWHERE
-.It MPlayer:xv
-FLOAT + FULLSCREEN
-.It OpenOffice.org 2.4:VCLSalFrame
-FLOAT
-.It OpenOffice.org 3.1:VCLSalFrame
-FLOAT
-.It pcb:pcb
-FLOAT
-.It xine:Xine Window
-FLOAT + ANYWHERE
-.It xine:xine Panel
-FLOAT + ANYWHERE
-.It xine:xine Video Fullscreen Window
-FULLSCREEN + FLOAT
-.It Xitk:Xitk Combo
-FLOAT + ANYWHERE
-.It Xitk:Xine Window
-FLOAT + ANYWHERE
-.It XTerm:xterm
-XTERM_FONTADJ
-.El
-.Pp
-Los "quirks" (o forzados) se describen a continuación:
-.Pp
-.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
-.It FLOAT
-Esta ventana no tiene que ser acomodada, pero le permitimos flotar libremente.
-.It TRANSSZ
-Ajusta el tamaño de las ventanas transitorias que son demasiado pequeñas utilizando dialog_ratio
-(ver
-.Sx ARCHIVOS DE CONFIGURACIÓN ) .
-.It ANYWHERE
-Permite que la ventana se ponga donde quiera.
-.It XTERM_FONTADJ
-Ajusta las fuentes de xterm cuando se redimenciona.
-.It FULLSCREEN
-Quita el borde para permitir las ventanas en pantalla completa.
-.It FOCUSPREV
-El enfoque de salida fuerza la solicitud de aplicacisn que 
-anteriormente se centraba en la aplicacion anterior del stack.
-.El
-.Pp
-Las configuraciones de "quirks" (o forzados) en el archivo de configuración se ven a continuación:
-.Pp
-.Dl quirk[<clases>:<nombre>] = <quirk> [ + <quirk> ... ]
-.Pp
-.Aq clases
-y
-.Aq nombre
-especifica la ventana en la cual el "quirk(s)" (o forzados) se aplica, y
-.Aq quirk
-es uno de los "quirks" (o forzados) de la lista.
-Por ejemplo:
-.Bd -literal -offset indent
-quirk[MPlayer:xv] = FLOAT + FULLSCREEN # dejamos que mplayer funcione libremente
-quirk[pcb:pcb] = NONE  # borramos el quirk existente
-.Ed
-.Pp
-Podes obtener
-.Aq clases
-y
-.Aq nombre
-corriendo el programa xprop(1) y luego clickear en la ventana que quieras.
-En el proximo ejemplo, podremos verlo en acción con una ventana de Firefox:
-.Bd -literal -offset indent
-$ xprop | grep WM_CLASS
-WM_CLASS(STRING) = "Navigator", "Firefox"
-.Ed
-.Sh EWMH
-.Nm
-parcialmente implementa los Consejos de ventana extendido Manager (EWMH) especificacion.
-Esto permite el control de las ventanas, asi como
-.Nm
-si a partir de scripts y programas externos. Esto se logra mediante
-.Nm
-responder a ciertos eventos ClientMessage. Desde la terminal de estos eventos
-se puede enviar facilmente el uso de herramientas tales como
-.Xr wmctrl 1
-y
-.Xr xdotool 1 .
-para el
-formato real de estos eventos ClientMessage, consulte la especificacion EWMH.
-.Pp
-La Identificacion de la ventana actualmente enfocada se almacena en el _NET_ACTIVE_WINDOW
-propiedad de la ventana raiz. Esto puede ser usado por ejemplo para recuperar el
-titulo de la ventana activa con
-.Xr xprop 1
-y
-.Xr grep 1 :
-.Bd -literal -offset indent
-$ WINDOWID=`xprop \-root _NET_ACTIVE_WINDOW | grep \-o "0x.*"`
-$ xprop \-id $WINDOWID WM_NAME | grep \-o "\\".*\\""
-.Ed
-.Pp
-Una ventana se puede enfocar mediante el envio de un mensaje del cliente _NET_ACTIVE_WINDOW
-a la ventana principal. Por ejemplo, usando
-.Xr wmctrl 1
-para enviar el mensaje
-(suponiendo que 0x4a0000b es el ID de la ventana para ser especifico):
-.Bd -literal -offset indent
-$ wmctrl \-i \-a 0x4a0000b
-.Ed
-.Pp
-Ventanas se pueden cerrar mediante el envmo de un mensaje del cliente _NET_CLOSE_WINDOW
-a la ventana principal. Por ejemplo, usando
-.Xr wmctrl 1
-para enviar el mensaje
-(suponiendo que 0x4a0000b es el ID de la ventana se cierre):
-.Bd -literal -offset indent
-$ wmctrl \-i \-c 0x4a0000b
-.Ed
-.Pp
-Las ventanas se pueden flotar y flotar sin-mediante la adicion o eliminacion de la
-_NET_WM_STATE_ABOVE atom desde _NET_WM_STATE la propiedad de la ventana
-Esto se puede lograr mediante el envio de un mensaje a los clientes _NET_WM_STATE
-raiz de la ventana. Por ejemplo, el siguiente cambia el estado de la flota.
-.Xr wmctrl 1
-para enviar el mensaje (suponiendo que 0x4a0000b es el ID de la ventana flotante
-o no-flotante):
-.Bd -literal -offset indent
-$ wmctrl \-i \-r 0x4a0000b \-b toggle,_NET_WM_STATE_ABOVE
-.Ed
-.Pp
-Ventanas flotantes tambien se puede cambiar el tamano y movido por el envio de un
-_NET_MOVERESIZE_WINDOW Mensaje del cliente de la ventana raiz. Por ejemplo,
-uso
-.Xr wmctrl 1
-para enviar el mensaje (suponiendo que 0x4a0000b es el ID de
-la ventana a redimensionar / mover):
-.Bd -literal -offset indent
-$ wmctrl \-i \-r 0x4a0000b \-e 0,100,50,640,480
-.Ed
-.Pp
-Esto mueve la ventana de (100,50) y cambia el tamaqo a 640x480.
-.Pp
-Todos los eventos _NET_MOVERESIZE_WINDOW recibido por las ventanas apiladas se ignoran.
-.Pp
-.Sh SIGNALS
-Enviando
-.Nm
-una senal de HUP reinicia scrotwm.
-.Pp
-.Sh ARCHIVOS
-.Bl -tag -width "/etc/scrotwm.confXXX" -compact
-.It Pa ~/.scrotwm.conf
-.Nm
-archivo de configuración especifico del usuario.
-.It Pa /etc/scrotwm.conf
-.Nm
-configuraciones globales.
-.El
-.Sh HISTORIA
-.Nm
-fue inspirado en xmonad y dwm.
-.Sh AUTORES
-.An -nosplit
-.Pp
-.Nm
-fue escrito por
-.An Marco Peereboom Aq marco@peereboom.us ,
-.An Ryan Thomas McBride Aq mcbride@countersiege.com
-and
-.An Darrin Chandler Aq dwchandler@stilyagin.com .
-.Sh BUGS
-Actualmente el menu, se llama con
-.Cm M-p ,
-depende de dmenu.
diff --git a/scrotwm_es.conf b/scrotwm_es.conf
deleted file mode 100644 (file)
index b585381..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Key bindings for Spanish (es) keyboards
-# unbind with: bind[] = <keys>
-bind[cycle_layout]     = MOD+space
-bind[flip_layout]      = MOD+Shift+backslash
-bind[stack_reset]      = MOD+Shift+space
-bind[master_shrink]    = MOD+h
-bind[master_grow]      = MOD+l
-bind[master_add]       = MOD+comma
-bind[master_del]       = MOD+period
-bind[stack_inc]                = MOD+Shift+comma
-bind[stack_dec]                = MOD+Shift+period
-bind[swap_main]                = MOD+Return
-bind[focus_next]       = MOD+j
-bind[focus_prev]       = MOD+k
-bind[swap_next]                = MOD+Shift+j
-bind[swap_prev]                = MOD+Shift+k
-bind[spawn_term]       = MOD+Shift+Return
-bind[menu]             = MOD+p
-bind[quit]             = MOD+Shift+q
-bind[restart]          = MOD+q
-bind[focus_main]       = MOD+m
-bind[ws_1]             = MOD+1
-bind[ws_2]             = MOD+2
-bind[ws_3]             = MOD+3
-bind[ws_4]             = MOD+4
-bind[ws_5]             = MOD+5
-bind[ws_6]             = MOD+6
-bind[ws_7]             = MOD+7
-bind[ws_8]             = MOD+8
-bind[ws_9]             = MOD+9
-bind[ws_10]            = MOD+0
-bind[ws_next]          = MOD+Right
-bind[ws_prev]          = MOD+Left
-bind[ws_next_all]      = MOD+Up
-bind[ws_prev_all]      = MOD+Down
-bind[ws_prior]         = MOD+a
-bind[screen_next]      = MOD+Shift+Right
-bind[screen_prev]      = MOD+Shift+Left
-bind[mvws_1]           = MOD+Shift+1
-bind[mvws_2]           = MOD+Shift+2
-bind[mvws_3]           = MOD+Shift+3
-bind[mvws_4]           = MOD+Shift+4
-bind[mvws_5]           = MOD+Shift+5
-bind[mvws_6]           = MOD+Shift+6
-bind[mvws_7]           = MOD+Shift+7
-bind[mvws_8]           = MOD+Shift+8
-bind[mvws_9]           = MOD+Shift+9
-bind[mvws_10]          = MOD+Shift+0
-bind[bar_toggle]       = MOD+b
-bind[focus_next]       = MOD+Tab
-bind[focus_prev]       = MOD+Shift+Tab
-bind[wind_kill]                = MOD+Shift+x
-bind[wind_del]         = MOD+x
-bind[screenshot_all]   = MOD+s
-bind[screenshot_wind]  = MOD+Shift+s
-bind[float_toggle]     = MOD+t
-bind[version]          = MOD+Shift+v
-bind[lock]             = MOD+Shift+Delete
-bind[initscr]          = MOD+Shift+i
-bind[iconify]          = MOD+w
-bind[uniconify]                = MOD+Shift+w
-bind[raise_toggle]     = MOD+Shift+r
-bind[button2]          = MOD+v
-bind[width_shrink]     = MOD+apostrophe
-bind[width_grow]       = MOD+exclamdown
-bind[height_shrink]    = MOD+Shift+apostrophe
-bind[height_grow]      = MOD+Shift+exclamdown
-bind[move_left]                = MOD+dead_grave
-bind[move_right]       = MOD+plus
-bind[move_up]          = MOD+Shift+dead_grave
-bind[move_down]                = MOD+Shift+plus
-bind[name_workspace]   = MOD+Shift+slash
-bind[search_workspace] = MOD+slash
-bind[search_win]       = MOD+f
diff --git a/scrotwm_fr.conf b/scrotwm_fr.conf
deleted file mode 100644 (file)
index d56aabb..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Key bindings for French (fr) keyboards
-# unbind with: bind[] = <keys>
-bind[cycle_layout]     = MOD+space
-bind[flip_layout]      = MOD+Shift+backslash
-bind[stack_reset]      = MOD+Shift+space
-bind[master_shrink]    = MOD+h
-bind[master_grow]      = MOD+l
-bind[master_add]       = MOD+comma
-bind[master_del]       = MOD+semicolon
-bind[stack_inc]                = MOD+Shift+comma
-bind[stack_dec]                = MOD+Shift+semicolon
-bind[swap_main]                = MOD+Return
-bind[focus_next]       = MOD+j
-bind[focus_prev]       = MOD+k
-bind[swap_next]                = MOD+Shift+j
-bind[swap_prev]                = MOD+Shift+k
-bind[spawn_term]       = MOD+Shift+Return
-bind[menu]             = MOD+p
-bind[quit]             = MOD+Shift+q
-bind[restart]          = MOD+q
-bind[focus_main]       = MOD+m
-bind[ws_1]             = MOD+ampersand
-bind[ws_2]             = MOD+eacute
-bind[ws_3]             = MOD+quotedbl
-bind[ws_4]             = MOD+apostrophe
-bind[ws_5]             = MOD+parenleft
-bind[ws_6]             = MOD+hyphen
-bind[ws_7]             = MOD+egrave
-bind[ws_8]             = MOD+underscore
-bind[ws_9]             = MOD+ccedilla
-bind[ws_10]            = MOD+agrave
-bind[ws_next]          = MOD+Right
-bind[ws_prev]          = MOD+Left
-bind[ws_next_all]      = MOD+Up
-bind[ws_prev_all]      = MOD+Down
-bind[ws_prior]         = MOD+a
-bind[screen_next]      = MOD+Shift+Right
-bind[screen_prev]      = MOD+Shift+Left
-bind[mvws_1]           = MOD+Shift+ampersand
-bind[mvws_2]           = MOD+Shift+eacute
-bind[mvws_3]           = MOD+Shift+quotedbl
-bind[mvws_4]           = MOD+Shift+apostrophe
-bind[mvws_5]           = MOD+Shift+parenleft
-bind[mvws_6]           = MOD+Shift+hyphen
-bind[mvws_7]           = MOD+Shift+egrave
-bind[mvws_8]           = MOD+Shift+underscore
-bind[mvws_9]           = MOD+Shift+ccedilla
-bind[mvws_10]          = MOD+Shift+agrave
-bind[bar_toggle]       = MOD+b
-bind[focus_next]       = MOD+Tab
-bind[focus_prev]       = MOD+Shift+Tab
-bind[wind_kill]                = MOD+Shift+x
-bind[wind_del]         = MOD+x
-bind[screenshot_all]   = MOD+s
-bind[screenshot_wind]  = MOD+Shift+s
-bind[float_toggle]     = MOD+t
-bind[version]          = MOD+Shift+v
-bind[lock]             = MOD+Shift+Delete
-bind[initscr]          = MOD+Shift+i
-bind[iconify]          = MOD+w
-bind[uniconify]                = MOD+Shift+w
-bind[raise_toggle]     = MOD+Shift+r
-bind[button2]          = MOD+v
-bind[width_shrink]     = MOD+minus
-bind[width_grow]       = MOD+equal
-bind[height_shrink]    = MOD+Shift+minus
-bind[height_grow]      = MOD+Shift+equal
-bind[move_left]                = MOD+ugrave
-bind[move_right]       = MOD+asterisk
-bind[move_up]          = MOD+Shift+ugrave
-bind[move_down]                = MOD+Shift+asterisk
-bind[name_workspace]   = MOD+Shift+slash
-bind[search_workspace] = MOD+slash
-bind[search_win]       = MOD+f
diff --git a/scrotwm_fr_ch.conf b/scrotwm_fr_ch.conf
deleted file mode 100644 (file)
index f78c5bb..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Key bindings for Swiss French (FR_CH) keyboards
-# unbind with: bind[] = <keys>
-bind[cycle_layout]     = MOD+space
-bind[flip_layout]      = MOD+Shift+backslash
-bind[stack_reset]      = MOD+Shift+space
-bind[master_shrink]    = MOD+h
-bind[master_grow]      = MOD+l
-bind[master_add]       = MOD+comma
-bind[master_del]       = MOD+period
-bind[stack_inc]                = MOD+Shift+comma
-bind[stack_dec]                = MOD+Shift+period
-bind[swap_main]                = MOD+Return
-bind[focus_next]       = MOD+j
-bind[focus_prev]       = MOD+k
-bind[swap_next]                = MOD+Shift+j
-bind[swap_prev]                = MOD+Shift+k
-bind[spawn_term]       = MOD+Shift+Return
-bind[menu]             = MOD+p
-bind[quit]             = MOD+Shift+q
-bind[restart]          = MOD+q
-bind[focus_main]       = MOD+m
-bind[ws_1]             = MOD+1
-bind[ws_2]             = MOD+2
-bind[ws_3]             = MOD+3
-bind[ws_4]             = MOD+4
-bind[ws_5]             = MOD+5
-bind[ws_6]             = MOD+6
-bind[ws_7]             = MOD+7
-bind[ws_8]             = MOD+8
-bind[ws_9]             = MOD+9
-bind[ws_10]            = MOD+0
-bind[ws_next]          = MOD+Right
-bind[ws_prev]          = MOD+Left
-bind[ws_next_all]      = MOD+Up
-bind[ws_prev_all]      = MOD+Down
-bind[ws_prior]         = MOD+a
-bind[screen_next]      = MOD+Shift+Right
-bind[screen_prev]      = MOD+Shift+Left
-bind[mvws_1]           = MOD+Shift+1
-bind[mvws_2]           = MOD+Shift+2
-bind[mvws_3]           = MOD+Shift+3
-bind[mvws_4]           = MOD+Shift+4
-bind[mvws_5]           = MOD+Shift+5
-bind[mvws_6]           = MOD+Shift+6
-bind[mvws_7]           = MOD+Shift+7
-bind[mvws_8]           = MOD+Shift+8
-bind[mvws_9]           = MOD+Shift+9
-bind[mvws_10]          = MOD+Shift+0
-bind[bar_toggle]       = MOD+b
-bind[focus_next]       = MOD+Tab
-bind[focus_prev]       = MOD+Shift+Tab
-bind[wind_kill]                = MOD+Shift+x
-bind[wind_del]         = MOD+x
-bind[screenshot_all]   = MOD+s
-bind[screenshot_wind]  = MOD+Shift+s
-bind[float_toggle]     = MOD+t
-bind[version]          = MOD+Shift+v
-bind[lock]             = MOD+Shift+Delete
-bind[initscr]          = MOD+Shift+i
-bind[iconify]          = MOD+w
-bind[uniconify]                = MOD+Shift+w
-bind[raise_toggle]     = MOD+Shift+r
-bind[button2]          = MOD+v
-bind[width_shrink]     = MOD+minus
-bind[width_grow]       = MOD+egrave
-bind[height_shrink]    = MOD+Shift+minus
-bind[height_grow]      = MOD+Shift+egrave
-bind[move_left]                = MOD+eacute
-bind[move_right]       = MOD+agrave
-bind[move_up]          = MOD+Shift+eacute
-bind[move_down]                = MOD+Shift+agrave
-bind[name_workspace]   = MOD+Shift+apostrophe
-bind[search_workspace] = MOD+apostrophe
-bind[search_win]       = MOD+f
diff --git a/scrotwm_it.1 b/scrotwm_it.1
deleted file mode 100644 (file)
index 5121be5..0000000
+++ /dev/null
@@ -1,755 +0,0 @@
-.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
-.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: September 15 2011 $
-.Dt SCROTWM 1
-.Os
-.Sh NOME
-.Nm scrotwm
-.Nd gestore di finestre per X11
-.Sh SINTASSI
-.Nm scrotwm
-.Sh DESCRIZIONE
-.Nm
-? un gestore di finestre minimale che cerca di stare in disparte, in modo
-che il prezioso spazio sullo schermo possa essere usato per cose pi?
-importanti. Hai dei default sensati e non costringe l'utente ad imparare
-un linguaggio di programmazione per configurarlo. ? stato scritto dagli
-hacker per gli hacker e cerca di essere piccolo, compatto e veloce.
-.Pp
-Quando
-.Nm
-viene avviato, legge le impostazioni presenti nel file di configurazione
-.Pa scrotwm.conf .
-Vedere la sezione
-.Sx FILE DI CONFIGURAZIONE
-pi? sotto.
-.Pp
-In questa pagina di manuale viene usata la seguente notazione:
-.Pp
-.Bl -tag -width Ds -offset indent -compact
-.It Cm M
-Meta
-.It Cm S
-Shift
-.It Aq Cm Nome
-Tasto nome
-.It Cm M1
-Tasto 1 (sinistro) del mouse
-.It Cm M3
-Tasto 3 (destro) del mouse
-.El
-.Pp
-.Nm
-? molto semplice da usare. La maggior parte delle operazioni vengono
-svolte usando combinazioni di tasti sulla tastiera o sul mouse.
-Vedere la sezione
-.Sx SCORCIATOIE
-pi? sotto per i default e le possibilit? di personalizzazione.
-.Sh FILE DI CONFIGURAZIONE
-.Nm
-prova per prima cosa ad aprire il file di configurazione personale
-dell'utente,
-.Pa ~/.scrotwm.conf .
-Se il file in questione non ? disponibile, prova ad usare il file di
-configurazione globale
-.Pa /etc/scrotwm.conf .
-.Pp
-Il formato di questo file ? \*(Ltchiave\*(Gt = \*(Ltvalore\*(Gt.
-Per esempio:
-.Pp
-.Dl color_focus = red
-.Pp
-Per abilitare o disabilitare un'opzione, usare i valori 1 o 0
-rispettivamente.
-.Pp
-Il file supporta le seguenti chiavi:
-.Pp
-.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
-.It Cm autorun
-Esegue un'applicazione nel workspace specificato all'avvio.
-Definito nel formato ws[<idx>]:applicazione, eg. ws[2]:xterm esegue un
-xterm nell'area di lavoro 2.
-.It Cm color_focus
-Colore del bordo della finestra che ha il focus.
-.It Cm color_unfocus
-Colore del bordo delle finestre che non hanno il focus.
-.It Cm bar_enabled
-Abilita o disabilita la barra di stato.
-.It Cm bar_border Ns Bq Ar x
-Colore del bordo della barra di stato nello schermo
-.Ar x .
-.It Cm bar_border_width
-Spessore del bordo attorno alla barra di stato in pixel. Il bordo
-pu? essere disabilitato usando il valore 0.
-.It Cm bar_color Ns Bq Ar x
-Colore della barra di stato nello schermo
-.Ar x .
-.It Cm bar_font_color Ns Bq Ar x
-Colore del testo della barra di stato nello schermo
-.Ar x .
-.It Cm bar_font
-Font della barra di stato.
-.It Cm bar_action
-Script esterno che aggiunge informazioni come la carica della batteria alla
-barra di stato.
-.It Cm bar_delay
-Frequenza di aggiornamento, in secondi, dello script esterno che aggiunge
-informazioni alla barra di stato.
-.It Cm bar_at_bottom
-Posiziona la barra di stato sul fondo dello schermo anzich? in cima.
-.It Cm stack_enabled
-Abilita o disabilita la visualizzazione dell'algoritmo di stacking
-corrente nella barra di stato.
-.It Cm clock_enabled
-Abilita o disabilita l'orologio nella barra di stato. Se disabilitato,
-usando il valore 0, ? possibile usare un orologio personalizzato nello
-script specificato in
-.Pa bar_action .
-.It Cm dialog_ratio
-Alcune applicazioni hanno finestre di dialogo troppo piccole per risultare
-utili. Questa ? la percentuale dello schermo che verr? usata per le finestre
-di dialogo: ad esempio, 0.6 indica il 60% della dimensione fisica dello
-schermo.
-.It Cm layout
-Layout da utilizzare all'avvio. Definito nel formato
-ws[<idx>]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode,
-eg. ws[2]:-4:0:1:0:horizontal assegna il layout orizzontale all'area di
-lavoro 2, riduce l'area principale di 4 unit?, aggiunge una finestra allo
-stack e mantiene il comportamento predefinito per quanto riguarda le
-finestre floating.
-I valori possibili per stack_mode sono
-.Pa vertical ,
-.Pa horizontal
-e
-.Pa fullscreen .
-.Pp
-Fare riferimento a
-.Pa master_grow ,
-.Pa master_shrink ,
-.Pa master_add ,
-.Pa master_del ,
-.Pa stack_inc ,
-.Pa stack_del
-e
-.Pa always_raise
-per ulteriori informazioni.
-Queste impostazioni sono complesse e hanno effetti secondari; ? opportuno
-familiarizzare con questi comandi prima di modificare l'opzione
-.Pa layout .
-.Pp
-Questa impostazione non viene applicata dopo il restart.
-.It Cm region
-Alloca una regione personalizzata, rimuovendo qualsiasi regione
-automaticamente rilevata stia occupando lo stesso spazio sullo schermo.
-Definita nel formato screen[<idx>]:LARGHEZZAxALTEZZA+X+Y, ad esempio
-\& screen[1]:800x1200+0+0.
-.Pp
-Per fare s? che pi? monitor vengano considerati come una singola entit?
-? sufficiente creare una regione sufficientemente grande da contenerli,
-eg. screen[1]:2048x760+0+0 unisce due monitor con risoluzione 1024x768
-posizionati uno di fianco all'altro.
-.It Cm term_width
-Imposta la dimensione minima preferita per il terminale. Se questo valore
-? maggiore di 0,
-.Nm
-cercher? di riaggiustare la dimensione del testo nel terminale in modo che
-la larghezza del terminale rimanga sopra il valore quando la finestra
-viene ridimensionata. Al momento solo
-.Xr xterm 1
-? supportato. Il binario di
-.Xr xterm 1
-deve essere setuid o setgid perch? questo funzioni: nella maggior parte dei
-sistemi, questo ? il default. L'utente potrebbe voler impostare
-program[term] (vedere la sezione
-.Sx PROGRAMMI
-pi? sotto) per usare una seconda copia del binario di
-.Xr xterm 1
-che non abbia il bit setgid impostato.
-.It Cm title_class_enabled
-Abilita o disabilita la visualizzazione della classe della finestra nella
-barra di stato. Impostare a 1 per abilitare.
-.It Cm title_name_enabled
-Abilita o disabilita la visualizzazione del titolo della finestra nella
-barra di stato. Impostare a 1 per abilitare.
-.It Cm urgent_enabled
-Abilita o disabilita l'hint "urgente".
-In molti emulatori di terminale, il supporto deve essere abilitato
-separatamente: per xterm, ad esempio, ? necessario aggiungere la riga
-.Pa xterm.urgentOnBell: true
-al file
-.Pa .Xdefaults .
-.It Cm window_name_enabled
-Abilita o disabilita la visualizzazione del nome della finestra nella
-barra di stato. Impostare a 1 per abilitare.
-.It Cm verbose_layout
-Abilita o disabilita la visualizzazione dei valori correnti di master e
-stack nella barra di stato. Impostare a 1 per abilitare.
-.It Cm modkey
-Cambia il tasto modificatore.
-Solitamente Mod1 ? il tasto ALT e Mod4 ? il tasto Windows su un PC.
-.It Cm focus_mode
-Se viene usato il valore
-.Pa follow_cursor ,
-il gestore di finestre dar? il focus alla finestra sotto il puntatore
-quando si cambia area di lavoro o si creano finestre.
-.It Cm disable_border
-Rimuovi il bordo dalle finestre se la barra di stato ? nascosta e c'?
-una sola finestra sullo schermo.
-.It Cm border_width
-Spessore del bordo delle finestre in pixel. Il valore 0 disabilita il bordo.
-.It Cm program Ns Bq Ar p
-Definisce una nuova azione per lanciare il programma
-.Ar p .
-Vedere la sezione
-.Sx PROGRAMMI
-pi? sotto.
-.It Cm bind Ns Bq Ar x
-Assegna una combinazione di tasti all'azione
-.Ar x .
-Vedere la sezione
-.Sx SCORCIATOIE
-pi? sotto.
-.It Cm quirk Ns Bq Ar c:n
-Aggiunge un "quirk" per le finestre di classe
-.Ar c
-e nome
-.Ar n .
-Vedere la sezione
-.Sx QUIRKS
-pi? sotto.
-.El
-.Pp
-I colori devono essere specificati nel formato usato da
-.Xr XQueryColor 3
-e i font in quello usato da
-.Xr XQueryFont 3 .
-.Pp
-Per avere una lista dei font disponibili sul proprio sistema utilizzare
-.Xr fc-list 1
-o
-.Xr xlsfonts 1 .
-L'applicazione
-.Xr xfontsel 1
-? utile per visualizzare la X Logical Font Description ("XLFD") usata per
-la chiave
-.Pa bar_font .
-.Sh PROGRAMMI
-.Nm
-consente la definizione di azioni personalizzate per lanciare programmi di
-propria scelta, che possono essere assegnate a combinazioni di tasti nello
-stesso modo in cui ? possibile farlo con le azioni predefinite.
-Vedere la sezione
-.Sx SCORCIATOIE
-pi? sotto.
-.Pp
-I programmi di default sono descritte qui sotto:
-.Pp
-.Bl -tag -width "screenshot_wind" -offset indent -compact
-.It Cm term
-xterm
-.It Cm screenshot_all
-screenshot.sh full
-.It Cm screenshot_wind
-screenshot.sh window
-.It Cm lock
-xlock
-.It Cm initscr
-initscreen.sh
-.It Cm menu
-dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
-.El
-.Pp
-I programmi personalizzati vengono specificati con la seguente sintassi:
-.Pp
-.Dl program[<nome>] = <percorso> [<arg> [... <arg>]]
-.Pp
-.Aq nome
-? un qualsiasi identificatore che non va in conflitto con un'azione
-predefinita o una chiave,
-.Aq percorso
-? il programma desiderato, e
-.Aq arg
-sono zero o pi? argomenti da passare al programma.
-.Pp
-Le seguenti variabili rappresentano valori impostabili in
-.Nm
-(vedere la sezione
-.Sx FILE DI CONFIGURAZIONE
-sopra), e possono essere usati nel campo
-.Aq arg
-dove saranno sostituite con il valore al momento del lancio del programma:
-.Pp
-.Bl -tag -width "$bar_font_color" -offset indent -compact
-.It Cm $bar_border
-.It Cm $bar_color
-.It Cm $bar_font
-.It Cm $bar_font_color
-.It Cm $color_focus
-.It Cm $color_unfocus
-.El
-.Pp
-Esempio:
-.Bd -literal -offset indent
-program[ff] = /usr/local/bin/firefox http://scrotwm.org/
-bind[ff] = Mod+f # adesso Mod+F lancia firefox
-.Ed
-.Pp
-Per eliminare la combinazione precedente:
-.Bd -literal -offset indent
-bind[] = Mod+f
-program[ff] =
-.Ed
-.Pp
-.Sh SCORCIATOIE
-.Nm
-fornisce molte funzioni (o azioni) accessibili tramite combinazioni di
-tasti sul mouse o sulla tastiera.
-.Pp
-Le scorciatoie assegnate al mouse sono:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M1
-D? focus alla finestra
-.It Cm M-M1
-Muove la finestra
-.It Cm M-M3
-Ridimensiona la finestra
-.It Cm M-S-M3
-Ridimensiona la finestra mantenendola centrata
-.El
-.Pp
-Le scorciatoie da tastiera di default sono:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M-S- Ns Aq Cm Return
-term
-.It Cm M-p
-menu
-.It Cm M-S-q
-quit
-.It Cm M-q
-restart
-.It Cm M- Ns Aq Cm Space
-cycle_layout
-.It Cm M-S- Ns Aq Cm Space
-reset_layout
-.It Cm M-h
-master_shrink
-.It Cm M-l
-master_grow
-.It Cm M-,
-master_add
-.It Cm M-.
-master_del
-.It Cm M-S-,
-stack_inc
-.It Cm M-S-.
-stack_del
-.It Cm M- Ns Aq Cm Return
-swap_main
-.It Xo
-.Cm M-j ,
-.Cm M- Ns Aq Cm TAB
-.Xc
-focus_next
-.It Xo
-.Cm M-k ,
-.Cm M-S- Ns Aq Cm TAB
-.Xc
-focus_prev
-.It Cm M-m
-focus_main
-.It Cm M-S-j
-swap_next
-.It Cm M-S-k
-swap_prev
-.It Cm M-b
-bar_toggle
-.It Cm M-x
-wind_del
-.It Cm M-S-x
-wind_kill
-.It Cm M- Ns Aq Ar n
-.Ns ws_ Ns Ar n
-.It Cm M-S- Ns Aq Ar n
-.Ns mvws_ Ns Ar n
-.It Cm M- Ns Aq Cm Right
-ws_next
-.It Cm M- Ns Aq Cm Left
-ws_prev
-.It Cm M-a
-ws_prior
-.It Cm M-S- Ns Aq Cm Right
-screen_next
-.It Cm M-S- Ns Aq Cm Left
-screen_prev
-.It Cm M-s
-screenshot_all
-.It Cm M-S-s
-screenshot_wind
-.It Cm M-S-v
-version
-.It Cm M-t
-float_toggle
-.It Cm M-S Aq Cm Delete
-lock
-.It Cm M-S-i
-initscr
-.It Cm M-w
-iconify
-.It Cm M-S-w
-uniconify
-.It Cm M-S-r
-always_raise
-.It Cm M-v
-button2
-.El
-.Pp
-I nomi delle azioni e le relative descrizioni sono le seguenti:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm term
-Lancia un nuovo terminale
-(vedi
-.Sx PROGRAMMI
-pi? in alto).
-.It Cm menu
-Menu
-(vedi
-.Sx PROGRAMMI
-pi? in alto).
-.It Cm quit
-Chiude
-.Nm .
-.It Cm restart
-Riavvia
-.Nm .
-.It Cm cycle_layout
-Cambia layout.
-.It Cm reset_layout
-Re-inizializza il layout.
-.It Cm master_shrink
-Restringe l'area principale.
-.It Cm master_grow
-Allarga l'area principale.
-.It Cm master_add
-Aggiunge finestre all'area principale.
-.It Cm master_del
-Rimuove finestre dall'area principale.
-.It Cm stack_inc
-Aggiunge righe/colonne all'area di stacking.
-.It Cm stack_del
-Rimuove righe/colonne dall'area di stacking.
-.It Cm swap_main
-Muove la finestra corrente nell'area principale.
-.It Cm focus_next
-D? il focus alla finestra successiva.
-.It Cm focus_prev
-D? il focus alla finestra precedente.
-.It Cm focus_main
-D? il focus alla finestra principale.
-.It Cm swap_next
-Scambia con la finestra successiva dell'area di lavoro.
-.It Cm swap_prev
-Scambia con la finestra precedente dell'area di lavoro.
-.It Cm bar_toggle
-Mostra/nascondi la barra di stato da tutte le aree di lavoro.
-.It Cm wind_del
-Chiude la finestra corrente.
-.It Cm wind_kill
-Distrugge la finestra corrente.
-.It Cm ws_ Ns Ar n
-Passa all'area di lavoro
-.Ar n ,
-dove
-.Ar n
-? compreso tra 1 e 10.
-.It Cm mvws_ Ns Ar n
-Sposta la finestra corrente nell'area di lavoro
-.Ar n ,
-dove
-.Ar n
-? compreso tra 1 e 10.
-.It Cm ws_next
-Passa all'area di lavoro non vuota successiva.
-.It Cm ws_prev
-Passa all'area di lavoro non vuota precedente.
-.It Cm ws_prior
-Passa all'ultima area di lavoro visitata.
-.It Cm screen_next
-Sposta il puntatore nella regione successiva.
-.It Cm screen_prev
-Sposta il puntatore nella regione precedente.
-.It Cm screenshot_all
-Cattura uno screenshot dell'intero schermo, se abilitato (vedere la sezione
-.Sx PROGRAMMI
-pi? in alto).
-.It Cm screenshot_wind
-Cattura uno screenshot di una singola finestra, se abilitato (vedere la
-sezione
-.Sx PROGRAMMI
-pi? in alto).
-.It Cm version
-Abilita/disabilita il numero di versione nella barra di stato.
-.It Cm float_toggle
-Passa la finestra che ha il focus da floating a tiled.
-.It Cm lock
-Blocca lo schermo (vedere la sezione
-.Sx PROGRAMMI
-pi? in alto).
-.It Cm initscr
-Re-inizializza gli schermi fisici (vedere la sezione
-.Sx PROGRAMMI
-pi? in alto).
-.It Cm iconify
-Minimizza (unmap) la finesta che ha il focus.
-.It Cm uniconify
-Massimizza (map) la finestra selezionata tramite dmenu.
-.It Cm always_raise
-Quando ? abilitato, le finestre floating possono essere oscurate da
-finestre tiled.
-.It Cm button2
-Simula la pressione del tasto centrale del mouse.
-.El
-.Pp
-Le scorciatoie personalizzate sono specificate nel file di configurazione
-come segue:
-.Pp
-.Dl bind[<azione>] = <tasti>
-.Pp
-.Aq azione
-? una delle azioni elencate sopra (oppure nulla) e
-.Aq tasti
-? dato da zero o pi? modificatori (MOD, Mod1, Shift, ecc.) e uno o pi?
-tasti normali (b, space, ecc.), separati da "+".
-Per esempio:
-.Bd -literal -offset indent
-bind[reset] = Mod4+q # assegna reset ai tasti Windows + q
-bind[] = Mod1+q # rimuovi l'assegnazione di Alt + q
-.Ed
-.Pp
-Pi? combinazioni di tasti possono essere assegnate alla stessa azione.
-.Sh QUIRK
-.Nm
-fornisce la possibilit? di specificare dei "quirk" per la gestione di
-finestre che devono subire un trattamento speciale da un gestore di finestre
-tiling, come ad esempio alcune finestre di dialogo e applicazioni a
-schermo intero.
-.Pp
-I quirk abilitati di default sono elencati qui sotto:
-.Pp
-.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
-.It Firefox\-bin:firefox\-bin
-TRANSSZ
-.It Firefox:Dialog
-FLOAT
-.It Gimp:gimp
-FLOAT + ANYWHERE
-.It MPlayer:xv
-FLOAT + FULLSCREEN + FOCUSPREV
-.It OpenOffice.org 2.4:VCLSalFrame
-FLOAT
-.It OpenOffice.org 3.1:VCLSalFrame
-FLOAT
-.It pcb:pcb
-FLOAT
-.It xine:Xine Window
-FLOAT + ANYWHERE
-.It xine:xine Panel
-FLOAT + ANYWHERE
-.It xine:xine Video Fullscreen Window
-FULLSCREEN + FLOAT
-.It Xitk:Xitk Combo
-FLOAT + ANYWHERE
-.It Xitk:Xine Window
-FLOAT + ANYWHERE
-.It XTerm:xterm
-XTERM_FONTADJ
-.El
-.Pp
-I quirk sono descritti qui sotto:
-.Pp
-.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
-.It FLOAT
-Questa finestra deve essere lasciata libera di muoversi (float).
-.It TRANSSZ
-Aggiusta la dimensione delle finestre troppo piccole usando dialog_ratio
-(vedere
-.Sx FILE DI CONFIGURAZIONE ) .
-.It ANYWHERE
-Consente alla finestra di decidere da sola dove posizionarsi.
-.It XTERM_FONTADJ
-Ridimensiona il font di xterm quando viene ridimensionata la finestra.
-.It FULLSCREEN
-Rimuove i bordi, consentendo alla finestra di usare l'intera dimensione
-dello schermo.
-.It FOCUSPREV
-Quando la finestra viene chiusa, d? il focus alla finestra che aveva il
-focus precedente anzich? all'applicazione precedente nello stack.
-.El
-.Pp
-I quirk personalizzati vanno specificati nel file di configurazione come
-segue:
-.Pp
-.Dl quirk[<classe>:<nome>] = <quirk> [ + <quirk> ... ]
-.Pp
-.Aq classe
-e
-.Aq nome
-specificano a quali finestre i quirk vanno applicati, e
-.Aq quirk
-? uno dei quirk presente nella lista sopra.
-Ad esempio:
-.Bd -literal -offset indent
-quirk[MPlayer:xv] = FLOAT + FULLSCREEN + FOCUSPREV
-quirk[pcb:pcb] = NONE  # rimuovi un quirk precedentemente specificato
-.Ed
-.Pp
-? possibile ottenere
-.Aq classe
-e
-.Aq nome
-usando xprop(1) e facendo click sulla finestra desiderata.
-Nel seguente esempio ? stato fatto click sulla finestra principale di
-Firefox:
-.Bd -literal -offset indent
-$ xprop | grep WM_CLASS
-WM_CLASS(STRING) = "Navigator", "Firefox"
-.Ed
-.Pp
-Bisogna tenere conto del fatto che usare grep per trovare WM_CLASS inverte
-la classe e il nome. Nell'esempio precedente, la dichiarazione del quirk
-sarebbe
-.Bd -literal -offset indent
-quirk[Firefox:Navigator] = FLOAT
-.Ed
-.Pp
-.Nm
-assegna automaticamente i quirk alle finestre in base al valore della
-propriet? _NET_WM_WINDOW_TYPE in base al seguente schema:
-.Pp
-.Bl -tag -width "_NET_WM_WINDOW_TYPE_TOOLBAR<TAB>XXX" -offset indent -compact
-.It _NET_WM_WINDOW_TYPE_DOCK
-FLOAT + ANYWHERE
-.It _NET_WM_WINDOW_TYPE_TOOLBAR
-FLOAT + ANYWHERE
-.It _NET_WM_WINDOW_TYPE_UTILITY
-FLOAT + ANYWHERE
-.It _NET_WM_WINDOW_TYPE_SPLASH
-FLOAT
-.It _NET_WM_WINDOW_TYPE_DIALOG
-FLOAT
-.El
-.Pp
-In tutti gli altri casi, nessun quirk ? automaticamente assegnato alla
-finestra. I quirk specificati nel file di configurazione hanno la precedenza
-sui quirk assegnati in automatico.
-.Sh EWMH
-.Nm
-implementa in maniera parziale la specifica Extended Window Manager Hints
-(EWMH). Ci? permette di controllare sia le finestre che
-.Nm
-stesso tramite script e programmi esterni. Per renderlo possibile,
-.Nm
-risponde ad alcuni eventi di tipo ClientMessage; questo tipo di messaggio
-pu? essere inviato da un terminale usando programmi come
-.Xr wmctrl 1
-e
-.Xr xdotool 1 .
-Per il formato esatto di questi messaggi, si veda la specifica EWMH.
-.Pp
-L'id della finestra che ha il focus ? memorizzato nella propriet?
-_NET_ACTIVE_WINDOW della root window. ? quindi possibile ottenere il titolo
-della finestra attiva usando
-.Xr xprop 1
-e
-.Xr grep 1
-.Bd -literal -offset indent
-$ WINDOWID=`xprop \-root _NET_ACTIVE_WINDOW | grep \-o "0x.*"`
-$ xprop \-id $WINDOWID WM_NAME | grep \-o "\\".*\\""
-.Ed
-.Pp
-Per dare il focus ad una finestra, ? sufficiente inviare il messaggio
-_NET_ACTIVE_WINDOW alla root window. Ad esempio, usando
-.Xr wmctrl 1
-(supponendo che 0x4a0000b sia l'id della finestra a cui dare il focus):
-.Bd -literal -offset indent
-$ wmctrl \-i \-c 0x4a0000b
-.Ed
-.Pp
-Per chiudere una finestra si pu? inviare il messaggio _NET_CLOSE_WINDOW
-alla root window. Ad esempio, usando
-.Xr wmctrl 1
-(supponendo che 0x4a0000b sia l'id della finestra da chiudere):
-.Bd -literal -offset indent
-$ wmctrl \-i \-c 0x4a0000b
-.Ed
-.Pp
-Per passare una finestra da floating a tiled si pu? aggiungere o rimuovere
-l'atomo _NET_WM_STATE_ABOVE alla propriet? _NET_WM_STATE della finestra,
-inviando il messaggio _NET_WM_STATE alla root window. Ad esempio, usando
-.Xr wmctrl 1
-(supponendo che 0x4a0000b sia l'id della finestra):
-.Bd -literal -offset indent
-$ wmctrl \-i \-r 0x4a0000b \-b toggle,_NET_WM_STATE_ABOVE
-.Ed
-.Pp
-Le finestre floating possono essere ridimensionate o spostate inviando il
-messaggio _NET_MOVERESIZE_WINDOW alla root window. Ad esempio, usando
-.Xr wmctrl 1
-(supponendo che 0x4a0000b sia l'id della finestra da spostare):
-.Bd -literal -offset indent
-$ wmctrl \-i \-r 0x4a0000b \-e 0,100,50,640,480
-.Ed
-.Pp
-Questo comando sposta la finestra in (100,50) e la ridimensiona a 640x480.
-.Pp
-I messaggi _NET_MOVERESIZE_WINDOW vengono ignorati per le finestre stacked.
-.Sh SEGNALI
-? possibile riavviare
-.Nm
-inviandogli il segnale HUP.
-.Sh FILE
-.Bl -tag -width "/etc/scrotwm.confXXX" -compact
-.It Pa ~/.scrotwm.conf
-impostazioni di
-.Nm
-dell'utente.
-.It Pa /etc/scrotwm.conf
-impostazioni globali di
-.Nm .
-.El
-.Sh ORIGINE
-.Nm
-prende ispirazione da xmonad & dwm.
-.Sh AUTORI
-.An -nosplit
-.Pp
-.Nm
-? stato scritto da:
-.Pp
-.Bl -tag -width "Ryan Thomas McBride Aq mcbride@countersiege.com " -offset indent -compact
-.It Cm Marco Peereboom Aq marco@peereboom.us
-.It Cm Ryan Thomas McBride Aq mcbride@countersiege.com
-.It Cm Darrin Chandler Aq dwchandler@stilyagin.com
-.It Cm Pierre-Yves Ritschard Aq pyr@spootnik.org
-.It Cm Tuukka Kataja Aq stuge@xor.fi
-.It Cm Jason L. Wright Aq jason@thought.net
-.El
-.Sh BUGS
-Al momento il menu, invocato usando
-.Cm M-p ,
-dipende da dmenu.
diff --git a/scrotwm_pt.1 b/scrotwm_pt.1
deleted file mode 100644 (file)
index 4534ade..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
-.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate$
-.Dt SCROTWM 1
-.Os
-.Sh NOME
-.Nm scrotwm
-.Nd gerenciador de janela para o X11
-.Sh SINOPSE
-.Nm scrotwm
-.Sh DESCRI\(,C\(~AO
-.Nm
-\('e um gerenciador de janela minimalista que tenta n\(~ao atrapalhar a
-valorosa forma real da tela para que essa possa
-ser usada para coisas muito mais importantes.
-Tem sensatos defaults e n\(~ao requer que algu\('em aprenda uma linguagem de
-programa\(,c\(~ao para fazer qualquer configura\(,c\(~ao.
-Ele foi escrito por hackers para hackers e esfor\(,ca-se em ser pequeno, compacto e 
-r\('apido.
-.Pp
-Quando o
-.Nm
-inicia, ele l\(^e as configura\(,c\(~oes do seu arquivo de configura\(,c\(~ao,
-.Pa scrotwm.conf .
-Veja a se\(,c\(~ao
-.Sx ARQUIVOS DE CONFIGURA\(,C\(~AO
-logo abaixo.
-.Pp
-A seguinte nota\(,c\(~ao \('e usada por toda essa p\('agina:
-.Pp
-.Bl -tag -width Ds -offset indent -compact
-.It Cm M
-Meta
-.It Cm S
-Shift
-.It Aq Cm Name
-Nome da tecla
-.It Cm M1
-Bot\(~ao 1 do mouse
-.It Cm M3
-Bot\(~ao 3 do mouse
-.El
-.Pp
-.Nm
-\('e muito simples de usar.
-Muitas das a\(,c\(~oes s\(~ao iniciadas por atalhos do mouse ou do teclado.
-Veja a se\(,c\(~ao
-.Sx ATALHOS
-logo abaixo para os defaults e as personaliza\(,c\(~oes.
-.Sh ARQUIVOS DE CONFIGURA\(,C\(~AO
-.Nm
-primeiro tenta abrir o arquivo de configura\(,c\(~ao no diret\('orio do usu\('ario,
-.Pa ~/.scrotwm.conf .
-Se o arquivo n\(~ao estiver dispon\('ivel, ent\(~ao tenta abrir o arquivo de
-configura\(,c\(~ao global
-.Pa /etc/scrotwm.conf .
-.Pp
-Assim \('e o formato do arquivo:\*(Ltpalavra-chave\*(Gt = \*(Ltconfigura\(,c\(~ao\*(Gt.
-Por exemplo:
-.Pp
-.Dl color_focus = red
-.Pp
-Para habilitar ou desabilitar uma op\(,c\(~ao usa-se o 1 ou 0, respectivamente. 
-.Pp
-O arquivo suporta as seguintes palavras-chave:
-.Pp
-.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
-.It Cm color_focus
-Cor da borda da janela atualmente focada.
-.It Cm color_unfocus
-Cor da borda das janelas fora de foco.
-.It Cm bar_enabled
-Habilita ou desabilita a barra de status.
-.It Cm bar_border Ns Bq Ar x
-Cor da borda da barra de status na tela
-.Ar x .
-.It Cm bar_color Ns Bq Ar x
-Cor da janela da barra de status na tela
-.Ar x .
-.It Cm bar_font_color Ns Bq Ar x
-Cor da fonte na barra de status na tela
-.Ar x .
-.It Cm bar_font
-Fonte da barra de status.
-.It Cm bar_action
-Script externo que preenche a barra de status com informa\(,c\(~oes adicionais,
-como tempo de vida da bateria.
-.It Cm bar_delay
-Freq\(:u\(^encia da atualiza\(,c\(~ao, em segundos, do script externo que preenche
-a barra de status.
-.It Cm bar_at_bottom
-Coloca a barra de status na parte inferior de cada regi\(~ao, ao inv\('es da parte superior.
-.It Cm stack_enabled
-Habilita ou desabilita mostrar o atual algor\('itmo de empilhamento na barra de status.
-.It Cm clock_enabled
-Habilita ou desabilita mostrar o rel\('ogio na barra de status.
-Desabilite configurando para 0, ent\(~ao um rel\('ogio personalizado pode ser usado no
-script bar_action.
-.It Cm dialog_ratio
-Algumas aplica\(,c\(~oes tem janelas de di\('alogo que s\(~ao muito pequenas para serem \('uteis.
-Essa taxa \('e o tamanho da tela para o qual elas ser\(~ao redimencionadas.
-Por exemplo, 0.6 equivale a 60% do tamanho da tela f\('isica.
-.It Cm region
-Aloca uma regi\(~ao personalizada, removendo qualquer regi\(~ao automaticamente detectada
-que ocupe o mesmo espa\(,co na tela.
-Definido no formato screen[<idx>]:WIDTHxHEIGHT+X+Y,
-e.g.\& screen[1]:800x1200+0+0.
-.It Cm term_width
-Configura a largura m\('inima preferida para o terminal
-Se esse valor for maior do que 0,
-.Nm
-vai tentar ajustar os tamanhos da fonte no terminal para manter a largura
-do terminal acima desse n\('umero enquanto a janela \('e redimencionada.
-Apenas o
-.Xr xterm 1
-\('e suportado atualmente.
-O bin\('ario do
-.Xr xterm 1
-n\(~ao deve ser setuid ou setgid, que \('e o default em muitos sistemas.
-Os usu\('arios podem precisar de configurar program[term] (veja a se\(,c\(~ao
-.Sx PROGRAMAS
-) para usar uma c\('opia alternativa do bin\('ario do
-.Xr xterm 1
-sem o bit setgid ativado.
-.It Cm title_class_enabled
-Habilita ou desabilita mostrar a classe da janela na barra de status.
-Habilite configurando para 1.
-.It Cm title_name_enabled
-Habilita ou desabilita mostrar o t\('itulo da janela na barra de status.
-Habilite configurando para 1.
-.It Cm window_name_enabled
-Habilita ou desabilita mostrar a nome da janela na barra de status.
-Habilite configurando para 1.
-.It Cm modkey
-Muda a tecla de modifica\(,c\(~ao.
-Mod1 \('e geralmente a tecla ALT e Mod4 \('e a tecla windows em um PC.
-.It Cm focus_mode
-Usar um valor de follow_cursor vai fazer o gerenciador de janela focar
-a janela sob o mouse quando trocando \('areas de trabalho e criando janelas.
-.It Cm disable_border
-Remove a borda quando a barra estiver desabilitada e houver apenas uma janela na tela.
-.It Cm program Ns Bq Ar p
-Define uma nova a\(,c\(~ao para executar um programa
-.Ar p .
-Veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo abaixo.
-.It Cm bind Ns Bq Ar x
-Cria uma combina\(,c\(~ao de teclas de atalho para a a\(,c\(~ao
-.Ar x .
-Veja a se\(,c\(~ao 
-.Sx ATALHOS
-logo abaixo.
-.It Cm quirk Ns Bq Ar c:n
-Adicione "quirk" para janelas com classe
-.Ar c
-e nome
-.Ar n .
-Veja a se\(,c\(~ao
-.Sx QUIRKS
-logo abaixo.
-.El
-.Pp
-Cores precisam ser especificadas pela especifica\(,c\(~ao
-.Xr XQueryColor 3
-e fontes pela especifica\(,c\(~ao
-.Xr XQueryFont 3 .
-.Pp
-Para listar as fontes dispon\('iveis em seu sistema veja o manual do
-.Xr fc-list 1
-ou do
-.Xr xlsfonts 1 .
-A aplica\(,c\(~ao 
-.Xr xfontsel 1
-pode te ajudar a mostrar a X Logical Font Description ("XLFD") usada na
-configura\(,c\(~ao da palavra-chave bar_font.
-.Sh PROGRAMAS
-.Nm
-te permite definir a\(,c\(~oes personalizadas para executar programas de sua escolha
-e ent\(~ao criar um atalho para elas da mesma forma que as a\(,c\(~oes embutidas.
-Veja a se\(,c\(~ao
-.Sx ATALHOS
-logo abaixo.
-.Pp
-Os programas default s\(~ao descritos abaixo:
-.Pp
-.Bl -tag -width "screenshot_wind" -offset indent -compact
-.It Cm term
-xterm
-.It Cm screenshot_all
-screenshot.sh full
-.It Cm screenshot_wind
-screenshot.sh window
-.It Cm lock
-xlock
-.It Cm initscr
-initscreen.sh
-.It Cm menu
-dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
-.El
-.Pp
-Programas personalizados no arquivo de configura\(,c\(~ao s\(~ao especificados da seguinte maneira:
-.Pp
-.Dl program[<name>] = <progpath> [<arg> [... <arg>]]
-.Pp
-.Aq name
-\('e um identificador qualquer que n\(~ao conflite com uma a\(,c\(~ao ou palavra-chave embutida,
-.Aq progpath
-\('e o programa desejado, e
-.Aq arg
-\('e zero ou mais argumentos para o programa.
-.Pp
-As seguintes vari\('aveis representam valores configur\('aveis no
-.Nm
-(veja a se\(,c\(~ao
-.Sx ARQUIVOS DE CONFIGURA\(,C\(~AO
-logo acima),
-e podem ser usadas nos campos
-.Aq arg
-e ser\(~ao substitu\('idas pelos valores na hora em que o programa for executado:
-.Pp
-.Bl -tag -width "$bar_font_color" -offset indent -compact
-.It Cm $bar_border
-.It Cm $bar_color
-.It Cm $bar_font
-.It Cm $bar_font_color
-.It Cm $color_focus
-.It Cm $color_unfocus
-.El
-.Pp
-Exemplo:
-.Bd -literal -offset indent
-program[ff] = /usr/local/bin/firefox http://scrotwm.org/
-bind[ff] = Mod+f # Agora Mod+F executa o firefox
-.Ed
-.Pp
-Para desfazer a configura\(,c\(~ao anterior:
-.Bd -literal -offset indent
-bind[] = Mod+f
-program[ff] =
-.Ed
-.Pp
-.Sh ATALHOS
-.Nm
-prov\(^e muitas fun\(,c\(~oes (ou a\(,cões) acessadas pelos atalhos do teclado ou do mouse.
-.Pp
-Os atuais atalhos do mouse s\(~ao descritos abaixo:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M1
-Foca a janela
-.It Cm M-M1
-Move a janela
-.It Cm M-M3
-Redimenciona a janela
-.It Cm M-S-M3
-Redimenciona a janela enquanto a mant\('em centralizada
-.El
-.Pp
-Os atalhos default do teclado s\(~ao descritos abaixo:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M-S- Ns Aq Cm Return
-term
-.It Cm M-p
-menu
-.It Cm M-S-q
-quit
-.It Cm M-q
-restart
-.Nm
-.It Cm M- Ns Aq Cm Space
-cycle_layout
-.It Cm M-S- Ns Aq Cm Space
-reset_layout
-.It Cm M-h
-master_shrink
-.It Cm M-l
-master_grow
-.It Cm M-,
-master_add
-.It Cm M-.
-master_del
-.It Cm M-S-,
-stack_inc
-.It Cm M-S-.
-stack_del
-.It Cm M- Ns Aq Cm Return
-swap_main
-.It Xo
-.Cm M-j ,
-.Cm M- Ns Aq Cm TAB
-.Xc
-focus_next
-.It Xo
-.Cm M-k ,
-.Cm M-S- Ns Aq Cm TAB
-.Xc
-focus_prev
-.It Cm M-m
-focus_main
-.It Cm M-S-j
-swap_next
-.It Cm M-S-k
-swap_prev
-.It Cm M-b
-bar_toggle
-.It Cm M-x
-wind_del
-.It Cm M-S-x
-wind_kill
-.It Cm M- Ns Aq Ar n
-.Ns ws_ Ns Ar n
-.It Cm M-S- Ns Aq Ar n
-.Ns mvws_ Ns Ar n
-.It Cm M- Ns Aq Cm Right
-ws_next
-.It Cm M- Ns Aq Cm Left
-ws_prev
-.It Cm M-a
-ws_prior
-.It Cm M-S- Ns Aq Cm Right
-screen_next
-.It Cm M-S- Ns Aq Cm Left
-screen_prev
-.It Cm M-s
-screenshot_all
-.It Cm M-S-s
-screenshot_wind
-.It Cm M-S-v
-version
-.It Cm M-t
-float_toggle
-.It Cm M-S Aq Cm Delete
-lock
-.It Cm M-S-i
-initscr
-.El
-.Pp
-Os nomes das a\(,c\(~oes e suas descri\(,cões est\(~ao listados abaixo:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm term
-Executa um novo terminal
-(veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo acima)
-.It Cm menu
-Menu
-(veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo acima)
-.It Cm quit
-Sair
-.Nm
-.It Cm restart
-Reiniciar
-.Nm
-.It Cm cycle_layout
-Circula entre os poss\('iveis layouts
-.It Cm reset_layout
-Reinicia o layout
-.It Cm master_shrink
-Encolhe a \('area mestre
-.It Cm master_grow
-Aumenta a \('area mestre
-.It Cm master_add
-Adiciona janelas na \('area mestre
-.It Cm master_del
-Remove janelas da \('area mestre
-.It Cm stack_inc
-Adiciona colunas/linhas para a \('area de empilhamento
-.It Cm stack_del
-Remove colunas/linhas da \('area de empilhamento
-.It Cm swap_main
-Move a janela atual para a \('area mestre
-.It Cm focus_next
-Foca a pr\('oxima janela da \('area de trabalho
-.It Cm focus_prev
-Foca a janela anterior da \('area de trabalho
-.It Cm focus_main
-Foca a janela principal da \('area de trabalho
-.It Cm swap_next
-Troca com a pr\('oxima janela da \('area de trabalho
-.It Cm swap_prev
-Troca com a janela anterior da \('area de trabalho
-.It Cm bar_toggle
-Ativa/desativa a barra de status em todas as \('areas de trabalho
-.It Cm wind_del
-Apaga a janela atual da \('area de trabalho
-.It Cm wind_kill
-Destr\('oi a janela atual da \('area de trabalho
-.It Cm ws_ Ns Ar n
-Troca para a \('area de trabalho
-.Ar n ,
-onde
-.Ar n
-vai de 1 at\('e 10
-.It Cm mvws_ Ns Ar n
-Move a janela atual para a \('area de trabalho
-.Ar n ,
-onde
-.Ar n
-vai de 1 at\('e 10
-.It Cm ws_next
-Troca para a pr\('oxima \('area de trabalho que possua uma janela
-.It Cm ws_prev
-Troca para a \('area de trabalho anterior que possua uma janela
-.It Cm ws_prior
-Troca para a \('ultima \('area de trabalho visitada
-.It Cm screen_next
-Move o ponteiro para a pr\('oxima regi\(~ao
-.It Cm screen_prev
-Move o ponteiro para a regi\(~ao anterior
-.It Cm screenshot_all
-Tira screenshot da tela inteira (se habilitado)
-(veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo acima)
-.It Cm screenshot_wind
-Tira screenshot da janela selecionada (se habilitado)
-(veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo acima)
-.It Cm version
-Ativa/desativa a vers\(~ao na barras de status
-.It Cm float_toggle
-Troca o estado da janela focada entre flutuante e tiled
-.It Cm lock
-Trava a tela
-(veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo acima)
-.It Cm initscr
-Reinicializa as telas f\('isicas
-(veja a se\(,c\(~ao
-.Sx PROGRAMAS
-logo acima)
-.El
-.Pp
-Atalhos personalizados no arquivo de configura\(,c\(~ao s\(~ao especificados da seguinte maneira:
-.Pp
-.Dl bind[<action>] = <keys>
-.Pp
-.Aq action
-\('e uma das a\(,c\(~oes listadas acima (ou vazio) e
-.Aq keys
-est\('a na forma de zero ou mais teclas de modifica\(,c\(~ao
-(MOD, Mod1, Shift, etc.) e uma ou mais teclas normais
-(b, space, etc.), separadas pelo "+".
-Por exemplo:
-.Bd -literal -offset indent
-bind[reset] = Mod4+q # combina a tecla Windows + q para reiniciar
-bind[] = Mod1+q # desfaz a combina\(,c\(~ao Alt + q
-.Ed
-.Pp
-M\('ultiplas combina\(,c\(~oes de teclas podem ser usadas para a mesma a\(,c\(~ao.
-.Sh QUIRKS
-.Nm
-prov\(^e "quirks" que manipulam janelas que devem ser tratadas especialmente
-em um gerenciador de janela "tiling", tal como algumas aplica\(,c\(~oes de
-di\('alogos e tela cheia.
-.Pp
-Os quirks default est\(~ao descritos abaixo:
-.Pp
-.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
-.It Firefox\-bin:firefox\-bin
-TRANSSZ
-.It Firefox:Dialog
-FLOAT
-.It Gimp:gimp
-FLOAT + ANYWHERE
-.It MPlayer:xv
-FLOAT + FULLSCREEN
-.It OpenOffice.org 2.4:VCLSalFrame
-FLOAT
-.It OpenOffice.org 3.1:VCLSalFrame
-FLOAT
-.It pcb:pcb
-FLOAT
-.It xine:Xine Window
-FLOAT + ANYWHERE
-.It xine:xine Panel
-FLOAT + ANYWHERE
-.It xine:xine Video Fullscreen Window
-FULLSCREEN + FLOAT
-.It Xitk:Xitk Combo
-FLOAT + ANYWHERE
-.It Xitk:Xine Window
-FLOAT + ANYWHERE
-.It XTerm:xterm
-XTERM_FONTADJ
-.El
-.Pp
-Os quirks em si est\(~ao descritos abaixo:
-.Pp
-.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
-.It FLOAT
-Esta janela n\(~ao deve ser "tiled", mas permitida a flutuar livremente.
-.It TRANSSZ
-Ajusta o tamanho das janelas transit\('orias que sejam muito pequenas
-usando dialog_ratio 
-(veja a se\(,c\(~ao
-.Sx ARQUIVOS DE CONFIGURA\(,C\(~AO ) .
-.It ANYWHERE
-Permite que a janela posicione a si mesma, n\(~ao-centrada.
-.It XTERM_FONTADJ
-Ajusta as fontes do xterm quando redimencionando.
-.It FULLSCREEN
-Remove a borda para permitir a janela usar todo o tamanho da tela.
-.El
-.Pp
-Quirks personalizados no arquivo de configura\(,c\(~ao s\(~ao especificados da seguinte maneira:
-.Pp
-.Dl quirk[<class>:<name>] = <quirk> [ + <quirk> ... ]
-.Pp
-.Aq class
-e
-.Aq name
-especificam a janela ao qual o quirk se aplica, e
-.Aq quirk
-\('e um dos quirks da lista acima.
-Por exemplo:
-.Bd -literal -offset indent
-quirk[MPlayer:xv] = FLOAT + FULLSCREEN # faz o mplayer tocar livremente
-quirk[pcb:pcb] = NONE  # remove quirk existente
-.Ed
-.Pp
-Voc\(^e pode obter
-.Aq class
-e
-.Aq name
-executando o xprop(1) e ent\(~ao clicando na janela desejada.
-No seguinte exemplo a jenela principal do Firefox foi clicada:
-.Bd -literal -offset indent
-$ xprop | grep WM_CLASS
-WM_CLASS(STRING) = "Navigator", "Firefox"
-.Ed
-.Pp
-Note que usando o grep(1) para WM_CLASS voc\(^e obt\('em class e name. 
-No exemplo acima a configura\(,c\(~ao do quirk poderia ser:
-.Bd -literal -offset indent
-quirk[Firefox:Navigator] = FLOAT
-.Ed
-.Sh SINAIS
-Enviar ao
-.Nm
-um sinal HUP far\('a com que o mesmo seja reiniciado.
-.Sh ARQUIVOS
-.Bl -tag -width "/etc/scrotwm.confXXX" -compact
-.It Pa ~/.scrotwm.conf
-Configura\(,c\(~oes espec\('ificas do usu\('ario.
-.It Pa /etc/scrotwm.conf
-Configura\(,c\(~oes globais.
-.El
-.Sh HIST\('ORIA
-.Nm
-foi inspirado pelo xmonad & dwm.
-.Sh AUTORES
-.An -nosplit
-.Pp
-.Nm
-foi escrito por
-.An Marco Peereboom Aq marco@peereboom.us ,
-.An Ryan Thomas McBride Aq mcbride@countersiege.com
-e
-.An Darrin Chandler Aq dwchandler@stilyagin.com .
-.Sh BUGS
-Atualmente o menu, invocado com
-.Cm M-p ,
-depende do dmenu.
diff --git a/scrotwm_ru.1 b/scrotwm_ru.1
deleted file mode 100644 (file)
index 5925ff6..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
-.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate$
-.Dt SCROTWM 1
-.Os
-.Sh НАЗВАНИЕ
-.Nm scrotwm
-.Nd Оконный менеджер для X11
-.Sh ИСПОЛЬЗОВАНИЕ
-.Nm scrotwm
-.Sh ОПИСАНИЕ
-.Nm
-это минималистичный менеджер окон, ставящий своей целью не мешать вам и не
-занимать ценное пространство экрана. Его настройки по-умолчанию разумны и,
-кроме того, он не требует знания языков программирования для работы с
-конфигурационным файлом. Он написан хакерами для хакеров и старается быть
-легким, компактным и быстрым.
-.Pp
-Когда
-.Nm
-запускается, он читает настройки из своего конфигурационного файла,
-.Pa scrotwm.conf .
-Смотрите секцию
-.Sx КОНФИГУРАЦИОННЫЕ ФАЙЛЫ
-ниже.
-.Pp
-На этой странице используются следующие обозначения:
-.Pp
-.Bl -tag -width Ds -offset indent -compact
-.It Cm M
-Мета-клавиша
-.It Cm S
-Shift
-.It Aq Cm Name
-Имя клавиши
-.It Cm M1
-Кнопка мыши 1
-.It Cm M3
-Кнопка мыши 3
-.El
-.Pp
-.Nm
-должен быть понятным и очевидным.
-Большинство действий выполняется комбинациями клавиш.
-Смотрите секцию
-.Sx ПРИВЯЗКИ
-ниже, чтобы узнать о стандартных настройках.
-.Sh КОНФИГУРАЦИОННЫЕ ФАЙЛЫ
-.Nm
-пытается прочитать файл в домашнем каталоге,
-.Pa ~/.scrotwm.conf .
-В случае, если он недоступен,
-происходит обращение к глобальному файлу настроек,
-.Pa /etc/scrotwm.conf .
-.Pp
-Формат файла следующий: \*(Ltключ\*(Gt = \*(Ltзначение\*(Gt.
-Например:
-.Pp
-.Dl color_focus = red
-.Pp
-Однозначное включение и выключение задается значениями 1 и 0.
-.Pp
-Поддерживаются следующие ключевые слова:
-.Pp
-.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
-.It Cm color_focus
-Цвет рамки окна в фокусе.
-.It Cm color_unfocus
-Цвет рамки окон не в фокусе.
-.It Cm bar_enabled
-Включение статусной строки.
-.It Cm bar_border Ns Bq Ar x
-Цвет рамки статусной строки
-.Ar x .
-.It Cm bar_color Ns Bq Ar x
-Цвет статусной строки
-.Ar x .
-.It Cm bar_font_color Ns Bq Ar x
-Цвет шрифта статусной строки
-.Ar x .
-.It Cm bar_font
-Тип шрифта статусной строки.
-.It Cm bar_action
-Внешний файл скрипта для статусной строки, выводящий туда информацию,
-например, уровень заряда батарей.
-.It Cm bar_delay
-Частота выполнения внешнего скрипта статусной строки, секунды.
-.It Cm stack_enabled
-Включить отображение способа укладки окон в статусной строке.
-.It Cm clock_enabled
-Включить часы в статусной строке.
-Можно отключить, установив 0, и Вы сможете использовать
-собственные часы из внешнего скрипта.
-.It Cm dialog_ratio
-Ряд приложений имеет слишком маленькие диалоговые окна.
-Это значение - доля размера экрана, к которой они будут приведены.
-Например, значение 0.6 будет соответствовать 60% от реального размера экрана.
-.It Cm region
-Выделяет область экрана на Ваше усмотрение, уничтожает все перекрытые области
-экрана, определенные автоматически.
-Формат: screen[<idx>]:WIDTHxHEIGHT+X+Y,
-например\& screen[1]:1280x800+0+0.
-.It Cm term_width
-Установить минимальную допустимую ширину эмулятора терминала.
-Если это значение больше 0,
-.Nm
-попытается отмасштабировать шрифты в терминале, чтобы ширина
-была больше этого значения
-.
-Поодерживается только
-.Xr xterm 1
-.
-Также
-.Xr xterm 1
-не может быть с setuid или setgid, хотя это так на многих системах.
-Возможно необходимо задать program[term] (Смотрите секцию
-.Sx ПРОГРАММЫ
-) чтобы использовалась другая копия
-.Xr xterm 1
-без заданного бита setgid.
-.It Cm title_class_enabled
-Отображать класс окна в статусной строке.
-Обычно выключено
-.It Cm title_name_enabled
-Отображать заголовок окна в статусной строке.
-Обычно выключено
-.It Cm modkey
-Назначить Мета-клавишу, клавишу-модификатор.
-Mod1 соответствует клавише ALT, а Mod4 соответствует клавише WIN на PC.
-.It Cm program Ns Bq Ar p
-Добавить пользовательскую программу для назначения привязки
-.Ar p .
-Смотрите секцию
-.Sx ПРОГРАММЫ
-ниже.
-.It Cm bind Ns Bq Ar x
-Назначить привязку на действие
-.Ar x .
-Смотрите секцию
-.Sx ПРИВЯЗКИ
-ниже.
-.It Cm quirk Ns Bq Ar c:n
-Добавить костыль для окон с классом
-.Ar c
-и именем
-.Ar n .
-Смотрите секцию
-.Sx КОСТЫЛИ
-ниже.
-.El
-.Pp
-Цвета задаются с помощью
-.Xr XQueryColor 3
-А шрифты задаются с использованием
-.Xr XQueryFont 3
-.
-.Sh ПРОГРАММЫ
-.Nm
-позволяет Вам добавлять Ваши собственные действия для запуска
-программ и делать к ним привязки как ко всем остальным действиям
-Смотрите секцию
-.Sx ПРИВЯЗКИ
-ниже.
-.Pp
-Стандартные программы:
-.Pp
-.Bl -tag -width "screenshot_wind" -offset indent -compact
-.It Cm term
-xterm
-.It Cm screenshot_all
-screenshot.sh full
-.It Cm screenshot_wind
-screenshot.sh window
-.It Cm lock
-xlock
-.It Cm initscr
-initscreen.sh
-.It Cm menu
-dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
-.El
-.Pp
-Ваши собственные программы задаются следующим образом:
-.Pp
-.Dl program[<name>] = <progpath> [<arg> [... <arg>]]
-.Pp
-.Aq name
-это любой идентификатор, не мешающийся с уже существующими,
-.Aq progpath
-это собственно путь к программе,
-.Aq arg
-это список передаваемых аргументов или оставьте пустым.
-.Pp
-Следующие переменные можно получать из
-.Nm
-(Смотрите секцию
-.Sx КОНФИГУРАЦИОННЫЕ ФАЙЛЫ
-выше),
-и их можно использовать как
-.Aq arg
-(в момент запуска программы будет выполнена подстановка значений):
-.Pp
-.Bl -tag -width "$bar_font_color" -offset indent -compact
-.It Cm $bar_border
-.It Cm $bar_color
-.It Cm $bar_font
-.It Cm $bar_font_color
-.It Cm $color_focus
-.It Cm $color_unfocus
-.El
-.Pp
-Например:
-.Bd -literal -offset indent
-program[ff] = /usr/local/bin/firefox http://scrotwm.org/
-bind[ff] = Mod+f # Значит Mod+F запускает firefox
-.Ed
-.Pp
-Чтобы отменить назначение:
-.Bd -literal -offset indent
-bind[] = Mod+f
-program[ff] =
-.Ed
-.Pp
-.Sh ПРИВЯЗКИ
-.Nm
-предоставляет доступ к действиям с помощью клавиатурных комбинаций.
-.Pp
-Установленные привязки для мыши:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M1
-Сфокусироваться на окне
-.It Cm M-M1
-Переместить окно
-.It Cm M-M3
-Изменить размер окна
-.It Cm M-S-M3
-Изменить размер окна, удерживая его в центре
-.El
-.Pp
-Стандартные клавиатурные привязки:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm M-S- Ns Aq Cm Return
-term
-.It Cm M-p
-menu
-.It Cm M-S-q
-quit
-.It Cm M-q
-restart
-.Nm
-.It Cm M- Ns Aq Cm Space
-cycle_layout
-.It Cm M-S- Ns Aq Cm Space
-reset_layout
-.It Cm M-h
-master_shrink
-.It Cm M-l
-master_grow
-.It Cm M-,
-master_add
-.It Cm M-.
-master_del
-.It Cm M-S-,
-stack_inc
-.It Cm M-S-.
-stack_del
-.It Cm M- Ns Aq Cm Return
-swap_main
-.It Xo
-.Cm M-j ,
-.Cm M- Ns Aq Cm TAB
-.Xc
-focus_next
-.It Xo
-.Cm M-k ,
-.Cm M-S- Ns Aq Cm TAB
-.Xc
-focus_prev
-.It Cm M-m
-focus_main
-.It Cm M-S-j
-swap_next
-.It Cm M-S-k
-swap_prev
-.It Cm M-b
-bar_toggle
-.It Cm M-x
-wind_del
-.It Cm M-S-x
-wind_kill
-.It Cm M- Ns Aq Ar n
-.Ns ws_ Ns Ar n
-.It Cm M-S- Ns Aq Ar n
-.Ns mvws_ Ns Ar n
-.It Cm M- Ns Aq Cm Right
-ws_next
-.It Cm M- Ns Aq Cm Left
-ws_prev
-.It Cm M-S- Ns Aq Cm Right
-screen_next
-.It Cm M-S- Ns Aq Cm Left
-screen_prev
-.It Cm M-s
-screenshot_all
-.It Cm M-S-s
-screenshot_wind
-.It Cm M-S-v
-version
-.It Cm M-t
-float_toggle
-.It Cm M-S Aq Cm Delete
-lock
-.It Cm M-S-i
-initscr
-.El
-.Pp
-Описания действий перечислены ниже:
-.Pp
-.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
-.It Cm term
-Запустить эмулятор терминала
-(Смотрите секцию
-.Sx ПРОГРАММЫ
-выше)
-.It Cm menu
-Меню
-(Смотрите секцию
-.Sx ПРОГРАММЫ
-выше)
-.It Cm quit
-Выйти
-.Nm
-.It Cm restart
-Перезапустить
-.Nm
-.It Cm cycle_layout
-Менять укладку окон
-.It Cm reset_layout
-Стандартная укладка
-.It Cm master_shrink
-Сжать область главного окна
-.It Cm master_grow
-Расширить область главного окна
-.It Cm master_add
-Добавить окна в главную область
-.It Cm master_del
-Убрать окна из главной области
-.It Cm stack_inc
-Увеличить число столбцов или рядов в текущей укладке
-.It Cm stack_del
-Уменьшить число столбцов или рядов в текущей укладке
-.It Cm swap_main
-Отправить текущее окно в главную область, сделать главным
-.It Cm focus_next
-Фокусироваться на следующем окне
-.It Cm focus_prev
-Фокусироваться на предыдущем окне
-.It Cm focus_main
-Фокусироваться на главном окне
-.It Cm swap_next
-Поменять со следующим окном
-.It Cm swap_prev
-Поменять со предыдущим окном
-.It Cm bar_toggle
-Выключить статусную строку на всех рабочих столах
-.It Cm wind_del
-Закрыть фокусированное окно
-.It Cm wind_kill
-Грохнуть фокусированное окно
-.It Cm ws_ Ns Ar n
-Переключиться на рабочий стол
-.Ar n ,
-где
-.Ar n
-от 1 до 10
-.It Cm mvws_ Ns Ar n
-Переместить фокусированное окно в рабочий стол
-.Ar n ,
-где
-.Ar n
-от 1 до 10
-.It Cm ws_next
-Перейти к следующему не пустому рабочему столу
-.It Cm ws_prev
-Перейти к следующему не пустому рабочему столу
-.It Cm screen_next
-Переместить указатель в следующую область
-.It Cm screen_prev
-Переместить указатель в следующую область
-.It Cm screenshot_all
-Сделать снимок всего экрана (если возможно)
-(Смотрите секцию
-.Sx ПРОГРАММЫ
-выше)
-.It Cm screenshot_wind
-Сделать снимок окна (если возможно)
-(Смотрите секцию
-.Sx ПРОГРАММЫ
-выше)
-.It Cm version
-Показать версию в статусной строке
-.It Cm float_toggle
-Переключить окно в фокусе в плавающий режим, float
-.It Cm lock
-Заблокировать экран
-(Смотрите секцию
-.Sx ПРОГРАММЫ
-выше)
-.It Cm initscr
-Инициализировать экран еще раз
-(Смотрите секцию
-.Sx ПРОГРАММЫ
-выше)
-.El
-.Pp
-Собственные привязки назначаются следующим образом:
-.Pp
-.Dl bind[<action>] = <keys>
-.Pp
-.Aq action
-это действие из списка программ
-.Aq keys
-это не более одной клавиши-модификатора
-(MOD, Mod1, Shift, и.т.п.) и обычные клавиши
-(b, space, и.т.п.), разделенные "+".
-Например:
-.Bd -literal -offset indent
-bind[reset] = Mod4+q # назначить WIN + q на действие reset
-bind[] = Mod1+q # снять все действия с Alt + q
-.Ed
-.Pp
-На одно действие можно назначить несколько комбинаций.
-.Sh КОСТЫЛИ
-.Nm
-позволяет настроить костыли, нужные для специальной работы scrotwm
-с рядом приложений, который вы определяете сами. То есть, Вы можете
-принудительно установить способ тайлинга для какого-нибудь приложения
-.Pp
-Список стандартных костылей:
-.Pp
-.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
-.It Firefox\-bin:firefox\-bin
-TRANSSZ
-.It Firefox:Dialog
-FLOAT
-.It Gimp:gimp
-FLOAT + ANYWHERE
-.It MPlayer:xv
-FLOAT + FULLSCREEN
-.It OpenOffice.org 2.4:VCLSalFrame
-FLOAT
-.It OpenOffice.org 3.1:VCLSalFrame
-FLOAT
-.It pcb:pcb
-FLOAT
-.It xine:Xine Window
-FLOAT + ANYWHERE
-.It xine:xine Panel
-FLOAT + ANYWHERE
-.It xine:xine Video Fullscreen Window
-FULLSCREEN + FLOAT
-.It Xitk:Xitk Combo
-FLOAT + ANYWHERE
-.It Xitk:Xine Window
-FLOAT + ANYWHERE
-.It XTerm:xterm
-XTERM_FONTADJ
-.El
-.Pp
-Описание:
-.Pp
-.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
-.It FLOAT
-Такое окно не нужно тайлить вообще, разрешить ему float
-.It TRANSSZ
-Тразиентое окно
-(Смотрите секцию
-.Sx КОНФИГУРАЦИОННЫЕ ФАЙЛЫ) .
-.It ANYWHERE
-Позволить окну самостоятельно выбрать местоположение
-.It XTERM_FONTADJ
-Изменять шрифты xterm при изменении размеров окна
-.It FULLSCREEN
-Позволить окну запускаться в полноэкранном режиме
-.El
-.Pp
-Назначать костыли можно следующим образом:
-.Pp
-.Dl quirk[<class>:<name>] = <quirk> [ + <quirk> ... ]
-.Pp
-.Aq class
-.Aq name
-определяют к какому окну будет применяться костыль, а
-.Aq quirk
-один из вышеперечисленных способов.
-Например:
-.Bd -literal -offset indent
-quirk[MPlayer:xv] = FLOAT + FULLSCREEN # mplayer настроен
-quirk[pcb:pcb] = NONE  # убрать существующий костыль
-.Ed
-.Pp
-Вы можете узнать
-.Aq class
-.Aq name
-запустив xprop и нажав в интересующее окно.
-Вот как будет выглядеть вывод для Firefox:
-.Bd -literal -offset indent
-$ xprop | grep WM_CLASS
-WM_CLASS(STRING) = "Navigator", "Firefox"
-.Ed
-.Pp
-Обратите внимание, класс и имя меняются местами,
-правильный костыль будет выглядеть так:
-.Bd -literal -offset indent
-quirk[Firefox:Navigator] = FLOAT
-.Ed
-.Sh ФАЙЛЫ
-.Bl -tag -width "/etc/scrotwm.confXXX" -compact
-.It Pa ~/.scrotwm.conf
-.Nm
-Личные настройки пользователя.
-.It Pa /etc/scrotwm.conf
-.Nm
-Глобавльные настройки.
-.El
-.Sh ИСТОРИЯ
-.Nm
-идейно основан на dwm и xmonad
-.Sh АВТОРЫ
-.An -nosplit
-.Pp
-.Nm
-написан:
-.An Marco Peereboom Aq marco@peereboom.us ,
-.An Ryan Thomas McBride Aq mcbride@countersiege.com
-and
-.An Darrin Chandler Aq dwchandler@stilyagin.com .
-.Sh БАГИ
-При вызове меню с помощью
-.Cm M-p ,
-необходима корректная работа dmenu.
diff --git a/scrotwm_se.conf b/scrotwm_se.conf
deleted file mode 100644 (file)
index 68dba05..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Key bindings for Swedish (se) keyboards
-# unbind with: bind[] = <keys>
-bind[cycle_layout]     = MOD+space
-bind[flip_layout]      = MOD+Shift+apostrophe
-bind[stack_reset]      = MOD+Shift+space
-bind[master_shrink]    = MOD+h
-bind[master_grow]      = MOD+l
-bind[master_add]       = MOD+comma
-bind[master_del]       = MOD+period
-bind[stack_inc]                = MOD+Shift+comma
-bind[stack_dec]                = MOD+Shift+period
-bind[swap_main]                = MOD+Return
-bind[focus_next]       = MOD+j
-bind[focus_prev]       = MOD+k
-bind[swap_next]                = MOD+Shift+j
-bind[swap_prev]                = MOD+Shift+k
-bind[spawn_term]       = MOD+Shift+Return
-bind[menu]             = MOD+p
-bind[quit]             = MOD+Shift+q
-bind[restart]          = MOD+q
-bind[focus_main]       = MOD+m
-bind[ws_1]             = MOD+1
-bind[ws_2]             = MOD+2
-bind[ws_3]             = MOD+3
-bind[ws_4]             = MOD+4
-bind[ws_5]             = MOD+5
-bind[ws_6]             = MOD+6
-bind[ws_7]             = MOD+7
-bind[ws_8]             = MOD+8
-bind[ws_9]             = MOD+9
-bind[ws_10]            = MOD+0
-bind[ws_next]          = MOD+Right
-bind[ws_prev]          = MOD+Left
-bind[ws_next_all]      = MOD+Up
-bind[ws_prev_all]      = MOD+Down
-bind[ws_prior]         = MOD+a
-bind[screen_next]      = MOD+Shift+Right
-bind[screen_prev]      = MOD+Shift+Left
-bind[mvws_1]           = MOD+Shift+1
-bind[mvws_2]           = MOD+Shift+2
-bind[mvws_3]           = MOD+Shift+3
-bind[mvws_4]           = MOD+Shift+4
-bind[mvws_5]           = MOD+Shift+5
-bind[mvws_6]           = MOD+Shift+6
-bind[mvws_7]           = MOD+Shift+7
-bind[mvws_8]           = MOD+Shift+8
-bind[mvws_9]           = MOD+Shift+9
-bind[mvws_10]          = MOD+Shift+0
-bind[bar_toggle]       = MOD+b
-bind[focus_next]       = MOD+Tab
-bind[focus_prev]       = MOD+Shift+Tab
-bind[wind_kill]                = MOD+Shift+x
-bind[wind_del]         = MOD+x
-bind[screenshot_all]   = MOD+s
-bind[screenshot_wind]  = MOD+Shift+s
-bind[float_toggle]     = MOD+t
-bind[version]          = MOD+Shift+v
-bind[lock]             = MOD+Shift+Delete
-bind[initscr]          = MOD+Shift+i
-bind[iconify]          = MOD+w
-bind[uniconify]                = MOD+Shift+w
-bind[raise_toggle]     = MOD+Shift+r
-bind[button2]          = MOD+v
-bind[width_shrink]     = MOD+plus
-bind[width_grow]       = MOD+dead_acute
-bind[height_shrink]    = MOD+Shift+plus
-bind[height_grow]      = MOD+Shift+dead_acute
-bind[move_left]                = MOD+aring
-bind[move_right]       = MOD+dead_diaeresis
-bind[move_up]          = MOD+Shift+aring
-bind[move_down]                = MOD+Shift+dead_diaeresis
-bind[name_workspace]   = MOD+Shift+minus
-bind[search_workspace] = MOD+minus
-bind[search_win]       = MOD+f
diff --git a/scrotwm_us.conf b/scrotwm_us.conf
deleted file mode 100644 (file)
index f2ce392..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# Key bindings for United States (us) keyboards
-# unbind with: bind[] = <keys>
-bind[cycle_layout]     = MOD+space
-bind[flip_layout]      = MOD+Shift+backslash
-bind[stack_reset]      = MOD+Shift+space
-bind[master_shrink]    = MOD+h
-bind[master_grow]      = MOD+l
-bind[master_add]       = MOD+comma
-bind[master_del]       = MOD+period
-bind[stack_inc]                = MOD+Shift+comma
-bind[stack_dec]                = MOD+Shift+period
-bind[swap_main]                = MOD+Return
-bind[focus_next]       = MOD+j
-bind[focus_prev]       = MOD+k
-bind[swap_next]                = MOD+Shift+j
-bind[swap_prev]                = MOD+Shift+k
-bind[spawn_term]       = MOD+Shift+Return
-bind[menu]             = MOD+p
-bind[quit]             = MOD+Shift+q
-bind[restart]          = MOD+q
-bind[focus_main]       = MOD+m
-bind[ws_1]             = MOD+1
-bind[ws_2]             = MOD+2
-bind[ws_3]             = MOD+3
-bind[ws_4]             = MOD+4
-bind[ws_5]             = MOD+5
-bind[ws_6]             = MOD+6
-bind[ws_7]             = MOD+7
-bind[ws_8]             = MOD+8
-bind[ws_9]             = MOD+9
-bind[ws_10]            = MOD+0
-bind[ws_next]          = MOD+Right
-bind[ws_prev]          = MOD+Left
-bind[ws_next_all]      = MOD+Up
-bind[ws_prev_all]      = MOD+Down
-bind[ws_prior]         = MOD+a
-bind[screen_next]      = MOD+Shift+Right
-bind[screen_prev]      = MOD+Shift+Left
-bind[mvws_1]           = MOD+Shift+1
-bind[mvws_2]           = MOD+Shift+2
-bind[mvws_3]           = MOD+Shift+3
-bind[mvws_4]           = MOD+Shift+4
-bind[mvws_5]           = MOD+Shift+5
-bind[mvws_6]           = MOD+Shift+6
-bind[mvws_7]           = MOD+Shift+7
-bind[mvws_8]           = MOD+Shift+8
-bind[mvws_9]           = MOD+Shift+9
-bind[mvws_10]          = MOD+Shift+0
-bind[bar_toggle]       = MOD+b
-bind[focus_next]       = MOD+Tab
-bind[focus_prev]       = MOD+Shift+Tab
-bind[wind_kill]                = MOD+Shift+x
-bind[wind_del]         = MOD+x
-bind[screenshot_all]   = MOD+s
-bind[screenshot_wind]  = MOD+Shift+s
-bind[float_toggle]     = MOD+t
-bind[version]          = MOD+Shift+v
-bind[lock]             = MOD+Shift+Delete
-bind[initscr]          = MOD+Shift+i
-bind[iconify]          = MOD+w
-bind[uniconify]                = MOD+Shift+w
-bind[raise_toggle]     = MOD+Shift+r
-bind[button2]          = MOD+v
-bind[width_shrink]     = MOD+minus
-bind[width_grow]       = MOD+equal
-bind[height_shrink]    = MOD+Shift+minus
-bind[height_grow]      = MOD+Shift+equal
-bind[move_left]                = MOD+bracketleft
-bind[move_right]       = MOD+bracketright
-bind[move_up]          = MOD+Shift+bracketleft
-bind[move_down]                = MOD+Shift+bracketright
-bind[name_workspace]   = MOD+Shift+slash
-bind[search_workspace] = MOD+slash
-bind[search_win]       = MOD+f
diff --git a/spectrwm.1 b/spectrwm.1
new file mode 100644 (file)
index 0000000..b85f44f
--- /dev/null
@@ -0,0 +1,854 @@
+.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: February 8 2012 $
+.Dt SPECTRWM 1
+.Os
+.Sh NAME
+.Nm spectrwm
+.Nd window manager for X11
+.Sh SYNOPSIS
+.Nm spectrwm
+.Sh DESCRIPTION
+.Nm
+is a minimalistic window manager that tries to stay out of the way so that
+valuable screen real estate can be used for much more important stuff.
+It has sane defaults and does not require one to learn a language to do any
+configuration.
+It was written by hackers for hackers and it strives to be small, compact and
+fast.
+.Pp
+When
+.Nm
+starts up, it reads settings from its configuration file,
+.Pa spectrwm.conf .
+See the
+.Sx CONFIGURATION FILES
+section below.
+.Pp
+The following notation is used throughout this page:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Cm M
+Meta
+.It Cm S
+Shift
+.It Aq Cm Name
+Named key
+.It Cm M1
+Mouse button 1
+.It Cm M3
+Mouse button 3
+.El
+.Pp
+.Nm
+is very simple in its use.
+Most of the actions are initiated via key or mouse bindings.
+See the
+.Sx BINDINGS
+section below for defaults and customizations.
+.Sh CONFIGURATION FILES
+.Nm
+first tries to open the user specific file,
+.Pa ~/.spectrwm.conf .
+If that file is unavailable,
+it then tries to open the global configuration file
+.Pa /etc/spectrwm.conf .
+.Pp
+The format of the file is \*(Ltkeyword\*(Gt = \*(Ltsetting\*(Gt.
+For example:
+.Pp
+.Dl color_focus = red
+.Pp
+Enabling or disabling an option is done by using 1 or 0 respectively.
+.Pp
+The file supports the following keywords:
+.Bl -tag -width 2m
+.It Ic autorun
+Launch an application in a specified workspace at start-of-day.
+Defined in the format ws[<idx>]:application, e.g. ws[2]:xterm launches an
+xterm in workspace 2.
+.It Ic bar_action
+External script that populates additional information in the status bar,
+such as battery life.
+.It Ic bar_at_bottom
+Place the statusbar at the bottom of each region instead of the top.
+.It Ic bar_border Ns Bq Ar x
+Color of the status bar border in screen
+.Ar x .
+.It Ic bar_border_width
+Set status bar border thickness in pixels.
+Disable border by setting to 0.
+.It Ic bar_color Ns Bq Ar x
+Color of the status bar window in screen
+.Ar x .
+.It Ic bar_delay
+Update frequency, in seconds, of external script that populates the status bar.
+.It Ic bar_enabled
+Enable or disable status bar.
+.It Ic bar_font
+Status bar font.
+.It Ic bar_font_color Ns Bq Ar x
+Color of the font in status bar in screen
+.Ar x .
+.It Ic bar_justify
+Justify the status bar text. Possible values are
+.Pa left ,
+.Pa center ,
+and
+.Pa right .
+.It Ic bind Ns Bq Ar x
+Bind key combo to action
+.Ar x .
+See the
+.Sx BINDINGS
+section below.
+.It Ic border_width
+Set window border thickness in pixels.
+Disable all borders by setting to 0.
+.It Ic clock_enabled
+Enable or disable displaying the clock in the status bar.
+Disable by setting to 0
+so a custom clock could be used in the
+.Pa bar_action
+script.
+.It Ic color_focus
+Border color of the currently focussed window.
+.It Ic color_unfocus
+Border color of unfocussed windows.
+.It Ic dialog_ratio
+Some applications have dialogue windows that are too small to be useful.
+This ratio is the screen size to what they will be resized.
+For example, 0.6 is 60% of the physical screen size.
+.It Ic disable_border
+Remove border when bar is disabled and there is only one window on the screen.
+.It Ic focus_mode
+Using a value of
+.Pa follow_cursor
+will make the window manager focus the window
+under the mouse when switching workspaces and creating windows.
+.It Ic keyboard_mapping
+Clear all key bindings and load new key bindings from the specified file.
+This allows you to load pre-defined key bindings for your keyboard layout.
+See the
+.Sx KEYBOARD MAPPING FILES
+section below for a list of keyboard mapping files that have been provided
+for several keyboard layouts.
+.It Ic layout
+Select layout to use at start-of-day.
+Defined in the format
+ws[idx]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode, e.g.
+ws[2]:-4:0:1:0:horizontal sets worskspace 2 to the horizontal stack mode and
+shrinks the master area by 4 ticks and adds one window to the stack, while
+maintaining default floating window behavior.
+Possible stack_mode values are
+.Pa vertical ,
+.Pa horizontal
+and
+.Pa fullscreen .
+.Pp
+See
+.Pa master_grow ,
+.Pa master_shrink ,
+.Pa master_add ,
+.Pa master_del ,
+.Pa stack_inc ,
+.Pa stack_dec ,
+and
+.Pa always_raise
+for more information.
+Note that the stacking options are complicated and have side-effects.
+One should familiarize oneself with these commands before experimenting with the
+.Pa layout
+option.
+.Pp
+This setting is not retained at restart.
+.It Ic modkey
+Change mod key.
+Mod1 is generally the ALT key and Mod4 is the windows key on a PC.
+.It Ic program Ns Bq Ar p
+Define new action to spawn a program
+.Ar p .
+See the
+.Sx PROGRAMS
+section below.
+.It Ic quirk Ns Bq Ar c:n
+Add "quirk" for windows with class
+.Ar c
+and name
+.Ar n .
+See the
+.Sx QUIRKS
+section below.
+.It Ic region
+Allocates a custom region, removing any autodetected regions which occupy the same
+space on the screen.
+Defined in the format screen[<idx>]:WIDTHxHEIGHT+X+Y,
+e.g.\& screen[1]:800x1200+0+0.
+.Pp
+To make a screen span multiple monitors, create a region big enough to cover
+them all, e.g. screen[1]:2048x768+0+0 makes the screen span two monitors with
+1024x768 resolution sitting one next to the other.
+.It Ic stack_enabled
+Enable or disable displaying the current stacking algorithm in the status bar.
+.It Ic term_width
+Set a preferred minimum width for the terminal.
+If this value is greater than 0,
+.Nm
+will attempt to adjust the font sizes in the terminal to keep the terminal
+width above this number as the window is resized.
+Only
+.Xr xterm 1
+is currently supported.
+The
+.Xr xterm 1
+binary must not be setuid or setgid, which it is by default on most systems.
+Users may need to set program[term] (see the
+.Sx PROGRAMS
+section) to use an alternate copy of the
+.Xr xterm 1
+binary without the setgid bit set.
+.It Ic title_class_enabled
+Enable or disable displaying the window class in the status bar.
+Enable by setting to 1.
+.It Ic title_name_enabled
+Enable or disable displaying the window title in the status bar.
+Enable by setting to 1.
+.It Ic urgent_enabled
+Enable or disable the urgency hint.
+Note that many terminal emulators require this to be enabled for it to
+propagate.
+In xterm, for example, one needs to add the following line
+.Pa xterm.urgentOnBell: true
+to
+.Pa .Xdefaults .
+.It Ic verbose_layout
+Enable or disable displaying the current master and stack values in the status
+bar.
+Enable by setting to 1.
+.It Ic window_name_enabled
+Enable or disable displaying the window name in the status bar.
+Enable by setting to 1.
+.El
+.Pp
+Colors need to be specified per the
+.Xr XQueryColor 3
+specification and fonts need to be specified per the
+.Xr XQueryFont 3
+specification.
+.Pp
+To list the available fonts in your system see
+.Xr fc-list 1
+or
+.Xr xlsfonts 1
+manpages.
+The
+.Xr xfontsel 1
+application can help you to show the X Logical Font Description ("XLFD") used
+as setting in the keyword
+.Pa bar_font .
+.Sh PROGRAMS
+.Nm
+allows you to define custom actions to launch programs of your choice and then
+bind them the same as with built-in actions.
+See the
+.Sx BINDINGS
+section below.
+.Pp
+The default programs are described below:
+.Pp
+.Bl -tag -width "screenshot_wind" -offset indent -compact
+.It Cm term
+xterm
+.It Cm screenshot_all
+screenshot.sh full
+.It Cm screenshot_wind
+screenshot.sh window
+.It Cm lock
+xlock
+.It Cm initscr
+initscreen.sh
+.It Cm menu
+dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
+.El
+.Pp
+Custom programs in the configuration file are specified as follows:
+.Pp
+.Dl program[<name>] = <progpath> [<arg> [... <arg>]]
+.Pp
+.Aq name
+is any identifier that does not conflict with a built-in action or keyword,
+.Aq progpath
+is the desired program, and
+.Aq arg
+is zero or more arguments to the program.
+.Pp
+The following variables represent settable values in
+.Nm
+(see the
+.Sx CONFIGURATION FILES
+section above),
+and may be used in the
+.Aq arg
+fields and will be substituted for values at the time the program is spawned:
+.Pp
+.Bl -tag -width "$bar_font_color" -offset indent -compact
+.It Cm $bar_border
+.It Cm $bar_color
+.It Cm $bar_font
+.It Cm $bar_font_color
+.It Cm $color_focus
+.It Cm $color_unfocus
+.El
+.Pp
+Example:
+.Bd -literal -offset indent
+program[ff] = /usr/local/bin/firefox http://spectrwm.org/
+bind[ff] = Mod+Shift+b # Now Mod+Shift+B launches firefox
+.Ed
+.Pp
+To undo the previous:
+.Bd -literal -offset indent
+bind[] = Mod+Shift+b
+program[ff] =
+.Ed
+.Sh BINDINGS
+.Nm
+provides many functions (or actions) accessed via key or mouse bindings.
+.Pp
+The current mouse bindings are described below:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M1
+Focus window
+.It Cm M-M1
+Move window
+.It Cm M-M3
+Resize window
+.It Cm M-S-M3
+Resize window while maintaining it centered
+.El
+.Pp
+The default key bindings are described below:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M-S- Ns Aq Cm Return
+term
+.It Cm M-p
+menu
+.It Cm M-S-q
+quit
+.It Cm M-q
+restart
+.It Cm M- Ns Aq Cm Space
+cycle_layout
+.It Cm M-S- Ns Aq Cm \e
+flip_layout
+.It Cm M-S- Ns Aq Cm Space
+stack_reset
+.It Cm M-h
+master_shrink
+.It Cm M-l
+master_grow
+.It Cm M-,
+master_add
+.It Cm M-.
+master_del
+.It Cm M-S-,
+stack_inc
+.It Cm M-S-.
+stack_dec
+.It Cm M- Ns Aq Cm Return
+swap_main
+.It Xo
+.Cm M-j ,
+.Cm M- Ns Aq Cm TAB
+.Xc
+focus_next
+.It Xo
+.Cm M-k ,
+.Cm M-S- Ns Aq Cm TAB
+.Xc
+focus_prev
+.It Cm M-m
+focus_main
+.It Cm M-S-j
+swap_next
+.It Cm M-S-k
+swap_prev
+.It Cm M-b
+bar_toggle
+.It Cm M-x
+wind_del
+.It Cm M-S-x
+wind_kill
+.It Cm M- Ns Aq Ar n
+.Pf ws_ Ar n
+.It Cm M-S- Ns Aq Ar n
+.Pf mvws_ Ar n
+.It Cm M- Ns Aq Cm Right
+ws_next
+.It Cm M- Ns Aq Cm Left
+ws_prev
+.It Cm M- Ns Aq Cm Up
+ws_next_all
+.It Cm M- Ns Aq Cm Down
+ws_prev_all
+.It Cm M-a
+ws_prior
+.It Cm M-S- Ns Aq Cm Right
+screen_next
+.It Cm M-S- Ns Aq Cm Left
+screen_prev
+.It Cm M-s
+screenshot_all
+.It Cm M-S-s
+screenshot_wind
+.It Cm M-S-v
+version
+.It Cm M-t
+float_toggle
+.It Cm M-S- Ns Aq Cm Delete
+lock
+.It Cm M-S-i
+initscr
+.It Cm M-w
+iconify
+.It Cm M-S-w
+uniconify
+.It Cm M-S-r
+always_raise
+.It Cm M-v
+button2
+.It Cm M--
+width_shrink
+.It Cm M-=
+width_grow
+.It Cm M-S--
+height_shrink
+.It Cm M-S-=
+height_grow
+.It Cm M-[
+move_left
+.It Cm M-]
+move_right
+.It Cm M-S-[
+move_up
+.It Cm M-S-]
+move_down
+.It Cm M-S-/
+name_workspace
+.It Cm M-/
+search_workspace
+.It Cm M-f
+search_win
+.El
+.Pp
+The action names and descriptions are listed below:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXXX" -offset indent -compact
+.It Cm term
+Spawn a new terminal
+(see
+.Sx PROGRAMS
+above).
+.It Cm menu
+Menu
+(see
+.Sx PROGRAMS
+above).
+.It Cm quit
+Quit
+.Nm .
+.It Cm restart
+Restart
+.Nm .
+.It Cm cycle_layout
+Cycle layout.
+.It Cm flip_layout
+Swap the master and stacking areas.
+.It Cm stack_reset
+Reset layout.
+.It Cm master_shrink
+Shrink master area.
+.It Cm master_grow
+Grow master area.
+.It Cm master_add
+Add windows to master area.
+.It Cm master_del
+Remove windows from master area.
+.It Cm stack_inc
+Add columns/rows to stacking area.
+.It Cm stack_dec
+Remove columns/rows from stacking area.
+.It Cm swap_main
+Move current window to master area.
+.It Cm focus_next
+Focus next window in workspace.
+.It Cm focus_prev
+Focus previous window in workspace.
+.It Cm focus_main
+Focus on main window in workspace.
+.It Cm swap_next
+Swap with next window in workspace.
+.It Cm swap_prev
+Swap with previous window in workspace.
+.It Cm bar_toggle
+Toggle status bar in all workspaces.
+.It Cm wind_del
+Delete current window in workspace.
+.It Cm wind_kill
+Destroy current window in workspace.
+.It Cm ws_ Ns Ar n
+Switch to workspace
+.Ar n ,
+where
+.Ar n
+is 1 through 10.
+.It Cm mvws_ Ns Ar n
+Move current window to workspace
+.Ar n ,
+where
+.Ar n
+is 1 through 10.
+.It Cm ws_next
+Switch to next workspace with a window in it.
+.It Cm ws_prev
+Switch to previous workspace with a window in it.
+.It Cm ws_next_all
+Switch to next workspace.
+.It Cm ws_prev_all
+Switch to previous workspace.
+.It Cm ws_prior
+Switch to last visited workspace.
+.It Cm screen_next
+Move pointer to next region.
+.It Cm screen_prev
+Move pointer to previous region.
+.It Cm screenshot_all
+Take screenshot of entire screen (if enabled)
+(see
+.Sx PROGRAMS
+above).
+.It Cm screenshot_wind
+Take screenshot of selected window (if enabled)
+(see
+.Sx PROGRAMS
+above).
+.It Cm version
+Toggle version in status bar.
+.It Cm float_toggle
+Toggle focused window between tiled and floating.
+.It Cm lock
+Lock screen
+(see
+.Sx PROGRAMS
+above).
+.It Cm initscr
+Reinitialize physical screens
+(see
+.Sx PROGRAMS
+above).
+.It Cm iconify
+Minimize (unmap) currently focused window.
+.It Cm uniconify
+Maximize (map) window returned by dmenu selection.
+.It Cm always_raise
+When set tiled windows are allowed to obscure floating windows.
+.It Cm button2
+Fake a middle mouse button click (mouse button 2).
+.It Cm width_shrink
+Shrink the width of a floating window.
+.It Cm width_grow
+Grow the width of a floating window.
+.It Cm height_shrink
+Shrink the height of a floating window.
+.It Cm height_grow
+Grow the height of a floating window.
+.It Cm move_left
+Move a floating window a step to the left.
+.It Cm move_right
+Move a floating window a step to the right.
+.It Cm move_up
+Move a floating window a step upwards.
+.It Cm move_down
+Move a floating window a step downwards.
+.It Cm name_workspace
+Name the current workspace.
+.It Cm search_workspace
+Search for a workspace.
+.It Cm search_win
+Search the windows in the current workspace.
+.El
+.Pp
+Custom bindings in the configuration file are specified as follows:
+.Pp
+.Dl bind[<action>] = <keys>
+.Pp
+.Aq action
+is one of the actions listed above (or empty) and
+.Aq keys
+is in the form of zero or more modifier keys
+(MOD, Mod1, Shift, etc.) and one or more normal keys
+(b, space, etc.), separated by "+".
+For example:
+.Bd -literal -offset indent
+bind[reset] = Mod4+q # bind Windows-key + q to reset
+bind[] = Mod1+q # unbind Alt + q
+.Ed
+.Pp
+To use the currently defined
+.Ic modkey ,
+specify MOD as the modifier key.
+.Pp
+Multiple key combinations may be bound to the same action.
+.Sh KEYBOARD MAPPING FILES
+Keyboard mapping files for several keyboard layouts are listed
+below.
+These files can be used with the
+.Pa keyboard_mapping
+setting to load pre-defined key bindings for the specified
+keyboard layout.
+.Pp
+.Bl -tag -width "spectrwm_XX.confXXX" -offset indent -compact
+.It Cm spectrwm_cz.conf
+Czech Republic keyboard layout
+.It Cm spectrwm_es.conf
+Spanish keyboard layout
+.It Cm spectrwm_fr.conf
+French keyboard layout
+.It Cm spectrwm_fr_ch.conf
+Swiss French keyboard layout
+.It Cm spectrwm_se.conf
+Swedish keyboard layout
+.It Cm spectrwm_us.conf
+United States keyboard layout
+.El
+.Sh QUIRKS
+.Nm
+provides "quirks" which handle windows that must be treated specially
+in a tiling window manager, such as some dialogs and fullscreen apps.
+.Pp
+The default quirks are described below:
+.Pp
+.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
+.It Firefox\-bin:firefox\-bin
+TRANSSZ
+.It Firefox:Dialog
+FLOAT
+.It Gimp:gimp
+FLOAT + ANYWHERE
+.It MPlayer:xv
+FLOAT + FULLSCREEN + FOCUSPREV
+.It OpenOffice.org 2.4:VCLSalFrame
+FLOAT
+.It OpenOffice.org 3.1:VCLSalFrame
+FLOAT
+.It pcb:pcb
+FLOAT
+.It xine:Xine Window
+FLOAT + ANYWHERE
+.It xine:xine Panel
+FLOAT + ANYWHERE
+.It xine:xine Video Fullscreen Window
+FULLSCREEN + FLOAT
+.It Xitk:Xitk Combo
+FLOAT + ANYWHERE
+.It Xitk:Xine Window
+FLOAT + ANYWHERE
+.It XTerm:xterm
+XTERM_FONTADJ
+.El
+.Pp
+The quirks themselves are described below:
+.Pp
+.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
+.It FLOAT
+This window should not be tiled, but allowed to float freely.
+.It TRANSSZ
+Adjusts size on transient windows that are too small using dialog_ratio
+(see
+.Sx CONFIGURATION FILES ) .
+.It ANYWHERE
+Allow window to position itself, uncentered.
+.It XTERM_FONTADJ
+Adjust xterm fonts when resizing.
+.It FULLSCREEN
+Remove border to allow window to use full screen size.
+.It FOCUSPREV
+On exit force focus on previously focused application not previous application
+in the stack.
+.El
+.Pp
+Custom quirks in the configuration file are specified as follows:
+.Pp
+.Dl quirk[<class>:<name>] = <quirk> [ + <quirk> ... ]
+.Pp
+.Aq class
+and
+.Aq name
+specify the window to which the quirk(s) apply, and
+.Aq quirk
+is one of the quirks from the list above.
+For example:
+.Bd -literal -offset indent
+quirk[MPlayer:xv] = FLOAT + FULLSCREEN + FOCUSPREV
+quirk[pcb:pcb] = NONE  # remove existing quirk
+.Ed
+.Pp
+You can obtain
+.Aq class
+and
+.Aq name
+by running
+.Xr xprop 1
+and then clicking on the desired window.
+In the following example the main window of Firefox was clicked:
+.Bd -literal -offset indent
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "Navigator", "Firefox"
+.Ed
+.Pp
+Note that grepping for WM_CLASS flips class and name.
+In the example above the quirk entry would be:
+.Bd -literal -offset indent
+quirk[Firefox:Navigator] = FLOAT
+.Ed
+.Pp
+.Nm
+also automatically assigns quirks to windows based on the value
+of the window's _NET_WM_WINDOW_TYPE property as follows:
+.Pp
+.Bl -tag -width "_NET_WM_WINDOW_TYPE_TOOLBAR<TAB>XXX" -offset indent -compact
+.It _NET_WM_WINDOW_TYPE_DOCK
+FLOAT + ANYWHERE
+.It _NET_WM_WINDOW_TYPE_TOOLBAR
+FLOAT + ANYWHERE
+.It _NET_WM_WINDOW_TYPE_UTILITY
+FLOAT + ANYWHERE
+.It _NET_WM_WINDOW_TYPE_SPLASH
+FLOAT
+.It _NET_WM_WINDOW_TYPE_DIALOG
+FLOAT
+.El
+.Pp
+In all other cases, no automatic quirks are assigned to the window.
+Quirks specified in the configuration file override the automatic quirks.
+.Sh EWMH
+.Nm
+partially implements the Extended Window Manager Hints (EWMH) specification.
+This enables controlling windows as well as
+.Nm
+itself from external scripts and programs.
+This is achieved by
+.Nm
+responding to certain ClientMessage events.
+From the terminal these events
+can be conveniently sent using tools such as
+.Xr wmctrl 1
+and
+.Xr xdotool 1 .
+For the
+actual format of these ClientMessage events, see the EWMH specification.
+.Pp
+The id of the currently focused window is stored in the _NET_ACTIVE_WINDOW
+property of the root window.
+This can be used for example to retrieve the
+title of the currently active window with
+.Xr xprop 1
+and
+.Xr grep 1 :
+.Bd -literal -offset indent
+$ WINDOWID=`xprop \-root _NET_ACTIVE_WINDOW | grep \-o "0x.*"`
+$ xprop \-id $WINDOWID WM_NAME | grep \-o "\\".*\\""
+.Ed
+.Pp
+A window can be focused by sending a _NET_ACTIVE_WINDOW client message
+to the root window.
+For example, using
+.Xr wmctrl 1
+to send the message
+(assuming 0x4a0000b is the id of the window to be focused):
+.Bd -literal -offset indent
+$ wmctrl \-i \-a 0x4a0000b
+.Ed
+.Pp
+Windows can be closed by sending a _NET_CLOSE_WINDOW client message
+to the root window.
+For example, using
+.Xr wmctrl 1
+to send the message
+(assuming 0x4a0000b is the id of the window to be closed):
+.Bd -literal -offset indent
+$ wmctrl \-i \-c 0x4a0000b
+.Ed
+.Pp
+Windows can be floated and un-floated by adding or removing the
+_NET_WM_STATE_ABOVE atom from the _NET_WM_STATE property of the window.
+This can be achieved by sending a _NET_WM_STATE client message to the
+root window.
+For example, the following toggles the floating state of
+a window using
+.Xr wmctrl 1
+to send the message (assuming 0x4a0000b is the  id of the window floated
+or un-floated):
+.Bd -literal -offset indent
+$ wmctrl \-i \-r 0x4a0000b \-b toggle,_NET_WM_STATE_ABOVE
+.Ed
+.Pp
+Floating windows can also be resized and moved by sending a
+_NET_MOVERESIZE_WINDOW client message to the root window.
+For example,
+using
+.Xr wmctrl 1
+to send the message (assuming 0x4a0000b is the id of
+the window to be resize/moved):
+.Bd -literal -offset indent
+$ wmctrl \-i \-r 0x4a0000b \-e 0,100,50,640,480
+.Ed
+.Pp
+This moves the window to (100,50) and resizes it to 640x480.
+.Pp
+Any _NET_MOVERESIZE_WINDOW events received for stacked windows are ignored.
+.Sh SIGNALS
+Sending
+.Nm
+a HUP signal will restart it.
+.Sh FILES
+.Bl -tag -width "/etc/spectrwm.confXXX" -compact
+.It Pa ~/.spectrwm.conf
+.Nm
+user specific settings.
+.It Pa /etc/spectrwm.conf
+.Nm
+global settings.
+.El
+.Sh HISTORY
+.Nm
+was inspired by xmonad & dwm.
+.Sh AUTHORS
+.An -nosplit
+.Nm
+was written by:
+.Pp
+.Bl -tag -width "Ryan Thomas McBride Aq mcbride@countersiege.com " -offset indent -compact
+.It Cm Marco Peereboom Aq marco@peereboom.us
+.It Cm Ryan Thomas McBride Aq mcbride@countersiege.com
+.It Cm Darrin Chandler Aq dwchandler@stilyagin.com
+.It Cm Pierre-Yves Ritschard Aq pyr@spootnik.org
+.It Cm Tuukka Kataja Aq stuge@xor.fi
+.It Cm Jason L. Wright Aq jason@thought.net
+.It Cm Reginald Kennedy Aq rk@rejii.com
+.El
diff --git a/spectrwm.c b/spectrwm.c
new file mode 100644 (file)
index 0000000..2928f00
--- /dev/null
@@ -0,0 +1,7096 @@
+/*
+ * Copyright (c) 2009-2012 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2009-2011 Ryan McBride <mcbride@countersiege.com>
+ * Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
+ * Copyright (c) 2009 Pierre-Yves Ritschard <pyr@spootnik.org>
+ * Copyright (c) 2010 Tuukka Kataja <stuge@xor.fi>
+ * Copyright (c) 2011 Jason L. Wright <jason@thought.net>
+ * Copyright (c) 2011-2012 Reginald Kennedy <rk@rejii.com>
+ * Copyright (c) 2012 Lawrence Teo <lteo@lteo.net>
+ * Copyright (c) 2012 Tiago Cunha <tcunha@gmx.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Much code and ideas taken from dwm under the following license:
+ * MIT/X Consortium License
+ *
+ * 2006-2008 Anselm R Garbe <garbeam at gmail dot com>
+ * 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
+ * 2006-2007 Jukka Salmi <jukka at salmi dot ch>
+ * 2007 Premysl Hruby <dfenze at gmail dot com>
+ * 2007 Szabolcs Nagy <nszabolcs at gmail dot com>
+ * 2007 Christof Musik <christof at sendfax dot de>
+ * 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
+ * 2007-2008 Peter Hartlich <sgkkr at hartlich dot com>
+ * 2008 Martin Hurton <martin dot hurton at gmail dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#include <util.h>
+#include <pwd.h>
+#include <paths.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/queue.h>
+#include <sys/param.h>
+#include <sys/select.h>
+#if defined(__linux__)
+#include "tree.h"
+#elif defined(__OpenBSD__)
+#include <sys/tree.h>
+#elif defined(__FreeBSD__)
+#include <sys/tree.h>
+#else
+#include <sys/tree.h>
+#endif
+
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/XTest.h>
+
+#ifdef __OSX__
+#include <osx.h>
+#endif
+
+#include "version.h"
+
+#ifdef SPECTRWM_BUILDSTR
+static const char      *buildstr = SPECTRWM_BUILDSTR;
+#else
+static const char      *buildstr = SPECTRWM_VERSION;
+#endif
+
+#if RANDR_MAJOR < 1
+#  error XRandR versions less than 1.0 are not supported
+#endif
+
+#if RANDR_MAJOR >= 1
+#if RANDR_MINOR >= 2
+#define SWM_XRR_HAS_CRTC
+#endif
+#endif
+
+/*#define SWM_DEBUG*/
+#ifdef SWM_DEBUG
+#define DPRINTF(x...)          do { if (swm_debug) fprintf(stderr, x); } while (0)
+#define DNPRINTF(n,x...)       do { if (swm_debug & n) fprintf(stderr, x); } while (0)
+#define SWM_D_MISC             0x0001
+#define SWM_D_EVENT            0x0002
+#define SWM_D_WS               0x0004
+#define SWM_D_FOCUS            0x0008
+#define SWM_D_MOVE             0x0010
+#define SWM_D_STACK            0x0020
+#define SWM_D_MOUSE            0x0040
+#define SWM_D_PROP             0x0080
+#define SWM_D_CLASS            0x0100
+#define SWM_D_KEY              0x0200
+#define SWM_D_QUIRK            0x0400
+#define SWM_D_SPAWN            0x0800
+#define SWM_D_EVENTQ           0x1000
+#define SWM_D_CONF             0x2000
+#define SWM_D_BAR              0x4000
+
+u_int32_t              swm_debug = 0
+                           | SWM_D_MISC
+                           | SWM_D_EVENT
+                           | SWM_D_WS
+                           | SWM_D_FOCUS
+                           | SWM_D_MOVE
+                           | SWM_D_STACK
+                           | SWM_D_MOUSE
+                           | SWM_D_PROP
+                           | SWM_D_CLASS
+                           | SWM_D_KEY
+                           | SWM_D_QUIRK
+                           | SWM_D_SPAWN
+                           | SWM_D_EVENTQ
+                           | SWM_D_CONF
+                           | SWM_D_BAR
+                           ;
+#else
+#define DPRINTF(x...)
+#define DNPRINTF(n,x...)
+#endif
+
+#define LENGTH(x)              (sizeof x / sizeof x[0])
+#define MODKEY                 Mod1Mask
+#define CLEANMASK(mask)                (mask & ~(numlockmask | LockMask))
+#define BUTTONMASK             (ButtonPressMask|ButtonReleaseMask)
+#define MOUSEMASK              (BUTTONMASK|PointerMotionMask)
+#define SWM_PROPLEN            (16)
+#define SWM_FUNCNAME_LEN       (32)
+#define SWM_KEYS_LEN           (255)
+#define SWM_QUIRK_LEN          (64)
+#define X(r)                   (r)->g.x
+#define Y(r)                   (r)->g.y
+#define WIDTH(r)               (r)->g.w
+#define HEIGHT(r)              (r)->g.h
+#define SH_MIN(w)              (w)->sh_mask & PMinSize
+#define SH_MIN_W(w)            (w)->sh.min_width
+#define SH_MIN_H(w)            (w)->sh.min_height
+#define SH_MAX(w)              (w)->sh_mask & PMaxSize
+#define SH_MAX_W(w)            (w)->sh.max_width
+#define SH_MAX_H(w)            (w)->sh.max_height
+#define SH_INC(w)              (w)->sh_mask & PResizeInc
+#define SH_INC_W(w)            (w)->sh.width_inc
+#define SH_INC_H(w)            (w)->sh.height_inc
+#define SWM_MAX_FONT_STEPS     (3)
+#define WINID(w)               ((w) ? (w)->id : 0)
+#define YESNO(x)               ((x) ? "yes" : "no")
+
+#define SWM_FOCUS_DEFAULT      (0)
+#define SWM_FOCUS_SYNERGY      (1)
+#define SWM_FOCUS_FOLLOW       (2)
+
+#define SWM_CONF_DEFAULT       (0)
+#define SWM_CONF_KEYMAPPING    (1)
+
+#ifndef SWM_LIB
+#define SWM_LIB                        "/usr/local/lib/libswmhack.so"
+#endif
+
+char                   **start_argv;
+Atom                   astate;
+Atom                   aprot;
+Atom                   adelete;
+Atom                   takefocus;
+Atom                   a_wmname;
+Atom                   a_netwmname;
+Atom                   a_utf8_string;
+Atom                   a_string;
+Atom                   a_swm_iconic;
+volatile sig_atomic_t   running = 1;
+volatile sig_atomic_t   restart_wm = 0;
+int                    outputs = 0;
+int                    last_focus_event = FocusOut;
+int                    (*xerrorxlib)(Display *, XErrorEvent *);
+int                    other_wm;
+int                    ss_enabled = 0;
+int                    xrandr_support;
+int                    xrandr_eventbase;
+unsigned int           numlockmask = 0;
+Display                        *display;
+
+int                    cycle_empty = 0;
+int                    cycle_visible = 0;
+int                    term_width = 0;
+int                    font_adjusted = 0;
+unsigned int           mod_key = MODKEY;
+
+/* dmenu search */
+struct swm_region      *search_r;
+int                    select_list_pipe[2];
+int                    select_resp_pipe[2];
+pid_t                  searchpid;
+volatile sig_atomic_t  search_resp;
+int                    search_resp_action;
+
+struct search_window {
+       TAILQ_ENTRY(search_window)      entry;
+       int                             idx;
+       struct ws_win                   *win;
+       GC                              gc;
+       Window                          indicator;
+};
+TAILQ_HEAD(search_winlist, search_window);
+
+struct search_winlist search_wl;
+
+/* search actions */
+enum {
+       SWM_SEARCH_NONE,
+       SWM_SEARCH_UNICONIFY,
+       SWM_SEARCH_NAME_WORKSPACE,
+       SWM_SEARCH_SEARCH_WORKSPACE,
+       SWM_SEARCH_SEARCH_WINDOW
+};
+
+/* dialog windows */
+double                 dialog_ratio = 0.6;
+/* status bar */
+#define SWM_BAR_MAX            (256)
+#define SWM_BAR_JUSTIFY_LEFT   (0)
+#define SWM_BAR_JUSTIFY_CENTER (1)
+#define SWM_BAR_JUSTIFY_RIGHT  (2)
+#define SWM_BAR_OFFSET         (4)
+#define SWM_BAR_FONTS          "-*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*," \
+                               "-*-profont-*-*-*-*-*-*-*-*-*-*-*-*,"       \
+                               "-*-times-medium-r-*-*-*-*-*-*-*-*-*-*,"    \
+                               "-misc-fixed-medium-r-*-*-*-*-*-*-*-*-*-*"
+
+#ifdef X_HAVE_UTF8_STRING
+#define DRAWSTRING(x...)       Xutf8DrawString(x)
+#else
+#define DRAWSTRING(x...)       XmbDrawString(x)
+#endif
+
+char                   *bar_argv[] = { NULL, NULL };
+int                    bar_pipe[2];
+unsigned char          bar_ext[SWM_BAR_MAX];
+char                   bar_vertext[SWM_BAR_MAX];
+int                    bar_version = 0;
+sig_atomic_t           bar_alarm = 0;
+int                    bar_delay = 30;
+int                    bar_enabled = 1;
+int                    bar_border_width = 1;
+int                    bar_at_bottom = 0;
+int                    bar_extra = 1;
+int                    bar_extra_running = 0;
+int                    bar_verbose = 1;
+int                    bar_height = 0;
+int                    bar_justify = SWM_BAR_JUSTIFY_LEFT;
+int                    stack_enabled = 1;
+int                    clock_enabled = 1;
+int                    urgent_enabled = 0;
+char                   *clock_format = NULL;
+int                    title_name_enabled = 0;
+int                    title_class_enabled = 0;
+int                    window_name_enabled = 0;
+int                    focus_mode = SWM_FOCUS_DEFAULT;
+int                    disable_border = 0;
+int                    border_width = 1;
+int                    verbose_layout = 0;
+pid_t                  bar_pid;
+XFontSet               bar_fs;
+XFontSetExtents                *bar_fs_extents;
+char                   *bar_fonts;
+char                   *spawn_term[] = { NULL, NULL }; /* XXX fully dynamic */
+struct passwd          *pwd;
+
+#define SWM_MENU_FN    (2)
+#define SWM_MENU_NB    (4)
+#define SWM_MENU_NF    (6)
+#define SWM_MENU_SB    (8)
+#define SWM_MENU_SF    (10)
+
+/* layout manager data */
+struct swm_geometry {
+       int                     x;
+       int                     y;
+       int                     w;
+       int                     h;
+};
+
+struct swm_screen;
+struct workspace;
+
+/* virtual "screens" */
+struct swm_region {
+       TAILQ_ENTRY(swm_region) entry;
+       struct swm_geometry     g;
+       struct workspace        *ws;    /* current workspace on this region */
+       struct workspace        *ws_prior; /* prior workspace on this region */
+       struct swm_screen       *s;     /* screen idx */
+       Window                  bar_window;
+};
+TAILQ_HEAD(swm_region_list, swm_region);
+
+struct ws_win {
+       TAILQ_ENTRY(ws_win)     entry;
+       Window                  id;
+       Window                  transient;
+       struct ws_win           *child_trans;   /* transient child window */
+       struct swm_geometry     g;              /* current geometry */
+       struct swm_geometry     g_float;        /* geometry when floating */
+       struct swm_geometry     rg_float;       /* region geom when floating */
+       int                     g_floatvalid;   /* g_float geometry validity */
+       int                     floatmaxed;     /* whether maxed by max_stack */
+       int                     floating;
+       int                     manual;
+       int                     iconic;
+       unsigned int            ewmh_flags;
+       int                     font_size_boundary[SWM_MAX_FONT_STEPS];
+       int                     font_steps;
+       int                     last_inc;
+       int                     can_delete;
+       int                     take_focus;
+       int                     java;
+       unsigned long           quirks;
+       struct workspace        *ws;    /* always valid */
+       struct swm_screen       *s;     /* always valid, never changes */
+       XWindowAttributes       wa;
+       XSizeHints              sh;
+       long                    sh_mask;
+       XClassHint              ch;
+       XWMHints                *hints;
+};
+TAILQ_HEAD(ws_win_list, ws_win);
+
+/* pid goo */
+struct pid_e {
+       TAILQ_ENTRY(pid_e)      entry;
+       long                    pid;
+       int                     ws;
+};
+TAILQ_HEAD(pid_list, pid_e);
+struct pid_list                        pidlist = TAILQ_HEAD_INITIALIZER(pidlist);
+
+/* layout handlers */
+void   stack(void);
+void   vertical_config(struct workspace *, int);
+void   vertical_stack(struct workspace *, struct swm_geometry *);
+void   horizontal_config(struct workspace *, int);
+void   horizontal_stack(struct workspace *, struct swm_geometry *);
+void   max_stack(struct workspace *, struct swm_geometry *);
+void   plain_stacker(struct workspace *);
+void   fancy_stacker(struct workspace *);
+
+struct ws_win *find_window(Window);
+
+void   grabbuttons(struct ws_win *, int);
+void   new_region(struct swm_screen *, int, int, int, int);
+void   unmanage_window(struct ws_win *);
+long   getstate(Window);
+
+int    conf_load(char *, int);
+
+struct layout {
+       void            (*l_stack)(struct workspace *, struct swm_geometry *);
+       void            (*l_config)(struct workspace *, int);
+       u_int32_t       flags;
+#define SWM_L_FOCUSPREV                (1<<0)
+#define SWM_L_MAPONFOCUS       (1<<1)
+       void            (*l_string)(struct workspace *);
+} layouts[] =  {
+       /* stack,               configure */
+       { vertical_stack,       vertical_config,        0,      plain_stacker },
+       { horizontal_stack,     horizontal_config,      0,      plain_stacker },
+       { max_stack,            NULL,
+         SWM_L_MAPONFOCUS | SWM_L_FOCUSPREV,                   plain_stacker },
+       { NULL,                 NULL,                   0,      NULL  },
+};
+
+/* position of max_stack mode in the layouts array, index into layouts! */
+#define SWM_V_STACK            (0)
+#define SWM_H_STACK            (1)
+#define SWM_MAX_STACK          (2)
+
+#define SWM_H_SLICE            (32)
+#define SWM_V_SLICE            (32)
+
+/* define work spaces */
+struct workspace {
+       int                     idx;            /* workspace index */
+       char                    *name;          /* workspace name */
+       int                     always_raise;   /* raise windows on focus */
+       struct layout           *cur_layout;    /* current layout handlers */
+       struct ws_win           *focus;         /* may be NULL */
+       struct ws_win           *focus_prev;    /* may be NULL */
+       struct swm_region       *r;             /* may be NULL */
+       struct swm_region       *old_r;         /* may be NULL */
+       struct ws_win_list      winlist;        /* list of windows in ws */
+       struct ws_win_list      unmanagedlist;  /* list of dead windows in ws */
+       char                    stacker[10];    /* display stacker and layout */
+
+       /* stacker state */
+       struct {
+                               int horizontal_msize;
+                               int horizontal_mwin;
+                               int horizontal_stacks;
+                               int horizontal_flip;
+                               int vertical_msize;
+                               int vertical_mwin;
+                               int vertical_stacks;
+                               int vertical_flip;
+       } l_state;
+};
+
+enum   { SWM_S_COLOR_BAR, SWM_S_COLOR_BAR_BORDER, SWM_S_COLOR_BAR_FONT,
+         SWM_S_COLOR_FOCUS, SWM_S_COLOR_UNFOCUS, SWM_S_COLOR_MAX };
+
+/* physical screen mapping */
+#define SWM_WS_MAX             (10)
+struct swm_screen {
+       int                     idx;    /* screen index */
+       struct swm_region_list  rl;     /* list of regions on this screen */
+       struct swm_region_list  orl;    /* list of old regions */
+       Window                  root;
+       struct workspace        ws[SWM_WS_MAX];
+
+       /* colors */
+       struct {
+               unsigned long   color;
+               char            *name;
+       } c[SWM_S_COLOR_MAX];
+
+       GC                      bar_gc;
+};
+struct swm_screen      *screens;
+int                    num_screens;
+
+/* args to functions */
+union arg {
+       int                     id;
+#define SWM_ARG_ID_FOCUSNEXT   (0)
+#define SWM_ARG_ID_FOCUSPREV   (1)
+#define SWM_ARG_ID_FOCUSMAIN   (2)
+#define SWM_ARG_ID_FOCUSCUR    (4)
+#define SWM_ARG_ID_SWAPNEXT    (10)
+#define SWM_ARG_ID_SWAPPREV    (11)
+#define SWM_ARG_ID_SWAPMAIN    (12)
+#define SWM_ARG_ID_MOVELAST    (13)
+#define SWM_ARG_ID_MASTERSHRINK (20)
+#define SWM_ARG_ID_MASTERGROW  (21)
+#define SWM_ARG_ID_MASTERADD   (22)
+#define SWM_ARG_ID_MASTERDEL   (23)
+#define SWM_ARG_ID_FLIPLAYOUT  (24)
+#define SWM_ARG_ID_STACKRESET  (30)
+#define SWM_ARG_ID_STACKINIT   (31)
+#define SWM_ARG_ID_CYCLEWS_UP  (40)
+#define SWM_ARG_ID_CYCLEWS_DOWN        (41)
+#define SWM_ARG_ID_CYCLESC_UP  (42)
+#define SWM_ARG_ID_CYCLESC_DOWN        (43)
+#define SWM_ARG_ID_CYCLEWS_UP_ALL      (44)
+#define SWM_ARG_ID_CYCLEWS_DOWN_ALL    (45)
+#define SWM_ARG_ID_STACKINC    (50)
+#define SWM_ARG_ID_STACKDEC    (51)
+#define SWM_ARG_ID_SS_ALL      (60)
+#define SWM_ARG_ID_SS_WINDOW   (61)
+#define SWM_ARG_ID_DONTCENTER  (70)
+#define SWM_ARG_ID_CENTER      (71)
+#define SWM_ARG_ID_KILLWINDOW  (80)
+#define SWM_ARG_ID_DELETEWINDOW        (81)
+#define SWM_ARG_ID_WIDTHGROW   (90)
+#define SWM_ARG_ID_WIDTHSHRINK (91)
+#define SWM_ARG_ID_HEIGHTGROW  (92)
+#define SWM_ARG_ID_HEIGHTSHRINK        (93)
+#define SWM_ARG_ID_MOVEUP      (100)
+#define SWM_ARG_ID_MOVEDOWN    (101)
+#define SWM_ARG_ID_MOVELEFT    (102)
+#define SWM_ARG_ID_MOVERIGHT   (103)
+       char                    **argv;
+};
+
+void   focus(struct swm_region *, union arg *);
+void   focus_magic(struct ws_win *);
+
+/* quirks */
+struct quirk {
+       TAILQ_ENTRY(quirk)      entry;
+       char                    *class;
+       char                    *name;
+       unsigned long           quirk;
+#define SWM_Q_FLOAT            (1<<0)  /* float this window */
+#define SWM_Q_TRANSSZ          (1<<1)  /* transiend window size too small */
+#define SWM_Q_ANYWHERE         (1<<2)  /* don't position this window */
+#define SWM_Q_XTERM_FONTADJ    (1<<3)  /* adjust xterm fonts when resizing */
+#define SWM_Q_FULLSCREEN       (1<<4)  /* remove border */
+#define SWM_Q_FOCUSPREV                (1<<5)  /* focus on caller */
+};
+TAILQ_HEAD(quirk_list, quirk);
+struct quirk_list              quirks = TAILQ_HEAD_INITIALIZER(quirks);
+
+/*
+ * Supported EWMH hints should be added to
+ * both the enum and the ewmh array
+ */
+enum { _NET_ACTIVE_WINDOW, _NET_MOVERESIZE_WINDOW, _NET_CLOSE_WINDOW,
+    _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DOCK,
+    _NET_WM_WINDOW_TYPE_TOOLBAR, _NET_WM_WINDOW_TYPE_UTILITY,
+    _NET_WM_WINDOW_TYPE_SPLASH, _NET_WM_WINDOW_TYPE_DIALOG,
+    _NET_WM_WINDOW_TYPE_NORMAL, _NET_WM_STATE,
+    _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT,
+    _NET_WM_STATE_SKIP_TASKBAR, _NET_WM_STATE_SKIP_PAGER,
+    _NET_WM_STATE_HIDDEN, _NET_WM_STATE_ABOVE, _SWM_WM_STATE_MANUAL,
+    _NET_WM_STATE_FULLSCREEN, _NET_WM_ALLOWED_ACTIONS, _NET_WM_ACTION_MOVE,
+    _NET_WM_ACTION_RESIZE, _NET_WM_ACTION_FULLSCREEN, _NET_WM_ACTION_CLOSE,
+    SWM_EWMH_HINT_MAX };
+
+struct ewmh_hint {
+       char    *name;
+       Atom     atom;
+} ewmh[SWM_EWMH_HINT_MAX] =    {
+    /* must be in same order as in the enum */
+    {"_NET_ACTIVE_WINDOW", None},
+    {"_NET_MOVERESIZE_WINDOW", None},
+    {"_NET_CLOSE_WINDOW", None},
+    {"_NET_WM_WINDOW_TYPE", None},
+    {"_NET_WM_WINDOW_TYPE_DOCK", None},
+    {"_NET_WM_WINDOW_TYPE_TOOLBAR", None},
+    {"_NET_WM_WINDOW_TYPE_UTILITY", None},
+    {"_NET_WM_WINDOW_TYPE_SPLASH", None},
+    {"_NET_WM_WINDOW_TYPE_DIALOG", None},
+    {"_NET_WM_WINDOW_TYPE_NORMAL", None},
+    {"_NET_WM_STATE", None},
+    {"_NET_WM_STATE_MAXIMIZED_HORZ", None},
+    {"_NET_WM_STATE_MAXIMIZED_VERT", None},
+    {"_NET_WM_STATE_SKIP_TASKBAR", None},
+    {"_NET_WM_STATE_SKIP_PAGER", None},
+    {"_NET_WM_STATE_HIDDEN", None},
+    {"_NET_WM_STATE_ABOVE", None},
+    {"_SWM_WM_STATE_MANUAL", None},
+    {"_NET_WM_STATE_FULLSCREEN", None},
+    {"_NET_WM_ALLOWED_ACTIONS", None},
+    {"_NET_WM_ACTION_MOVE", None},
+    {"_NET_WM_ACTION_RESIZE", None},
+    {"_NET_WM_ACTION_FULLSCREEN", None},
+    {"_NET_WM_ACTION_CLOSE", None},
+};
+
+void            store_float_geom(struct ws_win *, struct swm_region *);
+int             floating_toggle_win(struct ws_win *);
+void            spawn_select(struct swm_region *, union arg *, char *, int *);
+unsigned char  *get_win_name(Window);
+
+int
+get_property(Window id, Atom atom, long count, Atom type, unsigned long *nitems,
+    unsigned long *nbytes, unsigned char **data)
+{
+       int                     format, status;
+       unsigned long           *nbytes_ret, *nitems_ret;
+       unsigned long           nbytes_tmp, nitems_tmp;
+       Atom                    real;
+
+       nbytes_ret = nbytes != NULL ? nbytes : &nbytes_tmp;
+       nitems_ret = nitems != NULL ? nitems : &nitems_tmp;
+
+       status = XGetWindowProperty(display, id, atom, 0L, count, False, type,
+           &real, &format, nitems_ret, nbytes_ret, data);
+
+       if (status != Success)
+               return False;
+       if (real != type)
+               return False;
+
+       return True;
+}
+
+void
+update_iconic(struct ws_win *win, int newv)
+{
+       int32_t v = newv;
+       Atom iprop;
+
+       win->iconic = newv;
+
+       iprop = XInternAtom(display, "_SWM_ICONIC", False);
+       if (!iprop)
+               return;
+       if (newv)
+               XChangeProperty(display, win->id, iprop, XA_INTEGER, 32,
+                   PropModeReplace, (unsigned char *)&v, 1);
+       else
+               XDeleteProperty(display, win->id, iprop);
+}
+
+int
+get_iconic(struct ws_win *win)
+{
+       int32_t v = 0;
+       int retfmt, status;
+       Atom iprop, rettype;
+       unsigned long nitems, extra;
+       unsigned char *prop = NULL;
+
+       iprop = XInternAtom(display, "_SWM_ICONIC", False);
+       if (!iprop)
+               goto out;
+       status = XGetWindowProperty(display, win->id, iprop, 0L, 1L,
+           False, XA_INTEGER, &rettype, &retfmt, &nitems, &extra, &prop);
+       if (status != Success)
+               goto out;
+       if (rettype != XA_INTEGER || retfmt != 32)
+               goto out;
+       if (nitems != 1)
+               goto out;
+       v = *((int32_t *)prop);
+
+out:
+       if (prop != NULL)
+               XFree(prop);
+       return (v);
+}
+
+void
+setup_ewmh(void)
+{
+       int                     i,j;
+       Atom                    sup_list;
+
+       sup_list = XInternAtom(display, "_NET_SUPPORTED", False);
+
+       for (i = 0; i < LENGTH(ewmh); i++)
+               ewmh[i].atom = XInternAtom(display, ewmh[i].name, False);
+
+       for (i = 0; i < ScreenCount(display); i++) {
+               /* Support check window will be created by workaround(). */
+
+               /* Report supported atoms */
+               XDeleteProperty(display, screens[i].root, sup_list);
+               for (j = 0; j < LENGTH(ewmh); j++)
+                       XChangeProperty(display, screens[i].root,
+                           sup_list, XA_ATOM, 32,
+                           PropModeAppend, (unsigned char *)&ewmh[j].atom,1);
+       }
+}
+
+void
+teardown_ewmh(void)
+{
+       int                     i, success;
+       unsigned char           *data = NULL;
+       unsigned long           n;
+       Atom                    sup_check, sup_list;
+       Window                  id;
+
+       sup_check = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
+       sup_list = XInternAtom(display, "_NET_SUPPORTED", False);
+
+       for (i = 0; i < ScreenCount(display); i++) {
+               /* Get the support check window and destroy it */
+               success = get_property(screens[i].root, sup_check, 1, XA_WINDOW,
+                   &n, NULL, &data);
+
+               if (success) {
+                       id = data[0];
+                       XDestroyWindow(display, id);
+                       XDeleteProperty(display, screens[i].root, sup_check);
+                       XDeleteProperty(display, screens[i].root, sup_list);
+               }
+
+               XFree(data);
+       }
+}
+
+void
+ewmh_autoquirk(struct ws_win *win)
+{
+       int                     success, i;
+       unsigned long           *data = NULL, n;
+       Atom                    type;
+
+       success = get_property(win->id, ewmh[_NET_WM_WINDOW_TYPE].atom, (~0L),
+           XA_ATOM, &n, NULL, (void *)&data);
+
+       if (!success) {
+               XFree(data);
+               return;
+       }
+
+       for (i = 0; i < n; i++) {
+               type = data[i];
+               if (type == ewmh[_NET_WM_WINDOW_TYPE_NORMAL].atom)
+                       break;
+               if (type == ewmh[_NET_WM_WINDOW_TYPE_DOCK].atom ||
+                   type == ewmh[_NET_WM_WINDOW_TYPE_TOOLBAR].atom ||
+                   type == ewmh[_NET_WM_WINDOW_TYPE_UTILITY].atom) {
+                       win->floating = 1;
+                       win->quirks = SWM_Q_FLOAT | SWM_Q_ANYWHERE;
+                       break;
+               }
+               if (type == ewmh[_NET_WM_WINDOW_TYPE_SPLASH].atom ||
+                   type == ewmh[_NET_WM_WINDOW_TYPE_DIALOG].atom) {
+                       win->floating = 1;
+                       win->quirks = SWM_Q_FLOAT;
+                       break;
+               }
+       }
+
+       XFree(data);
+}
+
+#define SWM_EWMH_ACTION_COUNT_MAX      (6)
+#define EWMH_F_FULLSCREEN              (1<<0)
+#define EWMH_F_ABOVE                   (1<<1)
+#define EWMH_F_HIDDEN                  (1<<2)
+#define EWMH_F_SKIP_PAGER              (1<<3)
+#define EWMH_F_SKIP_TASKBAR            (1<<4)
+#define SWM_F_MANUAL                   (1<<5)
+
+int
+ewmh_set_win_fullscreen(struct ws_win *win, int fs)
+{
+       struct swm_geometry     rg;
+
+       if (!win->ws->r)
+               return 0;
+
+       if (!win->floating)
+               return 0;
+
+       DNPRINTF(SWM_D_MISC, "ewmh_set_win_fullscreen: window: 0x%lx, "
+           "fullscreen %s\n", win->id, YESNO(fs));
+
+       rg = win->ws->r->g;
+
+       if (fs) {
+               store_float_geom(win, win->ws->r);
+
+               win->g = rg;
+       } else {
+               if (win->g_floatvalid) {
+                       /* refloat at last floating relative position */
+                       X(win) = win->g_float.x - win->rg_float.x + rg.x;
+                       Y(win) = win->g_float.y - win->rg_float.y + rg.y;
+                       WIDTH(win) = win->g_float.w;
+                       HEIGHT(win) = win->g_float.h;
+               }
+       }
+
+       return 1;
+}
+
+void
+ewmh_update_actions(struct ws_win *win)
+{
+       Atom                    actions[SWM_EWMH_ACTION_COUNT_MAX];
+       int                     n = 0;
+
+       if (win == NULL)
+               return;
+
+       actions[n++] = ewmh[_NET_WM_ACTION_CLOSE].atom;
+
+       if (win->floating) {
+               actions[n++] = ewmh[_NET_WM_ACTION_MOVE].atom;
+               actions[n++] = ewmh[_NET_WM_ACTION_RESIZE].atom;
+       }
+
+       XChangeProperty(display, win->id, ewmh[_NET_WM_ALLOWED_ACTIONS].atom,
+           XA_ATOM, 32, PropModeReplace, (unsigned char *)actions, n);
+}
+
+#define _NET_WM_STATE_REMOVE   0    /* remove/unset property */
+#define _NET_WM_STATE_ADD      1    /* add/set property */
+#define _NET_WM_STATE_TOGGLE   2    /* toggle property */
+
+void
+ewmh_update_win_state(struct ws_win *win, long state, long action)
+{
+       unsigned int            mask = 0;
+       unsigned int            changed = 0;
+       unsigned int            orig_flags;
+
+       if (win == NULL)
+               return;
+
+       if (state == ewmh[_NET_WM_STATE_FULLSCREEN].atom)
+               mask = EWMH_F_FULLSCREEN;
+       if (state == ewmh[_NET_WM_STATE_ABOVE].atom)
+               mask = EWMH_F_ABOVE;
+       if (state == ewmh[_SWM_WM_STATE_MANUAL].atom)
+               mask = SWM_F_MANUAL;
+       if (state == ewmh[_NET_WM_STATE_SKIP_PAGER].atom)
+               mask = EWMH_F_SKIP_PAGER;
+       if (state == ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom)
+               mask = EWMH_F_SKIP_TASKBAR;
+
+
+       orig_flags = win->ewmh_flags;
+
+       switch (action) {
+       case _NET_WM_STATE_REMOVE:
+               win->ewmh_flags &= ~mask;
+               break;
+       case _NET_WM_STATE_ADD:
+               win->ewmh_flags |= mask;
+               break;
+       case _NET_WM_STATE_TOGGLE:
+               win->ewmh_flags ^= mask;
+               break;
+       }
+
+       changed = (win->ewmh_flags & mask) ^ (orig_flags & mask) ? 1 : 0;
+
+       if (state == ewmh[_NET_WM_STATE_ABOVE].atom)
+               if (changed)
+                       if (!floating_toggle_win(win))
+                               win->ewmh_flags = orig_flags; /* revert */
+       if (state == ewmh[_SWM_WM_STATE_MANUAL].atom)
+               if (changed)
+                       win->manual = (win->ewmh_flags & SWM_F_MANUAL) != 0;
+       if (state == ewmh[_NET_WM_STATE_FULLSCREEN].atom)
+               if (changed)
+                       if (!ewmh_set_win_fullscreen(win,
+                           win->ewmh_flags & EWMH_F_FULLSCREEN))
+                               win->ewmh_flags = orig_flags; /* revert */
+
+       XDeleteProperty(display, win->id, ewmh[_NET_WM_STATE].atom);
+
+       if (win->ewmh_flags & EWMH_F_FULLSCREEN)
+               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
+                   XA_ATOM, 32, PropModeAppend,
+                   (unsigned char *)&ewmh[_NET_WM_STATE_FULLSCREEN].atom, 1);
+       if (win->ewmh_flags & EWMH_F_SKIP_PAGER)
+               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
+                   XA_ATOM, 32, PropModeAppend,
+                   (unsigned char *)&ewmh[_NET_WM_STATE_SKIP_PAGER].atom, 1);
+       if (win->ewmh_flags & EWMH_F_SKIP_TASKBAR)
+               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
+                   XA_ATOM, 32, PropModeAppend,
+                   (unsigned char *)&ewmh[_NET_WM_STATE_SKIP_TASKBAR].atom, 1);
+       if (win->ewmh_flags & EWMH_F_ABOVE)
+               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
+                   XA_ATOM, 32, PropModeAppend,
+                   (unsigned char *)&ewmh[_NET_WM_STATE_ABOVE].atom, 1);
+       if (win->ewmh_flags & SWM_F_MANUAL)
+               XChangeProperty(display, win->id, ewmh[_NET_WM_STATE].atom,
+                   XA_ATOM, 32, PropModeAppend,
+                   (unsigned char *)&ewmh[_SWM_WM_STATE_MANUAL].atom, 1);
+}
+
+void
+ewmh_get_win_state(struct ws_win *win)
+{
+       int                     success, i;
+       unsigned long           n;
+       Atom                    *states;
+
+       if (win == NULL)
+               return;
+
+       win->ewmh_flags = 0;
+       if (win->floating)
+               win->ewmh_flags |= EWMH_F_ABOVE;
+       if (win->manual)
+               win->ewmh_flags |= SWM_F_MANUAL;
+
+       success = get_property(win->id, ewmh[_NET_WM_STATE].atom,
+           (~0L), XA_ATOM, &n, NULL, (void *)&states);
+
+       if (!success)
+               return;
+
+       for (i = 0; i < n; i++)
+               ewmh_update_win_state(win, states[i], _NET_WM_STATE_ADD);
+
+       XFree(states);
+}
+
+/* events */
+#ifdef SWM_DEBUG
+char *
+geteventname(XEvent *e)
+{
+       char                    *name = NULL;
+
+       switch (e->type) {
+       case KeyPress:
+               name = "KeyPress";
+               break;
+       case KeyRelease:
+               name = "KeyRelease";
+               break;
+       case ButtonPress:
+               name = "ButtonPress";
+               break;
+       case ButtonRelease:
+               name = "ButtonRelease";
+               break;
+       case MotionNotify:
+               name = "MotionNotify";
+               break;
+       case EnterNotify:
+               name = "EnterNotify";
+               break;
+       case LeaveNotify:
+               name = "LeaveNotify";
+               break;
+       case FocusIn:
+               name = "FocusIn";
+               break;
+       case FocusOut:
+               name = "FocusOut";
+               break;
+       case KeymapNotify:
+               name = "KeymapNotify";
+               break;
+       case Expose:
+               name = "Expose";
+               break;
+       case GraphicsExpose:
+               name = "GraphicsExpose";
+               break;
+       case NoExpose:
+               name = "NoExpose";
+               break;
+       case VisibilityNotify:
+               name = "VisibilityNotify";
+               break;
+       case CreateNotify:
+               name = "CreateNotify";
+               break;
+       case DestroyNotify:
+               name = "DestroyNotify";
+               break;
+       case UnmapNotify:
+               name = "UnmapNotify";
+               break;
+       case MapNotify:
+               name = "MapNotify";
+               break;
+       case MapRequest:
+               name = "MapRequest";
+               break;
+       case ReparentNotify:
+               name = "ReparentNotify";
+               break;
+       case ConfigureNotify:
+               name = "ConfigureNotify";
+               break;
+       case ConfigureRequest:
+               name = "ConfigureRequest";
+               break;
+       case GravityNotify:
+               name = "GravityNotify";
+               break;
+       case ResizeRequest:
+               name = "ResizeRequest";
+               break;
+       case CirculateNotify:
+               name = "CirculateNotify";
+               break;
+       case CirculateRequest:
+               name = "CirculateRequest";
+               break;
+       case PropertyNotify:
+               name = "PropertyNotify";
+               break;
+       case SelectionClear:
+               name = "SelectionClear";
+               break;
+       case SelectionRequest:
+               name = "SelectionRequest";
+               break;
+       case SelectionNotify:
+               name = "SelectionNotify";
+               break;
+       case ColormapNotify:
+               name = "ColormapNotify";
+               break;
+       case ClientMessage:
+               name = "ClientMessage";
+               break;
+       case MappingNotify:
+               name = "MappingNotify";
+               break;
+       default:
+               name = "Unknown";
+       }
+
+       return name;
+}
+
+char *
+xrandr_geteventname(XEvent *e)
+{
+       char                    *name = NULL;
+
+       switch(e->type - xrandr_eventbase) {
+       case RRScreenChangeNotify:
+               name = "RRScreenChangeNotify";
+               break;
+       default:
+               name = "Unknown";
+       }
+
+       return name;
+}
+
+void
+dumpwins(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *win;
+       unsigned int            state;
+       XWindowAttributes       wa;
+
+       if (r->ws == NULL) {
+               warnx("dumpwins: invalid workspace");
+               return;
+       }
+
+       warnx("=== managed window list ws %02d ===", r->ws->idx);
+
+       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
+               state = getstate(win->id);
+               if (!XGetWindowAttributes(display, win->id, &wa))
+                       warnx("window: 0x%lx, failed XGetWindowAttributes",
+                           win->id);
+               warnx("window: 0x%lx, map_state: %d, state: %d, "
+                   "transient: 0x%lx", win->id, wa.map_state, state,
+                   win->transient);
+       }
+
+       warnx("===== unmanaged window list =====");
+       TAILQ_FOREACH(win, &r->ws->unmanagedlist, entry) {
+               state = getstate(win->id);
+               if (!XGetWindowAttributes(display, win->id, &wa))
+                       warnx("window: 0x%lx, failed XGetWindowAttributes",
+                           win->id);
+               warnx("window: 0x%lx, map_state: %d, state: %d, "
+                   "transient: 0x%lx", win->id, wa.map_state, state,
+                   win->transient);
+       }
+
+       warnx("=================================");
+}
+#else
+void
+dumpwins(struct swm_region *r, union arg *args)
+{
+}
+#endif /* SWM_DEBUG */
+
+void                   expose(XEvent *);
+void                   keypress(XEvent *);
+void                   buttonpress(XEvent *);
+void                   configurerequest(XEvent *);
+void                   configurenotify(XEvent *);
+void                   destroynotify(XEvent *);
+void                   enternotify(XEvent *);
+void                   focusevent(XEvent *);
+void                   mapnotify(XEvent *);
+void                   mappingnotify(XEvent *);
+void                   maprequest(XEvent *);
+void                   propertynotify(XEvent *);
+void                   unmapnotify(XEvent *);
+void                   visibilitynotify(XEvent *);
+void                   clientmessage(XEvent *);
+
+void                   (*handler[LASTEvent])(XEvent *) = {
+                               [Expose] = expose,
+                               [KeyPress] = keypress,
+                               [ButtonPress] = buttonpress,
+                               [ConfigureRequest] = configurerequest,
+                               [ConfigureNotify] = configurenotify,
+                               [DestroyNotify] = destroynotify,
+                               [EnterNotify] = enternotify,
+                               [FocusIn] = focusevent,
+                               [FocusOut] = focusevent,
+                               [MapNotify] = mapnotify,
+                               [MappingNotify] = mappingnotify,
+                               [MapRequest] = maprequest,
+                               [PropertyNotify] = propertynotify,
+                               [UnmapNotify] = unmapnotify,
+                               [VisibilityNotify] = visibilitynotify,
+                               [ClientMessage] = clientmessage,
+};
+
+void
+sighdlr(int sig)
+{
+       int                     saved_errno, status;
+       pid_t                   pid;
+
+       saved_errno = errno;
+
+       switch (sig) {
+       case SIGCHLD:
+               while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) != 0) {
+                       if (pid == -1) {
+                               if (errno == EINTR)
+                                       continue;
+#ifdef SWM_DEBUG
+                               if (errno != ECHILD)
+                                       warn("sighdlr: waitpid");
+#endif /* SWM_DEBUG */
+                               break;
+                       }
+                       if (pid == searchpid)
+                               search_resp = 1;
+
+#ifdef SWM_DEBUG
+                       if (WIFEXITED(status)) {
+                               if (WEXITSTATUS(status) != 0)
+                                       warnx("sighdlr: child exit status: %d",
+                                           WEXITSTATUS(status));
+                       } else
+                               warnx("sighdlr: child is terminated "
+                                   "abnormally");
+#endif /* SWM_DEBUG */
+               }
+               break;
+
+       case SIGHUP:
+               restart_wm = 1;
+               break;
+       case SIGINT:
+       case SIGTERM:
+       case SIGQUIT:
+               running = 0;
+               break;
+       }
+
+       errno = saved_errno;
+}
+
+struct pid_e *
+find_pid(long pid)
+{
+       struct pid_e            *p = NULL;
+
+       DNPRINTF(SWM_D_MISC, "find_pid: %lu\n", pid);
+
+       if (pid == 0)
+               return (NULL);
+
+       TAILQ_FOREACH(p, &pidlist, entry) {
+               if (p->pid == pid)
+                       return (p);
+       }
+
+       return (NULL);
+}
+
+unsigned long
+name_to_color(char *colorname)
+{
+       Colormap                cmap;
+       Status                  status;
+       XColor                  screen_def, exact_def;
+       unsigned long           result = 0;
+       char                    cname[32] = "#";
+
+       cmap = DefaultColormap(display, screens[0].idx);
+       status = XAllocNamedColor(display, cmap, colorname,
+           &screen_def, &exact_def);
+       if (!status) {
+               strlcat(cname, colorname + 2, sizeof cname - 1);
+               status = XAllocNamedColor(display, cmap, cname, &screen_def,
+                   &exact_def);
+       }
+       if (status)
+               result = screen_def.pixel;
+       else
+               warnx("color '%s' not found", colorname);
+
+       return (result);
+}
+
+void
+setscreencolor(char *val, int i, int c)
+{
+       if (i > 0 && i <= ScreenCount(display)) {
+               screens[i - 1].c[c].color = name_to_color(val);
+               free(screens[i - 1].c[c].name);
+               if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
+                       err(1, "strdup");
+       } else if (i == -1) {
+               for (i = 0; i < ScreenCount(display); i++) {
+                       screens[i].c[c].color = name_to_color(val);
+                       free(screens[i].c[c].name);
+                       if ((screens[i].c[c].name = strdup(val)) == NULL)
+                               err(1, "strdup");
+               }
+       } else
+               errx(1, "invalid screen index: %d out of bounds (maximum %d)",
+                   i, ScreenCount(display));
+}
+
+void
+fancy_stacker(struct workspace *ws)
+{
+       strlcpy(ws->stacker, "[   ]", sizeof ws->stacker);
+       if (ws->cur_layout->l_stack == vertical_stack)
+               snprintf(ws->stacker, sizeof ws->stacker,
+                   ws->l_state.vertical_flip ? "[%d>%d]" : "[%d|%d]",
+                   ws->l_state.vertical_mwin, ws->l_state.vertical_stacks);
+       if (ws->cur_layout->l_stack == horizontal_stack)
+               snprintf(ws->stacker, sizeof ws->stacker,
+                   ws->l_state.horizontal_flip ? "[%dv%d]" : "[%d-%d]",
+                   ws->l_state.horizontal_mwin, ws->l_state.horizontal_stacks);
+}
+
+void
+plain_stacker(struct workspace *ws)
+{
+       strlcpy(ws->stacker, "[ ]", sizeof ws->stacker);
+       if (ws->cur_layout->l_stack == vertical_stack)
+               strlcpy(ws->stacker, ws->l_state.vertical_flip ? "[>]" : "[|]",
+                   sizeof ws->stacker);
+       if (ws->cur_layout->l_stack == horizontal_stack)
+               strlcpy(ws->stacker, ws->l_state.horizontal_flip ? "[v]" : "[-]",
+                   sizeof ws->stacker);
+}
+
+void
+custom_region(char *val)
+{
+       unsigned int                    sidx, x, y, w, h;
+
+       if (sscanf(val, "screen[%u]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5)
+               errx(1, "invalid custom region, "
+                   "should be 'screen[<n>]:<n>x<n>+<n>+<n>");
+       if (sidx < 1 || sidx > ScreenCount(display))
+               errx(1, "invalid screen index: %d out of bounds (maximum %d)",
+                   sidx, ScreenCount(display));
+       sidx--;
+
+       if (w < 1 || h < 1)
+               errx(1, "region %ux%u+%u+%u too small", w, h, x, y);
+
+       if (x > DisplayWidth(display, sidx) ||
+           y > DisplayHeight(display, sidx) ||
+           w + x > DisplayWidth(display, sidx) ||
+           h + y > DisplayHeight(display, sidx)) {
+               warnx("ignoring region %ux%u+%u+%u - not within screen "
+                   "boundaries (%ux%u)", w, h, x, y,
+                   DisplayWidth(display, sidx), DisplayHeight(display, sidx));
+               return;
+       }
+
+       new_region(&screens[sidx], x, y, w, h);
+}
+
+void
+socket_setnonblock(int fd)
+{
+       int                     flags;
+
+       if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+               err(1, "fcntl F_GETFL");
+       flags |= O_NONBLOCK;
+       if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
+               err(1, "fcntl F_SETFL");
+}
+
+void
+bar_print(struct swm_region *r, char *s)
+{
+       int                     x = 0;
+       size_t                  len;
+       XRectangle              ibox, lbox;
+
+       XClearWindow(display, r->bar_window);
+
+       len = strlen(s);
+       XmbTextExtents(bar_fs, s, len, &ibox, &lbox);
+
+       switch (bar_justify) {
+       case SWM_BAR_JUSTIFY_LEFT:
+               x = SWM_BAR_OFFSET;
+               break;
+       case SWM_BAR_JUSTIFY_CENTER:
+               x = (WIDTH(r) - lbox.width) / 2;
+               break;
+       case SWM_BAR_JUSTIFY_RIGHT:
+               x = WIDTH(r) - lbox.width - SWM_BAR_OFFSET;
+               break;
+       }
+
+       if (x < SWM_BAR_OFFSET)
+               x = SWM_BAR_OFFSET;
+
+       DRAWSTRING(display, r->bar_window, bar_fs, r->s->bar_gc,
+           x, (bar_fs_extents->max_logical_extent.height - lbox.height) / 2 -
+           lbox.y, s, len);
+}
+
+void
+bar_extra_stop(void)
+{
+       if (bar_pipe[0]) {
+               close(bar_pipe[0]);
+               bzero(bar_pipe, sizeof bar_pipe);
+       }
+       if (bar_pid) {
+               kill(bar_pid, SIGTERM);
+               bar_pid = 0;
+       }
+       strlcpy((char *)bar_ext, "", sizeof bar_ext);
+       bar_extra = 0;
+}
+
+void
+bar_class_name(char *s, ssize_t sz, struct ws_win *cur_focus)
+{
+       int                     do_class, do_name;
+       Status                  status;
+       XClassHint              *xch = NULL;
+
+       if ((title_name_enabled == 1 || title_class_enabled == 1) &&
+           cur_focus != NULL) {
+               if ((xch = XAllocClassHint()) == NULL)
+                       goto out;
+               status = XGetClassHint(display, cur_focus->id, xch);
+               if (status == BadWindow || status == BadAlloc)
+                       goto out;
+               do_class = (title_class_enabled && xch->res_class != NULL);
+               do_name = (title_name_enabled && xch->res_name != NULL);
+               if (do_class)
+                       strlcat(s, xch->res_class, sz);
+               if (do_class && do_name)
+                       strlcat(s, ":", sz);
+               if (do_name)
+                       strlcat(s, xch->res_name, sz);
+               strlcat(s, "    ", sz);
+       }
+out:
+       if (xch) {
+               XFree(xch->res_name);
+               XFree(xch->res_class);
+               XFree(xch);
+       }
+}
+
+void
+bar_window_name(char *s, ssize_t sz, struct ws_win *cur_focus)
+{
+       unsigned char           *title;
+
+       if (window_name_enabled && cur_focus != NULL) {
+               title = get_win_name(cur_focus->id);
+               if (title != NULL) {
+                       DNPRINTF(SWM_D_BAR, "bar_window_name: title: %s\n",
+                           title);
+
+                       if (cur_focus->floating)
+                               strlcat(s, "(f) ", sz);
+                       strlcat(s, (char *)title, sz);
+                       strlcat(s, " ", sz);
+                       XFree(title);
+               }
+       }
+}
+
+int            urgent[SWM_WS_MAX];
+void
+bar_urgent(char *s, ssize_t sz)
+{
+       XWMHints                *wmh = NULL;
+       struct ws_win           *win;
+       int                     i, j;
+       char                    b[8];
+
+       if (urgent_enabled == 0)
+               return;
+
+       for (i = 0; i < SWM_WS_MAX; i++)
+               urgent[i] = 0;
+
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
+                               wmh = XGetWMHints(display, win->id);
+                               if (wmh == NULL)
+                                       continue;
+
+                               if (wmh->flags & XUrgencyHint)
+                                       urgent[j] = 1;
+                               XFree(wmh);
+                       }
+
+       strlcat(s, "* ", sz);
+       for (i = 0; i < SWM_WS_MAX; i++) {
+               if (urgent[i])
+                       snprintf(b, sizeof b, "%d ", i + 1);
+               else
+                       snprintf(b, sizeof b, "- ");
+               strlcat(s, b, sz);
+       }
+       strlcat(s, "*    ", sz);
+}
+
+void
+bar_update(void)
+{
+       time_t                  tmt;
+       struct tm               tm;
+       struct swm_region       *r;
+       int                     i, x;
+       size_t                  len;
+       char                    ws[SWM_BAR_MAX];
+       char                    s[SWM_BAR_MAX];
+       unsigned char           cn[SWM_BAR_MAX];
+       char                    loc[SWM_BAR_MAX];
+       char                    *b, *stack = "";
+
+       if (bar_enabled == 0)
+               return;
+       if (bar_extra && bar_extra_running) {
+               /* ignore short reads; it'll correct itself */
+               while ((b = fgetln(stdin, &len)) != NULL)
+                       if (b && b[len - 1] == '\n') {
+                               b[len - 1] = '\0';
+                               strlcpy((char *)bar_ext, b, sizeof bar_ext);
+                       }
+               if (b == NULL && errno != EAGAIN) {
+                       warn("bar_update: bar_extra failed");
+                       bar_extra_stop();
+               }
+       } else
+               strlcpy((char *)bar_ext, "", sizeof bar_ext);
+
+       if (clock_enabled == 0)
+               strlcpy(s, "", sizeof s);
+       else {
+               time(&tmt);
+               localtime_r(&tmt, &tm);
+               len = strftime(s, sizeof s, clock_format, &tm);
+               s[len] = '\0';
+               strlcat(s, "    ", sizeof s);
+       }
+
+       for (i = 0; i < ScreenCount(display); i++) {
+               x = 1;
+               TAILQ_FOREACH(r, &screens[i].rl, entry) {
+                       strlcpy((char *)cn, "", sizeof cn);
+                       strlcpy(ws, "", sizeof ws);
+                       if (r && r->ws) {
+                               bar_urgent((char *)cn, sizeof cn);
+                               bar_class_name((char *)cn, sizeof cn,
+                                   r->ws->focus);
+                               bar_window_name((char *)cn, sizeof cn,
+                                   r->ws->focus);
+                               if (r->ws->name)
+                                       snprintf(ws, sizeof ws, "<%s>",
+                                           r->ws->name);
+                       }
+                       if (stack_enabled)
+                               stack = r->ws->stacker;
+
+                       snprintf(loc, sizeof loc, "%d:%d %s %s   %s%s    %s    "
+                           "%s", x++, r->ws->idx + 1, stack, ws, s, cn,
+                           bar_ext, bar_vertext);
+                       bar_print(r, loc);
+               }
+       }
+       alarm(bar_delay);
+}
+
+void
+bar_check_opts(void)
+{
+       if (title_class_enabled || title_name_enabled || window_name_enabled)
+               bar_update();
+}
+
+void
+bar_signal(int sig)
+{
+       bar_alarm = 1;
+}
+
+void
+bar_toggle(struct swm_region *r, union arg *args)
+{
+       struct swm_region       *tmpr;
+       int                     i, sc = ScreenCount(display);
+
+       DNPRINTF(SWM_D_BAR, "bar_toggle\n");
+
+       if (bar_enabled)
+               for (i = 0; i < sc; i++)
+                       TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
+                               XUnmapWindow(display, tmpr->bar_window);
+       else
+               for (i = 0; i < sc; i++)
+                       TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
+                               XMapRaised(display, tmpr->bar_window);
+
+       bar_enabled = !bar_enabled;
+
+       stack();
+       /* must be after stack */
+       bar_update();
+}
+
+void
+bar_refresh(void)
+{
+       XSetWindowAttributes    wa;
+       struct swm_region       *r;
+       int                     i;
+
+       /* do this here because the conf file is in memory */
+       if (bar_extra && bar_extra_running == 0 && bar_argv[0]) {
+               /* launch external status app */
+               bar_extra_running = 1;
+               if (pipe(bar_pipe) == -1)
+                       err(1, "pipe error");
+               socket_setnonblock(bar_pipe[0]);
+               socket_setnonblock(bar_pipe[1]); /* XXX hmmm, really? */
+               if (dup2(bar_pipe[0], 0) == -1)
+                       err(1, "dup2");
+               if (dup2(bar_pipe[1], 1) == -1)
+                       err(1, "dup2");
+               if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+                       err(1, "could not disable SIGPIPE");
+               switch (bar_pid = fork()) {
+               case -1:
+                       err(1, "cannot fork");
+                       break;
+               case 0: /* child */
+                       close(bar_pipe[0]);
+                       execvp(bar_argv[0], bar_argv);
+                       err(1, "%s external app failed", bar_argv[0]);
+                       break;
+               default: /* parent */
+                       close(bar_pipe[1]);
+                       break;
+               }
+       }
+
+       bzero(&wa, sizeof wa);
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry) {
+                       wa.border_pixel =
+                           screens[i].c[SWM_S_COLOR_BAR_BORDER].color;
+                       wa.background_pixel =
+                           screens[i].c[SWM_S_COLOR_BAR].color;
+                       XChangeWindowAttributes(display, r->bar_window,
+                           CWBackPixel | CWBorderPixel, &wa);
+               }
+       bar_update();
+}
+
+void
+bar_setup(struct swm_region *r)
+{
+       char                    *default_string;
+       char                    **missing_charsets;
+       int                     num_missing_charsets = 0;
+       int                     i, x, y;
+
+       if (bar_fs) {
+               XFreeFontSet(display, bar_fs);
+               bar_fs = NULL;
+       }
+
+
+       DNPRINTF(SWM_D_BAR, "bar_setup: loading bar_fonts: %s\n", bar_fonts);
+
+       bar_fs = XCreateFontSet(display, bar_fonts, &missing_charsets,
+           &num_missing_charsets, &default_string);
+
+       if (num_missing_charsets > 0) {
+               warnx("Unable to load charset(s):");
+
+               for (i = 0; i < num_missing_charsets; ++i)
+                       warnx("%s", missing_charsets[i]);
+
+               XFreeStringList(missing_charsets);
+
+               if (strcmp(default_string, ""))
+                       warnx("Glyphs from those sets will be replaced "
+                           "by '%s'.", default_string);
+               else
+                       warnx("Glyphs from those sets won't be drawn.");
+       }
+
+       if (bar_fs == NULL)
+               errx(1, "Error creating font set structure.");
+
+       bar_fs_extents = XExtentsOfFontSet(bar_fs);
+
+       bar_height = bar_fs_extents->max_logical_extent.height +
+           2 * bar_border_width;
+
+       if (bar_height < 1)
+               bar_height = 1;
+
+       x = X(r);
+       y = bar_at_bottom ? (Y(r) + HEIGHT(r) - bar_height) : Y(r);
+
+       r->bar_window = XCreateSimpleWindow(display,
+           r->s->root, x, y, WIDTH(r) - 2 * bar_border_width,
+           bar_height - 2 * bar_border_width,
+           bar_border_width, r->s->c[SWM_S_COLOR_BAR_BORDER].color,
+           r->s->c[SWM_S_COLOR_BAR].color);
+       XSelectInput(display, r->bar_window, VisibilityChangeMask);
+       if (bar_enabled)
+               XMapRaised(display, r->bar_window);
+       DNPRINTF(SWM_D_BAR, "bar_setup: bar_window: 0x%lx\n", r->bar_window);
+
+       if (signal(SIGALRM, bar_signal) == SIG_ERR)
+               err(1, "could not install bar_signal");
+       bar_refresh();
+}
+
+void
+drain_enter_notify(void)
+{
+       int                     i = 0;
+       XEvent                  cne;
+
+       while (XCheckMaskEvent(display, EnterWindowMask, &cne))
+               i++;
+
+       DNPRINTF(SWM_D_MISC, "drain_enter_notify: drained: %d\n", i);
+}
+
+void
+set_win_state(struct ws_win *win, long state)
+{
+       long                    data[] = {state, None};
+
+       DNPRINTF(SWM_D_EVENT, "set_win_state: window: 0x%lx\n", win->id);
+
+       if (win == NULL)
+               return;
+
+       XChangeProperty(display, win->id, astate, astate, 32, PropModeReplace,
+           (unsigned char *)data, 2);
+}
+
+long
+getstate(Window w)
+{
+       long                    result = -1;
+       unsigned char           *p = NULL;
+       unsigned long           n;
+
+       if (!get_property(w, astate, 2L, astate, &n, NULL, &p))
+               return (-1);
+       if (n != 0)
+               result = *((long *)p);
+       XFree(p);
+       return (result);
+}
+
+void
+version(struct swm_region *r, union arg *args)
+{
+       bar_version = !bar_version;
+       if (bar_version)
+               snprintf(bar_vertext, sizeof bar_vertext,
+                   "Version: %s Build: %s", SPECTRWM_VERSION, buildstr);
+       else
+               strlcpy(bar_vertext, "", sizeof bar_vertext);
+       bar_update();
+}
+
+void
+client_msg(struct ws_win *win, Atom a)
+{
+       XClientMessageEvent     cm;
+
+       if (win == NULL)
+               return;
+
+       bzero(&cm, sizeof cm);
+       cm.type = ClientMessage;
+       cm.window = win->id;
+       cm.message_type = aprot;
+       cm.format = 32;
+       cm.data.l[0] = a;
+       cm.data.l[1] = CurrentTime;
+       XSendEvent(display, win->id, False, 0L, (XEvent *)&cm);
+}
+
+/* synthetic response to a ConfigureRequest when not making a change */
+void
+config_win(struct ws_win *win, XConfigureRequestEvent  *ev)
+{
+       XConfigureEvent         ce;
+
+       if (win == NULL)
+               return;
+
+       /* send notification of unchanged state. */
+       ce.type = ConfigureNotify;
+       ce.x = X(win);
+       ce.y = Y(win);
+       ce.width = WIDTH(win);
+       ce.height = HEIGHT(win);
+       ce.override_redirect = False;
+
+       if (ev == NULL) {
+               /* EWMH */
+               ce.display = display;
+               ce.event = win->id;
+               ce.window = win->id;
+               ce.border_width = border_width;
+               ce.above = None;
+       } else {
+               /* normal */
+               ce.display = ev->display;
+               ce.event = ev->window;
+               ce.window = ev->window;
+
+               /* make response appear more WM_SIZE_HINTS-compliant */
+               if (win->sh_mask)
+                       DNPRINTF(SWM_D_MISC, "config_win: hints: window: 0x%lx,"
+                           " sh_mask: %ld, min: %d x %d, max: %d x %d, inc: "
+                           "%d x %d\n", win->id, win->sh_mask, SH_MIN_W(win),
+                           SH_MIN_H(win), SH_MAX_W(win), SH_MAX_H(win),
+                           SH_INC_W(win), SH_INC_H(win));
+
+               /* min size */
+               if (SH_MIN(win)) {
+                       /* the hint may be set... to 0! */
+                       if (SH_MIN_W(win) > 0 && ce.width < SH_MIN_W(win))
+                               ce.width = SH_MIN_W(win);
+                       if (SH_MIN_H(win) > 0 && ce.height < SH_MIN_H(win))
+                               ce.height = SH_MIN_H(win);
+               }
+
+               /* max size */
+               if (SH_MAX(win)) {
+                       /* may also be advertized as 0 */
+                       if (SH_MAX_W(win) > 0 && ce.width > SH_MAX_W(win))
+                               ce.width = SH_MAX_W(win);
+                       if (SH_MAX_H(win) > 0 && ce.height > SH_MAX_H(win))
+                               ce.height = SH_MAX_H(win);
+               }
+
+               /* resize increment. */
+               if (SH_INC(win)) {
+                       if (SH_INC_W(win) > 1 && ce.width > SH_INC_W(win))
+                               ce.width -= (ce.width - SH_MIN_W(win)) %
+                                   SH_INC_W(win);
+                       if (SH_INC_H(win) > 1 && ce.height > SH_INC_H(win))
+                               ce.height -= (ce.height - SH_MIN_H(win)) %
+                                   SH_INC_H(win);
+               }
+
+               /* adjust x and y for requested border_width. */
+               ce.x += border_width - ev->border_width;
+               ce.y += border_width - ev->border_width;
+               ce.border_width = ev->border_width;
+               ce.above = ev->above;
+       }
+
+       DNPRINTF(SWM_D_MISC, "config_win: ewmh: %s, window: 0x%lx, (x,y) w x h: "
+           "(%d,%d) %d x %d, border: %d\n", YESNO(ev == NULL), win->id, ce.x,
+           ce.y, ce.width, ce.height, ce.border_width);
+
+       XSendEvent(display, win->id, False, StructureNotifyMask, (XEvent *)&ce);
+}
+
+int
+count_win(struct workspace *ws, int count_transient)
+{
+       struct ws_win           *win;
+       int                     count = 0;
+
+       TAILQ_FOREACH(win, &ws->winlist, entry) {
+               if (count_transient == 0 && win->floating)
+                       continue;
+               if (count_transient == 0 && win->transient)
+                       continue;
+               if (win->iconic)
+                       continue;
+               count++;
+       }
+       DNPRINTF(SWM_D_MISC, "count_win: %d\n", count);
+
+       return (count);
+}
+
+void
+quit(struct swm_region *r, union arg *args)
+{
+       DNPRINTF(SWM_D_MISC, "quit\n");
+       running = 0;
+}
+
+void
+unmap_window(struct ws_win *win)
+{
+       if (win == NULL)
+               return;
+
+       /* don't unmap again */
+       if (getstate(win->id) == IconicState)
+               return;
+
+       set_win_state(win, IconicState);
+
+       XUnmapWindow(display, win->id);
+       XSetWindowBorder(display, win->id,
+           win->s->c[SWM_S_COLOR_UNFOCUS].color);
+}
+
+void
+unmap_all(void)
+{
+       struct ws_win           *win;
+       int                     i, j;
+
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               unmap_window(win);
+}
+
+void
+fake_keypress(struct ws_win *win, int keysym, int modifiers)
+{
+       XKeyEvent event;
+
+       if (win == NULL)
+               return;
+
+       event.display = display;        /* Ignored, but what the hell */
+       event.window = win->id;
+       event.root = win->s->root;
+       event.subwindow = None;
+       event.time = CurrentTime;
+       event.x = X(win);
+       event.y = Y(win);
+       event.x_root = 1;
+       event.y_root = 1;
+       event.same_screen = True;
+       event.keycode = XKeysymToKeycode(display, keysym);
+       event.state = modifiers;
+
+       event.type = KeyPress;
+       XSendEvent(event.display, event.window, True,
+           KeyPressMask, (XEvent *)&event);
+
+       event.type = KeyRelease;
+       XSendEvent(event.display, event.window, True,
+           KeyPressMask, (XEvent *)&event);
+
+}
+
+void
+restart(struct swm_region *r, union arg *args)
+{
+       DNPRINTF(SWM_D_MISC, "restart: %s\n", start_argv[0]);
+
+       /* disable alarm because the following code may not be interrupted */
+       alarm(0);
+       if (signal(SIGALRM, SIG_IGN) == SIG_ERR)
+               err(1, "can't disable alarm");
+
+       bar_extra_stop();
+       bar_extra = 1;
+       unmap_all();
+       XCloseDisplay(display);
+       execvp(start_argv[0], start_argv);
+       warn("execvp failed");
+       quit(NULL, NULL);
+}
+
+struct swm_region *
+root_to_region(Window root)
+{
+       struct swm_region       *r = NULL;
+       Window                  rr, cr;
+       int                     i, x, y, wx, wy;
+       unsigned int            mask;
+
+       for (i = 0; i < ScreenCount(display); i++)
+               if (screens[i].root == root)
+                       break;
+
+       if (XQueryPointer(display, screens[i].root,
+           &rr, &cr, &x, &y, &wx, &wy, &mask) != False) {
+               /* choose a region based on pointer location */
+               TAILQ_FOREACH(r, &screens[i].rl, entry)
+                       if (x >= X(r) && x <= X(r) + WIDTH(r) &&
+                           y >= Y(r) && y <= Y(r) + HEIGHT(r))
+                               break;
+       }
+
+       if (r == NULL)
+               r = TAILQ_FIRST(&screens[i].rl);
+
+       return (r);
+}
+
+struct ws_win *
+find_unmanaged_window(Window id)
+{
+       struct ws_win           *win;
+       int                     i, j;
+
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].unmanagedlist,
+                           entry)
+                               if (id == win->id)
+                                       return (win);
+       return (NULL);
+}
+
+struct ws_win *
+find_window(Window id)
+{
+       struct ws_win           *win;
+       Window                  wrr, wpr, *wcr = NULL;
+       int                     i, j;
+       unsigned int            nc;
+
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               if (id == win->id)
+                                       return (win);
+
+       /* if we were looking for the parent return that window instead */
+       if (XQueryTree(display, id, &wrr, &wpr, &wcr, &nc) == 0)
+               return (NULL);
+       if (wcr)
+               XFree(wcr);
+
+       /* ignore not found and root */
+       if (wpr == 0 || wrr == wpr)
+               return (NULL);
+
+       /* look for parent */
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               if (wpr == win->id)
+                                       return (win);
+
+       return (NULL);
+}
+
+void
+spawn(int ws_idx, union arg *args, int close_fd)
+{
+       int                     fd;
+       char                    *ret = NULL;
+
+       DNPRINTF(SWM_D_MISC, "spawn: %s\n", args->argv[0]);
+
+       if (display)
+               close(ConnectionNumber(display));
+
+       setenv("LD_PRELOAD", SWM_LIB, 1);
+
+       if (asprintf(&ret, "%d", ws_idx) == -1) {
+               warn("spawn: asprintf SWM_WS");
+               _exit(1);
+       }
+       setenv("_SWM_WS", ret, 1);
+       free(ret);
+       ret = NULL;
+
+       if (asprintf(&ret, "%d", getpid()) == -1) {
+               warn("spawn: asprintf _SWM_PID");
+               _exit(1);
+       }
+       setenv("_SWM_PID", ret, 1);
+       free(ret);
+       ret = NULL;
+
+       if (setsid() == -1) {
+               warn("spawn: setsid");
+               _exit(1);
+       }
+
+       if (close_fd) {
+               /*
+                * close stdin and stdout to prevent interaction between apps
+                * and the baraction script
+                * leave stderr open to record errors
+               */
+               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) {
+                       warn("spawn: open");
+                       _exit(1);
+               }
+               dup2(fd, STDIN_FILENO);
+               dup2(fd, STDOUT_FILENO);
+               if (fd > 2)
+                       close(fd);
+       }
+
+       execvp(args->argv[0], args->argv);
+
+       warn("spawn: execvp");
+       _exit(1);
+}
+
+void
+spawnterm(struct swm_region *r, union arg *args)
+{
+       DNPRINTF(SWM_D_MISC, "spawnterm\n");
+
+       if (fork() == 0) {
+               if (term_width)
+                       setenv("_SWM_XTERM_FONTADJ", "", 1);
+               spawn(r->ws->idx, args, 1);
+       }
+}
+
+void
+kill_refs(struct ws_win *win)
+{
+       int                     i, x;
+       struct swm_region       *r;
+       struct workspace        *ws;
+
+       if (win == NULL)
+               return;
+
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry)
+                       for (x = 0; x < SWM_WS_MAX; x++) {
+                               ws = &r->s->ws[x];
+                               if (win == ws->focus)
+                                       ws->focus = NULL;
+                               if (win == ws->focus_prev)
+                                       ws->focus_prev = NULL;
+                       }
+}
+
+int
+validate_win(struct ws_win *testwin)
+{
+       struct ws_win           *win;
+       struct workspace        *ws;
+       struct swm_region       *r;
+       int                     i, x;
+
+       if (testwin == NULL)
+               return (0);
+
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry)
+                       for (x = 0; x < SWM_WS_MAX; x++) {
+                               ws = &r->s->ws[x];
+                               TAILQ_FOREACH(win, &ws->winlist, entry)
+                                       if (win == testwin)
+                                               return (0);
+                       }
+       return (1);
+}
+
+int
+validate_ws(struct workspace *testws)
+{
+       struct swm_region       *r;
+       struct workspace        *ws;
+       int                     i, x;
+
+       /* validate all ws */
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry)
+                       for (x = 0; x < SWM_WS_MAX; x++) {
+                               ws = &r->s->ws[x];
+                               if (ws == testws)
+                                       return (0);
+                       }
+       return (1);
+}
+
+void
+unfocus_win(struct ws_win *win)
+{
+       XEvent                  cne;
+       Window                  none = None;
+
+       DNPRINTF(SWM_D_FOCUS, "unfocus_win: window: 0x%lx\n", WINID(win));
+
+       if (win == NULL)
+               return;
+       if (win->ws == NULL)
+               return;
+
+       if (validate_ws(win->ws))
+               return; /* XXX this gets hit with thunderbird, needs fixing */
+
+       if (win->ws->r == NULL)
+               return;
+
+       if (validate_win(win)) {
+               kill_refs(win);
+               return;
+       }
+
+       if (win->ws->focus == win) {
+               win->ws->focus = NULL;
+               win->ws->focus_prev = win;
+       }
+
+       if (validate_win(win->ws->focus)) {
+               kill_refs(win->ws->focus);
+               win->ws->focus = NULL;
+       }
+       if (validate_win(win->ws->focus_prev)) {
+               kill_refs(win->ws->focus_prev);
+               win->ws->focus_prev = NULL;
+       }
+
+       /* drain all previous unfocus events */
+       while (XCheckTypedEvent(display, FocusOut, &cne) == True)
+               ;
+
+       grabbuttons(win, 0);
+       XSetWindowBorder(display, win->id,
+           win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
+
+       XChangeProperty(display, win->s->root,
+           ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
+           PropModeReplace, (unsigned char *)&none,1);
+}
+
+void
+unfocus_all(void)
+{
+       struct ws_win           *win;
+       int                     i, j;
+
+       DNPRINTF(SWM_D_FOCUS, "unfocus_all\n");
+
+       for (i = 0; i < ScreenCount(display); i++)
+               for (j = 0; j < SWM_WS_MAX; j++)
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               unfocus_win(win);
+}
+
+void
+focus_win(struct ws_win *win)
+{
+       XEvent                  cne;
+       Window                  cur_focus;
+       int                     rr;
+       struct ws_win           *cfw = NULL;
+
+
+       DNPRINTF(SWM_D_FOCUS, "focus_win: window: 0x%lx\n", WINID(win));
+
+       if (win == NULL)
+               return;
+       if (win->ws == NULL)
+               return;
+
+       if (validate_ws(win->ws))
+               return; /* XXX this gets hit with thunderbird, needs fixing */
+
+       if (validate_win(win)) {
+               kill_refs(win);
+               return;
+       }
+
+       if (validate_win(win)) {
+               kill_refs(win);
+               return;
+       }
+
+       XGetInputFocus(display, &cur_focus, &rr);
+       if ((cfw = find_window(cur_focus)) != NULL)
+               unfocus_win(cfw);
+       else {
+               /* use larger hammer since the window was killed somehow */
+               TAILQ_FOREACH(cfw, &win->ws->winlist, entry)
+                       if (cfw->ws && cfw->ws->r && cfw->ws->r->s)
+                               XSetWindowBorder(display, cfw->id,
+                                   cfw->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
+       }
+
+       win->ws->focus = win;
+
+       if (win->ws->r != NULL) {
+               /* drain all previous focus events */
+               while (XCheckTypedEvent(display, FocusIn, &cne) == True)
+                       ;
+
+               if (win->java == 0)
+                       XSetInputFocus(display, win->id,
+                           RevertToParent, CurrentTime);
+               grabbuttons(win, 1);
+               XSetWindowBorder(display, win->id,
+                   win->ws->r->s->c[SWM_S_COLOR_FOCUS].color);
+               if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
+                   win->ws->always_raise)
+                       XMapRaised(display, win->id);
+
+               XChangeProperty(display, win->s->root,
+                   ewmh[_NET_ACTIVE_WINDOW].atom, XA_WINDOW, 32,
+                   PropModeReplace, (unsigned char *)&win->id,1);
+       }
+
+       bar_check_opts();
+}
+
+void
+switchws(struct swm_region *r, union arg *args)
+{
+       int                     wsid = args->id, unmap_old = 0;
+       struct swm_region       *this_r, *other_r;
+       struct ws_win           *win;
+       struct workspace        *new_ws, *old_ws;
+       union arg               a;
+
+       if (!(r && r->s))
+               return;
+
+       this_r = r;
+       old_ws = this_r->ws;
+       new_ws = &this_r->s->ws[wsid];
+
+       DNPRINTF(SWM_D_WS, "switchws: screen[%d]:%dx%d+%d+%d: %d -> %d\n",
+           r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), old_ws->idx, wsid);
+
+       if (new_ws == NULL || old_ws == NULL)
+               return;
+       if (new_ws == old_ws)
+               return;
+
+       other_r = new_ws->r;
+       if (other_r == NULL) {
+               /* the other workspace is hidden, hide this one */
+               old_ws->r = NULL;
+               unmap_old = 1;
+       } else {
+               /* the other ws is visible in another region, exchange them */
+               other_r->ws_prior = new_ws;
+               other_r->ws = old_ws;
+               old_ws->r = other_r;
+       }
+       this_r->ws_prior = old_ws;
+       this_r->ws = new_ws;
+       new_ws->r = this_r;
+
+       /* this is needed so that we can click on a window after a restart */
+       unfocus_all();
+
+       stack();
+       a.id = SWM_ARG_ID_FOCUSCUR;
+       focus(new_ws->r, &a);
+
+       bar_update();
+
+       /* unmap old windows */
+       if (unmap_old)
+               TAILQ_FOREACH(win, &old_ws->winlist, entry)
+                       unmap_window(win);
+
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+}
+
+void
+cyclews(struct swm_region *r, union arg *args)
+{
+       union                   arg a;
+       struct swm_screen       *s = r->s;
+       int                     cycle_all = 0;
+
+       DNPRINTF(SWM_D_WS, "cyclews: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
+           args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
+
+       a.id = r->ws->idx;
+       do {
+               switch (args->id) {
+               case SWM_ARG_ID_CYCLEWS_UP_ALL:
+                       cycle_all = 1;
+                       /* FALLTHROUGH */
+               case SWM_ARG_ID_CYCLEWS_UP:
+                       if (a.id < SWM_WS_MAX - 1)
+                               a.id++;
+                       else
+                               a.id = 0;
+                       break;
+               case SWM_ARG_ID_CYCLEWS_DOWN_ALL:
+                       cycle_all = 1;
+                       /* FALLTHROUGH */
+               case SWM_ARG_ID_CYCLEWS_DOWN:
+                       if (a.id > 0)
+                               a.id--;
+                       else
+                               a.id = SWM_WS_MAX - 1;
+                       break;
+               default:
+                       return;
+               };
+
+               if (!cycle_all &&
+                   (cycle_empty == 0 && TAILQ_EMPTY(&s->ws[a.id].winlist)))
+                       continue;
+               if (cycle_visible == 0 && s->ws[a.id].r != NULL)
+                       continue;
+
+               switchws(r, &a);
+       } while (a.id != r->ws->idx);
+}
+
+void
+priorws(struct swm_region *r, union arg *args)
+{
+       union arg               a;
+
+       DNPRINTF(SWM_D_WS, "priorws: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
+           args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
+
+       if (r->ws_prior == NULL)
+               return;
+
+       a.id = r->ws_prior->idx;
+       switchws(r, &a);
+}
+
+void
+cyclescr(struct swm_region *r, union arg *args)
+{
+       struct swm_region       *rr = NULL;
+       union arg               a;
+       int                     i, x, y;
+
+       /* do nothing if we don't have more than one screen */
+       if (!(ScreenCount(display) > 1 || outputs > 1))
+               return;
+
+       i = r->s->idx;
+       switch (args->id) {
+       case SWM_ARG_ID_CYCLESC_UP:
+               rr = TAILQ_NEXT(r, entry);
+               if (rr == NULL)
+                       rr = TAILQ_FIRST(&screens[i].rl);
+               break;
+       case SWM_ARG_ID_CYCLESC_DOWN:
+               rr = TAILQ_PREV(r, swm_region_list, entry);
+               if (rr == NULL)
+                       rr = TAILQ_LAST(&screens[i].rl, swm_region_list);
+               break;
+       default:
+               return;
+       };
+       if (rr == NULL)
+               return;
+
+       /* move mouse to region */
+       x = X(rr) + 1;
+       y = Y(rr) + 1 + (bar_enabled ? bar_height : 0);
+       XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, x, y);
+
+       a.id = SWM_ARG_ID_FOCUSCUR;
+       focus(rr, &a);
+
+       if (rr->ws->focus) {
+               /* move to focus window */
+               x = X(rr->ws->focus) + 1;
+               y = Y(rr->ws->focus) + 1;
+               XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, x, y);
+       }
+}
+
+void
+sort_windows(struct ws_win_list *wl)
+{
+       struct ws_win           *win, *parent, *nxt;
+
+       if (wl == NULL)
+               return;
+
+       for (win = TAILQ_FIRST(wl); win != TAILQ_END(wl); win = nxt) {
+               nxt = TAILQ_NEXT(win, entry);
+               if (win->transient) {
+                       parent = find_window(win->transient);
+                       if (parent == NULL) {
+                               warnx("not possible bug");
+                               continue;
+                       }
+                       TAILQ_REMOVE(wl, win, entry);
+                       TAILQ_INSERT_AFTER(wl, parent, win, entry);
+               }
+       }
+
+}
+
+void
+swapwin(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *target, *source;
+       struct ws_win           *cur_focus;
+       struct ws_win_list      *wl;
+
+
+       DNPRINTF(SWM_D_WS, "swapwin: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
+           args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
+
+       cur_focus = r->ws->focus;
+       if (cur_focus == NULL)
+               return;
+
+       source = cur_focus;
+       wl = &source->ws->winlist;
+
+       switch (args->id) {
+       case SWM_ARG_ID_SWAPPREV:
+               if (source->transient)
+                       source = find_window(source->transient);
+               target = TAILQ_PREV(source, ws_win_list, entry);
+               if (target && target->transient)
+                       target = find_window(target->transient);
+               TAILQ_REMOVE(wl, source, entry);
+               if (target == NULL)
+                       TAILQ_INSERT_TAIL(wl, source, entry);
+               else
+                       TAILQ_INSERT_BEFORE(target, source, entry);
+               break;
+       case SWM_ARG_ID_SWAPNEXT:
+               target = TAILQ_NEXT(source, entry);
+               /* move the parent and let the sort handle the move */
+               if (source->transient)
+                       source = find_window(source->transient);
+               TAILQ_REMOVE(wl, source, entry);
+               if (target == NULL)
+                       TAILQ_INSERT_HEAD(wl, source, entry);
+               else
+                       TAILQ_INSERT_AFTER(wl, target, source, entry);
+               break;
+       case SWM_ARG_ID_SWAPMAIN:
+               target = TAILQ_FIRST(wl);
+               if (target == source) {
+                       if (source->ws->focus_prev != NULL &&
+                           source->ws->focus_prev != target)
+
+                               source = source->ws->focus_prev;
+                       else
+                               return;
+               }
+               if (target == NULL || source == NULL)
+                       return;
+               source->ws->focus_prev = target;
+               TAILQ_REMOVE(wl, target, entry);
+               TAILQ_INSERT_BEFORE(source, target, entry);
+               TAILQ_REMOVE(wl, source, entry);
+               TAILQ_INSERT_HEAD(wl, source, entry);
+               break;
+       case SWM_ARG_ID_MOVELAST:
+               TAILQ_REMOVE(wl, source, entry);
+               TAILQ_INSERT_TAIL(wl, source, entry);
+               break;
+       default:
+               DNPRINTF(SWM_D_MOVE, "swapwin: invalid id: %d\n", args->id);
+               return;
+       }
+
+       sort_windows(wl);
+
+       stack();
+}
+
+void
+focus_prev(struct ws_win *win)
+{
+       struct ws_win           *winfocus = NULL;
+       struct ws_win           *cur_focus = NULL;
+       struct ws_win_list      *wl = NULL;
+       struct workspace        *ws = NULL;
+
+       DNPRINTF(SWM_D_FOCUS, "focus_prev: window: 0x%lx\n", WINID(win));
+
+       if (!(win && win->ws))
+               return;
+
+       ws = win->ws;
+       wl = &ws->winlist;
+       cur_focus = ws->focus;
+
+       /* pickle, just focus on whatever */
+       if (cur_focus == NULL) {
+               /* use prev_focus if valid */
+               if (ws->focus_prev && ws->focus_prev != cur_focus &&
+                   find_window(WINID(ws->focus_prev)))
+                       winfocus = ws->focus_prev;
+               if (winfocus == NULL)
+                       winfocus = TAILQ_FIRST(wl);
+               goto done;
+       }
+
+       /* if transient focus on parent */
+       if (cur_focus->transient) {
+               winfocus = find_window(cur_focus->transient);
+               goto done;
+       }
+
+       /* if in max_stack try harder */
+       if ((win->quirks & SWM_Q_FOCUSPREV) ||
+           (ws->cur_layout->flags & SWM_L_FOCUSPREV)) {
+               if (cur_focus != ws->focus_prev)
+                       winfocus = ws->focus_prev;
+               else if (cur_focus != ws->focus)
+                       winfocus = ws->focus;
+               else
+                       winfocus = TAILQ_PREV(win, ws_win_list, entry);
+               if (winfocus)
+                       goto done;
+       }
+
+       if (cur_focus == win)
+               winfocus = TAILQ_PREV(win, ws_win_list, entry);
+       if (winfocus == NULL)
+               winfocus = TAILQ_LAST(wl, ws_win_list);
+       if (winfocus == NULL || winfocus == win)
+               winfocus = TAILQ_NEXT(cur_focus, entry);
+
+done:
+       focus_magic(winfocus);
+}
+
+void
+focus(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *winfocus = NULL, *head;
+       struct ws_win           *cur_focus = NULL;
+       struct ws_win_list      *wl = NULL;
+       struct workspace        *ws = NULL;
+       int                     all_iconics;
+
+       if (!(r && r->ws))
+               return;
+
+       DNPRINTF(SWM_D_FOCUS, "focus: id: %d\n", args->id);
+
+       /* treat FOCUS_CUR special */
+       if (args->id == SWM_ARG_ID_FOCUSCUR) {
+               if (r->ws->focus && r->ws->focus->iconic == 0)
+                       winfocus = r->ws->focus;
+               else if (r->ws->focus_prev && r->ws->focus_prev->iconic == 0)
+                       winfocus = r->ws->focus_prev;
+               else
+                       TAILQ_FOREACH(winfocus, &r->ws->winlist, entry)
+                               if (winfocus->iconic == 0)
+                                       break;
+
+               focus_magic(winfocus);
+               return;
+       }
+
+       if ((cur_focus = r->ws->focus) == NULL)
+               return;
+       ws = r->ws;
+       wl = &ws->winlist;
+       if (TAILQ_EMPTY(wl))
+               return;
+       /* make sure there is at least one uniconified window */
+       all_iconics = 1;
+       TAILQ_FOREACH(winfocus, wl, entry)
+               if (winfocus->iconic == 0) {
+                       all_iconics = 0;
+                       break;
+               }
+       if (all_iconics)
+               return;
+
+       switch (args->id) {
+       case SWM_ARG_ID_FOCUSPREV:
+               head = TAILQ_PREV(cur_focus, ws_win_list, entry);
+               if (head == NULL)
+                       head = TAILQ_LAST(wl, ws_win_list);
+               winfocus = head;
+               if (WINID(winfocus) == cur_focus->transient) {
+                       head = TAILQ_PREV(winfocus, ws_win_list, entry);
+                       if (head == NULL)
+                               head = TAILQ_LAST(wl, ws_win_list);
+                       winfocus = head;
+               }
+
+               /* skip iconics */
+               if (winfocus && winfocus->iconic) {
+                       while (winfocus != cur_focus) {
+                               if (winfocus == NULL)
+                                       winfocus = TAILQ_LAST(wl, ws_win_list);
+                               if (winfocus->iconic == 0)
+                                       break;
+                               winfocus = TAILQ_PREV(winfocus, ws_win_list,
+                                   entry);
+                       }
+               }
+               break;
+
+       case SWM_ARG_ID_FOCUSNEXT:
+               head = TAILQ_NEXT(cur_focus, entry);
+               if (head == NULL)
+                       head = TAILQ_FIRST(wl);
+               winfocus = head;
+
+               /* skip iconics */
+               if (winfocus && winfocus->iconic) {
+                       while (winfocus != cur_focus) {
+                               if (winfocus == NULL)
+                                       winfocus = TAILQ_FIRST(wl);
+                               if (winfocus->iconic == 0)
+                                       break;
+                               winfocus = TAILQ_NEXT(winfocus, entry);
+                       }
+               }
+               break;
+
+       case SWM_ARG_ID_FOCUSMAIN:
+               winfocus = TAILQ_FIRST(wl);
+               if (winfocus == cur_focus)
+                       winfocus = cur_focus->ws->focus_prev;
+               break;
+
+       default:
+               return;
+       }
+
+       focus_magic(winfocus);
+}
+
+void
+cycle_layout(struct swm_region *r, union arg *args)
+{
+       struct workspace        *ws = r->ws;
+       union arg               a;
+
+       DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx);
+
+       ws->cur_layout++;
+       if (ws->cur_layout->l_stack == NULL)
+               ws->cur_layout = &layouts[0];
+
+       stack();
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+       a.id = SWM_ARG_ID_FOCUSCUR;
+       focus(r, &a);
+       bar_update();
+}
+
+void
+stack_config(struct swm_region *r, union arg *args)
+{
+       struct workspace        *ws = r->ws;
+
+       DNPRINTF(SWM_D_STACK, "stack_config: id: %d workspace: %d\n",
+           args->id, ws->idx);
+
+       if (ws->cur_layout->l_config != NULL)
+               ws->cur_layout->l_config(ws, args->id);
+
+       if (args->id != SWM_ARG_ID_STACKINIT)
+               stack();
+       bar_update();
+}
+
+void
+stack(void) {
+       struct swm_geometry     g;
+       struct swm_region       *r;
+       int                     i;
+#ifdef SWM_DEBUG
+       int j;
+#endif
+
+       DNPRINTF(SWM_D_STACK, "stack: begin\n");
+
+       for (i = 0; i < ScreenCount(display); i++) {
+#ifdef SWM_DEBUG
+               j = 0;
+#endif
+               TAILQ_FOREACH(r, &screens[i].rl, entry) {
+                       DNPRINTF(SWM_D_STACK, "stack: workspace: %d "
+                           "(screen: %d, region: %d)\n", r->ws->idx, i, j++);
+
+                       /* start with screen geometry, adjust for bar */
+                       g = r->g;
+                       g.w -= 2 * border_width;
+                       g.h -= 2 * border_width;
+                       if (bar_enabled) {
+                               if (!bar_at_bottom)
+                                       g.y += bar_height;
+                               g.h -= bar_height;
+                       }
+                       r->ws->cur_layout->l_stack(r->ws, &g);
+                       r->ws->cur_layout->l_string(r->ws);
+                       /* save r so we can track region changes */
+                       r->ws->old_r = r;
+               }
+       }
+       if (font_adjusted)
+               font_adjusted--;
+
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+
+       DNPRINTF(SWM_D_STACK, "stack: end\n");
+}
+
+void
+store_float_geom(struct ws_win *win, struct swm_region *r)
+{
+       /* retain window geom and region geom */
+       win->g_float = win->g;
+       win->rg_float = r->g;
+       win->g_floatvalid = 1;
+}
+
+void
+stack_floater(struct ws_win *win, struct swm_region *r)
+{
+       unsigned int            mask;
+       XWindowChanges          wc;
+
+       if (win == NULL)
+               return;
+
+       bzero(&wc, sizeof wc);
+       mask = CWX | CWY | CWBorderWidth | CWWidth | CWHeight;
+
+       /*
+        * to allow windows to change their size (e.g. mplayer fs) only retrieve
+        * geom on ws switches or return from max mode
+        */
+       if (win->floatmaxed || (r != r->ws->old_r && win->g_floatvalid
+           && !(win->ewmh_flags & EWMH_F_FULLSCREEN))) {
+               /*
+                * use stored g and rg to set relative position and size
+                * as in old region or before max stack mode
+                */
+               X(win) = win->g_float.x - win->rg_float.x + X(r);
+               Y(win) = win->g_float.y - win->rg_float.y + Y(r);
+               WIDTH(win) = win->g_float.w;
+               HEIGHT(win) = win->g_float.h;
+               win->g_floatvalid = 0;
+       }
+
+       win->floatmaxed = 0;
+
+       if ((win->quirks & SWM_Q_FULLSCREEN) && (WIDTH(win) >= WIDTH(r)) &&
+           (HEIGHT(win) >= HEIGHT(r)))
+               wc.border_width = 0;
+       else
+               wc.border_width = border_width;
+       if (win->transient && (win->quirks & SWM_Q_TRANSSZ)) {
+               WIDTH(win) = (double)WIDTH(r) * dialog_ratio;
+               HEIGHT(win) = (double)HEIGHT(r) * dialog_ratio;
+       }
+
+       if (!win->manual) {
+               /*
+                * floaters and transients are auto-centred unless moved
+                * or resized
+                */
+               X(win) = X(r) + (WIDTH(r) - WIDTH(win)) /  2 - wc.border_width;
+               Y(win) = Y(r) + (HEIGHT(r) - HEIGHT(win)) / 2 - wc.border_width;
+       }
+
+       /* win can be outside r if new r smaller than old r */
+       /* Ensure top left corner inside r (move probs otherwise) */
+       if (X(win) < X(r) - wc.border_width)
+               X(win) = X(r) - wc.border_width;
+       if (X(win) > X(r) + WIDTH(r) - 1)
+               X(win) = (WIDTH(win) > WIDTH(r)) ? X(r) :
+                   (X(r) + WIDTH(r) - WIDTH(win) - 2 * wc.border_width);
+       if (Y(win) < Y(r) - wc.border_width)
+               Y(win) = Y(r) - wc.border_width;
+       if (Y(win) > Y(r) + HEIGHT(r) - 1)
+               Y(win) = (HEIGHT(win) > HEIGHT(r)) ? Y(r) :
+                   (Y(r) + HEIGHT(r) - HEIGHT(win) - 2 * wc.border_width);
+
+       wc.x = X(win);
+       wc.y = Y(win);
+       wc.width = WIDTH(win);
+       wc.height = HEIGHT(win);
+
+       /*
+        * Retain floater and transient geometry for correct positioning
+        * when ws changes region
+        */
+       if (!(win->ewmh_flags & EWMH_F_FULLSCREEN))
+               store_float_geom(win, r);
+
+       DNPRINTF(SWM_D_MISC, "stack_floater: window: %lu, (x,y) w x h: (%d,%d) "
+           "%d x %d\n", win->id, wc.x, wc.y, wc.width, wc.height);
+
+       XConfigureWindow(display, win->id, mask, &wc);
+}
+
+/*
+ * Send keystrokes to terminal to decrease/increase the font size as the
+ * window size changes.
+ */
+void
+adjust_font(struct ws_win *win)
+{
+       if (!(win->quirks & SWM_Q_XTERM_FONTADJ) ||
+           win->floating || win->transient)
+               return;
+
+       if (win->sh.width_inc && win->last_inc != win->sh.width_inc &&
+           WIDTH(win) / win->sh.width_inc < term_width &&
+           win->font_steps < SWM_MAX_FONT_STEPS) {
+               win->font_size_boundary[win->font_steps] =
+                   (win->sh.width_inc * term_width) + win->sh.base_width;
+               win->font_steps++;
+               font_adjusted++;
+               win->last_inc = win->sh.width_inc;
+               fake_keypress(win, XK_KP_Subtract, ShiftMask);
+       } else if (win->font_steps && win->last_inc != win->sh.width_inc &&
+           WIDTH(win) > win->font_size_boundary[win->font_steps - 1]) {
+               win->font_steps--;
+               font_adjusted++;
+               win->last_inc = win->sh.width_inc;
+               fake_keypress(win, XK_KP_Add, ShiftMask);
+       }
+}
+
+#define SWAPXY(g)      do {                            \
+       int tmp;                                        \
+       tmp = (g)->y; (g)->y = (g)->x; (g)->x = tmp;    \
+       tmp = (g)->h; (g)->h = (g)->w; (g)->w = tmp;    \
+} while (0)
+void
+stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
+{
+       XWindowChanges          wc;
+       XWindowAttributes       wa;
+       struct swm_geometry     win_g, r_g = *g;
+       struct ws_win           *win, *fs_win = 0;
+       int                     i, j, s, stacks;
+       int                     w_inc = 1, h_inc, w_base = 1, h_base;
+       int                     hrh, extra = 0, h_slice, last_h = 0;
+       int                     split, colno, winno, mwin, msize, mscale;
+       int                     remain, missing, v_slice, reconfigure;
+       unsigned int            mask;
+
+       DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d, rot: %s, "
+           "flip: %s\n", ws->idx, YESNO(rot), YESNO(flip));
+
+       winno = count_win(ws, 0);
+       if (winno == 0 && count_win(ws, 1) == 0)
+               return;
+
+       TAILQ_FOREACH(win, &ws->winlist, entry)
+               if (win->transient == 0 && win->floating == 0
+                   && win->iconic == 0)
+                       break;
+
+       if (win == NULL)
+               goto notiles;
+
+       if (rot) {
+               w_inc = win->sh.width_inc;
+               w_base = win->sh.base_width;
+               mwin = ws->l_state.horizontal_mwin;
+               mscale = ws->l_state.horizontal_msize;
+               stacks = ws->l_state.horizontal_stacks;
+               SWAPXY(&r_g);
+       } else {
+               w_inc = win->sh.height_inc;
+               w_base = win->sh.base_height;
+               mwin = ws->l_state.vertical_mwin;
+               mscale = ws->l_state.vertical_msize;
+               stacks = ws->l_state.vertical_stacks;
+       }
+       win_g = r_g;
+
+       if (stacks > winno - mwin)
+               stacks = winno - mwin;
+       if (stacks < 1)
+               stacks = 1;
+
+       h_slice = r_g.h / SWM_H_SLICE;
+       if (mwin && winno > mwin) {
+               v_slice = r_g.w / SWM_V_SLICE;
+
+               split = mwin;
+               colno = split;
+               win_g.w = v_slice * mscale;
+
+               if (w_inc > 1 && w_inc < v_slice) {
+                       /* adjust for window's requested size increment */
+                       remain = (win_g.w - w_base) % w_inc;
+                       missing = w_inc - remain;
+                       win_g.w -= remain;
+                       extra += remain;
+               }
+
+               msize = win_g.w;
+               if (flip)
+                       win_g.x += r_g.w - msize;
+       } else {
+               msize = -2;
+               colno = split = winno / stacks;
+               win_g.w = ((r_g.w - (stacks * 2 * border_width) +
+                   2 * border_width) / stacks);
+       }
+       hrh = r_g.h / colno;
+       extra = r_g.h - (colno * hrh);
+       win_g.h = hrh - 2 * border_width;
+
+       /*  stack all the tiled windows */
+       i = j = 0, s = stacks;
+       TAILQ_FOREACH(win, &ws->winlist, entry) {
+               if (win->transient != 0 || win->floating != 0)
+                       continue;
+               if (win->iconic != 0)
+                       continue;
+
+               if (win->ewmh_flags & EWMH_F_FULLSCREEN) {
+                       fs_win = win;
+                       continue;
+               }
+
+               if (split && i == split) {
+                       colno = (winno - mwin) / stacks;
+                       if (s <= (winno - mwin) % stacks)
+                               colno++;
+                       split = split + colno;
+                       hrh = (r_g.h / colno);
+                       extra = r_g.h - (colno * hrh);
+                       if (flip)
+                               win_g.x = r_g.x;
+                       else
+                               win_g.x += win_g.w + 2 * border_width;
+                       win_g.w = (r_g.w - msize -
+                           (stacks * 2 * border_width)) / stacks;
+                       if (s == 1)
+                               win_g.w += (r_g.w - msize -
+                                   (stacks * 2 * border_width)) % stacks;
+                       s--;
+                       j = 0;
+               }
+               win_g.h = hrh - 2 * border_width;
+               if (rot) {
+                       h_inc = win->sh.width_inc;
+                       h_base = win->sh.base_width;
+               } else {
+                       h_inc = win->sh.height_inc;
+                       h_base = win->sh.base_height;
+               }
+               if (j == colno - 1) {
+                       win_g.h = hrh + extra;
+               } else if (h_inc > 1 && h_inc < h_slice) {
+                       /* adjust for window's requested size increment */
+                       remain = (win_g.h - h_base) % h_inc;
+                       missing = h_inc - remain;
+
+                       if (missing <= extra || j == 0) {
+                               extra -= missing;
+                               win_g.h += missing;
+                       } else {
+                               win_g.h -= remain;
+                               extra += remain;
+                       }
+               }
+
+               if (j == 0)
+                       win_g.y = r_g.y;
+               else
+                       win_g.y += last_h + 2 * border_width;
+
+               bzero(&wc, sizeof wc);
+               if (disable_border && bar_enabled == 0 && winno == 1){
+                       wc.border_width = 0;
+                       win_g.w += 2 * border_width;
+                       win_g.h += 2 * border_width;
+               } else
+                       wc.border_width = border_width;
+               reconfigure = 0;
+               if (rot) {
+                       if (X(win) != win_g.y || Y(win) != win_g.x ||
+                           WIDTH(win) != win_g.h || HEIGHT(win) != win_g.w) {
+                               reconfigure = 1;
+                               X(win) = wc.x = win_g.y;
+                               Y(win) = wc.y = win_g.x;
+                               WIDTH(win) = wc.width = win_g.h;
+                               HEIGHT(win) = wc.height = win_g.w;
+                       }
+               } else {
+                       if (X(win) != win_g.x || Y(win) != win_g.y ||
+                           WIDTH(win) != win_g.w || HEIGHT(win) != win_g.h) {
+                               reconfigure = 1;
+                               X(win) = wc.x = win_g.x;
+                               Y(win) = wc.y = win_g.y;
+                               WIDTH(win) = wc.width = win_g.w;
+                               HEIGHT(win) = wc.height = win_g.h;
+                       }
+               }
+               if (reconfigure) {
+                       adjust_font(win);
+                       mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
+                       XConfigureWindow(display, win->id, mask, &wc);
+               }
+
+               if (XGetWindowAttributes(display, win->id, &wa))
+                       if (wa.map_state == IsUnmapped)
+                               XMapRaised(display, win->id);
+
+               last_h = win_g.h;
+               i++;
+               j++;
+       }
+
+notiles:
+       /* now, stack all the floaters and transients */
+       TAILQ_FOREACH(win, &ws->winlist, entry) {
+               if (win->transient == 0 && win->floating == 0)
+                       continue;
+               if (win->iconic == 1)
+                       continue;
+               if (win->ewmh_flags & EWMH_F_FULLSCREEN) {
+                       fs_win = win;
+                       continue;
+               }
+
+               stack_floater(win, ws->r);
+               XMapRaised(display, win->id);
+       }
+
+       if (fs_win) {
+               stack_floater(fs_win, ws->r);
+               XMapRaised(display, fs_win->id);
+       }
+}
+
+void
+vertical_config(struct workspace *ws, int id)
+{
+       DNPRINTF(SWM_D_STACK, "vertical_config: id: %d, workspace: %d\n",
+           id, ws->idx);
+
+       switch (id) {
+       case SWM_ARG_ID_STACKRESET:
+       case SWM_ARG_ID_STACKINIT:
+               ws->l_state.vertical_msize = SWM_V_SLICE / 2;
+               ws->l_state.vertical_mwin = 1;
+               ws->l_state.vertical_stacks = 1;
+               break;
+       case SWM_ARG_ID_MASTERSHRINK:
+               if (ws->l_state.vertical_msize > 1)
+                       ws->l_state.vertical_msize--;
+               break;
+       case SWM_ARG_ID_MASTERGROW:
+               if (ws->l_state.vertical_msize < SWM_V_SLICE - 1)
+                       ws->l_state.vertical_msize++;
+               break;
+       case SWM_ARG_ID_MASTERADD:
+               ws->l_state.vertical_mwin++;
+               break;
+       case SWM_ARG_ID_MASTERDEL:
+               if (ws->l_state.vertical_mwin > 0)
+                       ws->l_state.vertical_mwin--;
+               break;
+       case SWM_ARG_ID_STACKINC:
+               ws->l_state.vertical_stacks++;
+               break;
+       case SWM_ARG_ID_STACKDEC:
+               if (ws->l_state.vertical_stacks > 1)
+                       ws->l_state.vertical_stacks--;
+               break;
+       case SWM_ARG_ID_FLIPLAYOUT:
+               ws->l_state.vertical_flip = !ws->l_state.vertical_flip;
+               break;
+       default:
+               return;
+       }
+}
+
+void
+vertical_stack(struct workspace *ws, struct swm_geometry *g)
+{
+       DNPRINTF(SWM_D_STACK, "vertical_stack: workspace: %d\n", ws->idx);
+
+       stack_master(ws, g, 0, ws->l_state.vertical_flip);
+}
+
+void
+horizontal_config(struct workspace *ws, int id)
+{
+       DNPRINTF(SWM_D_STACK, "horizontal_config: workspace: %d\n", ws->idx);
+
+       switch (id) {
+       case SWM_ARG_ID_STACKRESET:
+       case SWM_ARG_ID_STACKINIT:
+               ws->l_state.horizontal_mwin = 1;
+               ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
+               ws->l_state.horizontal_stacks = 1;
+               break;
+       case SWM_ARG_ID_MASTERSHRINK:
+               if (ws->l_state.horizontal_msize > 1)
+                       ws->l_state.horizontal_msize--;
+               break;
+       case SWM_ARG_ID_MASTERGROW:
+               if (ws->l_state.horizontal_msize < SWM_H_SLICE - 1)
+                       ws->l_state.horizontal_msize++;
+               break;
+       case SWM_ARG_ID_MASTERADD:
+               ws->l_state.horizontal_mwin++;
+               break;
+       case SWM_ARG_ID_MASTERDEL:
+               if (ws->l_state.horizontal_mwin > 0)
+                       ws->l_state.horizontal_mwin--;
+               break;
+       case SWM_ARG_ID_STACKINC:
+               ws->l_state.horizontal_stacks++;
+               break;
+       case SWM_ARG_ID_STACKDEC:
+               if (ws->l_state.horizontal_stacks > 1)
+                       ws->l_state.horizontal_stacks--;
+               break;
+       case SWM_ARG_ID_FLIPLAYOUT:
+               ws->l_state.horizontal_flip = !ws->l_state.horizontal_flip;
+               break;
+       default:
+               return;
+       }
+}
+
+void
+horizontal_stack(struct workspace *ws, struct swm_geometry *g)
+{
+       DNPRINTF(SWM_D_STACK, "horizontal_stack: workspace: %d\n", ws->idx);
+
+       stack_master(ws, g, 1, ws->l_state.horizontal_flip);
+}
+
+/* fullscreen view */
+void
+max_stack(struct workspace *ws, struct swm_geometry *g)
+{
+       XWindowChanges          wc;
+       struct swm_geometry     gg = *g;
+       struct ws_win           *win, *wintrans = NULL, *parent = NULL;
+       unsigned int            mask;
+       int                     winno;
+
+       DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
+
+       if (ws == NULL)
+               return;
+
+       winno = count_win(ws, 0);
+       if (winno == 0 && count_win(ws, 1) == 0)
+               return;
+
+       TAILQ_FOREACH(win, &ws->winlist, entry) {
+               if (win->transient) {
+                       wintrans = win;
+                       parent = find_window(win->transient);
+                       continue;
+               }
+
+               if (win->floating && win->floatmaxed == 0 ) {
+                       /*
+                        * retain geometry for retrieval on exit from
+                        * max_stack mode
+                        */
+                       store_float_geom(win, ws->r);
+                       win->floatmaxed = 1;
+               }
+
+               /* only reconfigure if necessary */
+               if (X(win) != gg.x || Y(win) != gg.y || WIDTH(win) != gg.w ||
+                   HEIGHT(win) != gg.h) {
+                       bzero(&wc, sizeof wc);
+                       X(win) = wc.x = gg.x;
+                       Y(win) = wc.y = gg.y;
+                       if (bar_enabled){
+                               wc.border_width = border_width;
+                               WIDTH(win) = wc.width = gg.w;
+                               HEIGHT(win) = wc.height = gg.h;
+                       } else {
+                               wc.border_width = 0;
+                               WIDTH(win) = wc.width = gg.w + 2 * border_width;
+                               HEIGHT(win) = wc.height = gg.h +
+                                   2 * border_width;
+                       }
+                       mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
+                       XConfigureWindow(display, win->id, mask, &wc);
+               }
+               /* unmap only if we don't have multi screen */
+               if (win != ws->focus)
+                       if (!(ScreenCount(display) > 1 || outputs > 1))
+                               unmap_window(win);
+       }
+
+       /* put the last transient on top */
+       if (wintrans) {
+               if (parent)
+                       XMapRaised(display, parent->id);
+               stack_floater(wintrans, ws->r);
+               focus_magic(wintrans);
+       }
+}
+
+void
+send_to_ws(struct swm_region *r, union arg *args)
+{
+       int                     wsid = args->id;
+       struct ws_win           *win = NULL, *parent;
+       struct workspace        *ws, *nws;
+       Atom                    ws_idx_atom = 0;
+       unsigned char           ws_idx_str[SWM_PROPLEN];
+       union arg               a;
+
+       if (r && r->ws && r->ws->focus)
+               win = r->ws->focus;
+       else
+               return;
+       if (win == NULL)
+               return;
+       if (win->ws->idx == wsid)
+               return;
+
+       DNPRINTF(SWM_D_MOVE, "send_to_ws: window: 0x%lx\n", win->id);
+
+       ws = win->ws;
+       nws = &win->s->ws[wsid];
+
+       a.id = SWM_ARG_ID_FOCUSPREV;
+       focus(r, &a);
+       if (win->transient) {
+               parent = find_window(win->transient);
+               if (parent) {
+                       unmap_window(parent);
+                       TAILQ_REMOVE(&ws->winlist, parent, entry);
+                       TAILQ_INSERT_TAIL(&nws->winlist, parent, entry);
+                       parent->ws = nws;
+               }
+       }
+       unmap_window(win);
+       TAILQ_REMOVE(&ws->winlist, win, entry);
+       TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
+       if (TAILQ_EMPTY(&ws->winlist))
+               r->ws->focus = NULL;
+       win->ws = nws;
+
+       /* Try to update the window's workspace property */
+       ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
+       if (ws_idx_atom &&
+           snprintf((char *)ws_idx_str, SWM_PROPLEN, "%d", nws->idx) <
+               SWM_PROPLEN) {
+               DNPRINTF(SWM_D_PROP, "send_to_ws: set property: _SWM_WS: %s\n",
+                   ws_idx_str);
+               XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
+                   PropModeReplace, ws_idx_str, strlen((char *)ws_idx_str));
+       }
+
+       stack();
+}
+
+void
+pressbutton(struct swm_region *r, union arg *args)
+{
+       XTestFakeButtonEvent(display, args->id, True, CurrentTime);
+       XTestFakeButtonEvent(display, args->id, False, CurrentTime);
+}
+
+void
+raise_toggle(struct swm_region *r, union arg *args)
+{
+       if (r && r->ws == NULL)
+               return;
+
+       r->ws->always_raise = !r->ws->always_raise;
+
+       /* bring floaters back to top */
+       if (r->ws->always_raise == 0)
+               stack();
+}
+
+void
+iconify(struct swm_region *r, union arg *args)
+{
+       union arg a;
+
+       if (r->ws->focus == NULL)
+               return;
+       unmap_window(r->ws->focus);
+       update_iconic(r->ws->focus, 1);
+       stack();
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+       r->ws->focus = NULL;
+       a.id = SWM_ARG_ID_FOCUSCUR;
+       focus(r, &a);
+}
+
+unsigned char *
+get_win_name(Window win)
+{
+       unsigned char           *prop = NULL;
+       unsigned long           nbytes, nitems;
+
+       /* try _NET_WM_NAME first */
+       if (get_property(win, a_netwmname, 0L, a_utf8_string, NULL, &nbytes,
+           &prop)) {
+               XFree(prop);
+               if (get_property(win, a_netwmname, nbytes, a_utf8_string,
+                   &nitems, NULL, &prop))
+                       return (prop);
+       }
+
+       /* fallback to WM_NAME */
+       if (!get_property(win, a_wmname, 0L, a_string, NULL, &nbytes, &prop))
+               return (NULL);
+       XFree(prop);
+       if (get_property(win, a_wmname, nbytes, a_string, &nitems, NULL, &prop))
+               return (prop);
+
+       return (NULL);
+}
+
+void
+uniconify(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *win;
+       FILE                    *lfile;
+       unsigned char           *name;
+       int                     count = 0;
+
+       DNPRINTF(SWM_D_MISC, "uniconify\n");
+
+       if (r && r->ws == NULL)
+               return;
+
+       /* make sure we have anything to uniconify */
+       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
+               if (win->ws == NULL)
+                       continue; /* should never happen */
+               if (win->iconic == 0)
+                       continue;
+               count++;
+       }
+       if (count == 0)
+               return;
+
+       search_r = r;
+       search_resp_action = SWM_SEARCH_UNICONIFY;
+
+       spawn_select(r, args, "search", &searchpid);
+
+       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+               return;
+
+       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
+               if (win->ws == NULL)
+                       continue; /* should never happen */
+               if (win->iconic == 0)
+                       continue;
+
+               name = get_win_name(win->id);
+               if (name == NULL)
+                       continue;
+               fprintf(lfile, "%s.%lu\n", name, win->id);
+               XFree(name);
+       }
+
+       fclose(lfile);
+}
+
+void
+name_workspace(struct swm_region *r, union arg *args)
+{
+       FILE                    *lfile;
+
+       DNPRINTF(SWM_D_MISC, "name_workspace\n");
+
+       if (r == NULL)
+               return;
+
+       search_r = r;
+       search_resp_action = SWM_SEARCH_NAME_WORKSPACE;
+
+       spawn_select(r, args, "name_workspace", &searchpid);
+
+       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+               return;
+
+       fprintf(lfile, "%s", "");
+       fclose(lfile);
+}
+
+void
+search_workspace(struct swm_region *r, union arg *args)
+{
+       int                     i;
+       struct workspace        *ws;
+       FILE                    *lfile;
+
+       DNPRINTF(SWM_D_MISC, "search_workspace\n");
+
+       if (r == NULL)
+               return;
+
+       search_r = r;
+       search_resp_action = SWM_SEARCH_SEARCH_WORKSPACE;
+
+       spawn_select(r, args, "search", &searchpid);
+
+       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+               return;
+
+       for (i = 0; i < SWM_WS_MAX; i++) {
+               ws = &r->s->ws[i];
+               if (ws == NULL)
+                       continue;
+               fprintf(lfile, "%d%s%s\n", ws->idx + 1,
+                   (ws->name ? ":" : ""), (ws->name ? ws->name : ""));
+       }
+
+       fclose(lfile);
+}
+
+void
+search_win_cleanup(void)
+{
+       struct search_window    *sw = NULL;
+
+       while ((sw = TAILQ_FIRST(&search_wl)) != NULL) {
+               XDestroyWindow(display, sw->indicator);
+               XFreeGC(display, sw->gc);
+               TAILQ_REMOVE(&search_wl, sw, entry);
+               free(sw);
+       }
+}
+
+void
+search_win(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *win = NULL;
+       struct search_window    *sw = NULL;
+       Window                  w;
+       XGCValues               gcv;
+       int                     i;
+       char                    s[8];
+       FILE                    *lfile;
+       size_t                  len;
+       XRectangle              ibox, lbox;
+
+       DNPRINTF(SWM_D_MISC, "search_win\n");
+
+       search_r = r;
+       search_resp_action = SWM_SEARCH_SEARCH_WINDOW;
+
+       spawn_select(r, args, "search", &searchpid);
+
+       if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+               return;
+
+       TAILQ_INIT(&search_wl);
+
+       i = 1;
+       TAILQ_FOREACH(win, &r->ws->winlist, entry) {
+               if (win->iconic == 1)
+                       continue;
+
+               sw = calloc(1, sizeof(struct search_window));
+               if (sw == NULL) {
+                       warn("search_win: calloc");
+                       fclose(lfile);
+                       search_win_cleanup();
+                       return;
+               }
+               sw->idx = i;
+               sw->win = win;
+
+               snprintf(s, sizeof s, "%d", i);
+               len = strlen(s);
+
+               XmbTextExtents(bar_fs, s, len, &ibox, &lbox);
+
+               w = XCreateSimpleWindow(display,
+                   win->id, 0, 0,lbox.width + 4,
+                   bar_fs_extents->max_logical_extent.height, 1,
+                   r->s->c[SWM_S_COLOR_UNFOCUS].color,
+                   r->s->c[SWM_S_COLOR_FOCUS].color);
+
+               sw->indicator = w;
+               TAILQ_INSERT_TAIL(&search_wl, sw, entry);
+
+               sw->gc = XCreateGC(display, w, 0, &gcv);
+               XMapRaised(display, w);
+               XSetForeground(display, sw->gc, r->s->c[SWM_S_COLOR_BAR].color);
+
+               DRAWSTRING(display, w, bar_fs, sw->gc, 2,
+                   (bar_fs_extents->max_logical_extent.height -
+                   lbox.height) / 2 - lbox.y, s, len);
+
+               fprintf(lfile, "%d\n", i);
+               i++;
+       }
+
+       fclose(lfile);
+}
+
+void
+search_resp_uniconify(char *resp, unsigned long len)
+{
+       unsigned char           *name;
+       struct ws_win           *win;
+       char                    *s;
+
+       DNPRINTF(SWM_D_MISC, "search_resp_uniconify: resp: %s\n", resp);
+
+       TAILQ_FOREACH(win, &search_r->ws->winlist, entry) {
+               if (win->iconic == 0)
+                       continue;
+               name = get_win_name(win->id);
+               if (name == NULL)
+                       continue;
+               if (asprintf(&s, "%s.%lu", name, win->id) == -1) {
+                       XFree(name);
+                       continue;
+               }
+               XFree(name);
+               if (strncmp(s, resp, len) == 0) {
+                       /* XXX this should be a callback to generalize */
+                       update_iconic(win, 0);
+                       free(s);
+                       break;
+               }
+               free(s);
+       }
+}
+
+void
+search_resp_name_workspace(char *resp, unsigned long len)
+{
+       struct workspace        *ws;
+
+       DNPRINTF(SWM_D_MISC, "search_resp_name_workspace: resp: %s\n", resp);
+
+       if (search_r->ws == NULL)
+               return;
+       ws = search_r->ws;
+
+       if (ws->name) {
+               free(search_r->ws->name);
+               search_r->ws->name = NULL;
+       }
+
+       if (len > 1) {
+               ws->name = strdup(resp);
+               if (ws->name == NULL) {
+                       DNPRINTF(SWM_D_MISC, "search_resp_name_workspace: "
+                           "strdup: %s", strerror(errno));
+                       return;
+               }
+       }
+}
+
+void
+search_resp_search_workspace(char *resp, unsigned long len)
+{
+       char                    *p, *q;
+       int                     ws_idx;
+       const char              *errstr;
+       union arg               a;
+
+       DNPRINTF(SWM_D_MISC, "search_resp_search_workspace: resp: %s\n", resp);
+
+       q = strdup(resp);
+       if (!q) {
+               DNPRINTF(SWM_D_MISC, "search_resp_search_workspace: strdup: %s",
+                   strerror(errno));
+               return;
+       }
+       p = strchr(q, ':');
+       if (p != NULL)
+               *p = '\0';
+       ws_idx = strtonum(q, 1, SWM_WS_MAX, &errstr);
+       if (errstr) {
+               DNPRINTF(SWM_D_MISC, "workspace idx is %s: %s",
+                   errstr, q);
+               free(q);
+               return;
+       }
+       free(q);
+       a.id = ws_idx - 1;
+       switchws(search_r, &a);
+}
+
+void
+search_resp_search_window(char *resp, unsigned long len)
+{
+       char                    *s;
+       int                     idx;
+       const char              *errstr;
+       struct search_window    *sw;
+
+       DNPRINTF(SWM_D_MISC, "search_resp_search_window: resp: %s\n", resp);
+
+       s = strdup(resp);
+       if (!s) {
+               DNPRINTF(SWM_D_MISC, "search_resp_search_window: strdup: %s",
+                   strerror(errno));
+               return;
+       }
+
+       idx = strtonum(s, 1, INT_MAX, &errstr);
+       if (errstr) {
+               DNPRINTF(SWM_D_MISC, "window idx is %s: %s",
+                   errstr, s);
+               free(s);
+               return;
+       }
+       free(s);
+
+       TAILQ_FOREACH(sw, &search_wl, entry)
+               if (idx == sw->idx) {
+                       focus_win(sw->win);
+                       break;
+               }
+}
+
+#define MAX_RESP_LEN   1024
+
+void
+search_do_resp(void)
+{
+       ssize_t                 rbytes;
+       char                    *resp;
+       unsigned long           len;
+
+       DNPRINTF(SWM_D_MISC, "search_do_resp:\n");
+
+       search_resp = 0;
+       searchpid = 0;
+
+       if ((resp = calloc(1, MAX_RESP_LEN + 1)) == NULL) {
+               warn("search: calloc");
+               goto done;
+       }
+
+       rbytes = read(select_resp_pipe[0], resp, MAX_RESP_LEN);
+       if (rbytes <= 0) {
+               warn("search: read error");
+               goto done;
+       }
+       resp[rbytes] = '\0';
+
+       /* XXX:
+        * Older versions of dmenu (Atleast pre 4.4.1) do not send a
+        * newline, so work around that by sanitizing the resp now.
+        */
+       resp[strcspn(resp, "\n")] = '\0';
+       len = strlen(resp);
+
+       switch (search_resp_action) {
+       case SWM_SEARCH_UNICONIFY:
+               search_resp_uniconify(resp, len);
+               break;
+       case SWM_SEARCH_NAME_WORKSPACE:
+               search_resp_name_workspace(resp, len);
+               break;
+       case SWM_SEARCH_SEARCH_WORKSPACE:
+               search_resp_search_workspace(resp, len);
+               break;
+       case SWM_SEARCH_SEARCH_WINDOW:
+               search_resp_search_window(resp, len);
+               break;
+       }
+
+done:
+       if (search_resp_action == SWM_SEARCH_SEARCH_WINDOW)
+               search_win_cleanup();
+
+       search_resp_action = SWM_SEARCH_NONE;
+       close(select_resp_pipe[0]);
+       free(resp);
+}
+
+void
+wkill(struct swm_region *r, union arg *args)
+{
+       DNPRINTF(SWM_D_MISC, "wkill: id: %d\n", args->id);
+
+       if (r->ws->focus == NULL)
+               return;
+
+       if (args->id == SWM_ARG_ID_KILLWINDOW)
+               XKillClient(display, r->ws->focus->id);
+       else
+               if (r->ws->focus->can_delete)
+                       client_msg(r->ws->focus, adelete);
+}
+
+
+int
+floating_toggle_win(struct ws_win *win)
+{
+       struct swm_region       *r;
+
+       if (win == NULL)
+               return 0;
+
+       if (!win->ws->r)
+               return 0;
+
+       r = win->ws->r;
+
+       /* reject floating toggles in max stack mode */
+       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK])
+               return 0;
+
+       if (win->floating) {
+               if (!win->floatmaxed) {
+                       /* retain position for refloat */
+                       store_float_geom(win, r);
+               }
+               win->floating = 0;
+       } else {
+               if (win->g_floatvalid) {
+                       /* refloat at last floating relative position */
+                       X(win) = win->g_float.x - win->rg_float.x + X(r);
+                       Y(win) = win->g_float.y - win->rg_float.y + Y(r);
+                       WIDTH(win) = win->g_float.w;
+                       HEIGHT(win) = win->g_float.h;
+               }
+               win->floating = 1;
+       }
+
+       ewmh_update_actions(win);
+
+       return 1;
+}
+
+void
+floating_toggle(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *win = r->ws->focus;
+       union arg               a;
+
+       if (win == NULL)
+               return;
+
+       ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
+           _NET_WM_STATE_TOGGLE);
+
+       stack();
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+
+       if (win == win->ws->focus) {
+               a.id = SWM_ARG_ID_FOCUSCUR;
+               focus(win->ws->r, &a);
+       }
+}
+
+void
+constrain_window(struct ws_win *win, struct swm_region *r, int resizable)
+{
+       if (X(win) + WIDTH(win) > X(r) + WIDTH(r) - border_width) {
+               if (resizable)
+                       WIDTH(win) = X(r) + WIDTH(r) - X(win) - border_width;
+               else
+                       X(win) = X(r) + WIDTH(r) - WIDTH(win) - border_width;
+       }
+
+       if (X(win) < X(r) - border_width) {
+               if (resizable)
+                       WIDTH(win) -= X(r) - X(win) - border_width;
+
+               X(win) = X(r) - border_width;
+       }
+
+       if (Y(win) + HEIGHT(win) > Y(r) + HEIGHT(r) - border_width) {
+               if (resizable)
+                       HEIGHT(win) = Y(r) + HEIGHT(r) - Y(win) - border_width;
+               else
+                       Y(win) = Y(r) + HEIGHT(r) - HEIGHT(win) - border_width;
+       }
+
+       if (Y(win) < Y(r) - border_width) {
+               if (resizable)
+                       HEIGHT(win) -= Y(r) - Y(win) - border_width;
+
+               Y(win) = Y(r) - border_width;
+       }
+
+       if (WIDTH(win) < 1)
+               WIDTH(win) = 1;
+       if (HEIGHT(win) < 1)
+               HEIGHT(win) = 1;
+}
+
+void
+update_window(struct ws_win *win)
+{
+       unsigned int            mask;
+       XWindowChanges          wc;
+
+       bzero(&wc, sizeof wc);
+       mask = CWBorderWidth | CWWidth | CWHeight | CWX | CWY;
+       wc.border_width = border_width;
+       wc.x = X(win);
+       wc.y = Y(win);
+       wc.width = WIDTH(win);
+       wc.height = HEIGHT(win);
+
+       DNPRINTF(SWM_D_MISC, "update_window: window: 0x%lx, (x,y) w x h: "
+           "(%d,%d) %d x %d\n", win->id, wc.x, wc.y, wc.width, wc.height);
+
+       XConfigureWindow(display, win->id, mask, &wc);
+}
+
+#define SWM_RESIZE_STEPS       (50)
+
+void
+resize(struct ws_win *win, union arg *args)
+{
+       XEvent                  ev;
+       Time                    time = 0;
+       struct swm_region       *r = NULL;
+       int                     resize_step = 0;
+       Window                  rr, cr;
+       int                     x, y, wx, wy;
+       unsigned int            mask;
+       struct swm_geometry     g;
+       int                     top = 0, left = 0;
+       int                     dx, dy;
+       Cursor                  cursor;
+       unsigned int            shape; /* cursor style */
+
+       if (win == NULL)
+               return;
+       r = win->ws->r;
+
+       DNPRINTF(SWM_D_MOUSE, "resize: window: 0x%lx, floating: %s, "
+           "transient: 0x%lx\n", win->id, YESNO(win->floating),
+           win->transient);
+
+       if (!(win->transient != 0 || win->floating != 0))
+               return;
+
+       /* reject resizes in max mode for floaters (transient ok) */
+       if (win->floatmaxed)
+               return;
+
+       win->manual = 1;
+       ewmh_update_win_state(win, ewmh[_SWM_WM_STATE_MANUAL].atom,
+           _NET_WM_STATE_ADD);
+
+       stack();
+
+       switch (args->id) {
+       case SWM_ARG_ID_WIDTHSHRINK:
+               WIDTH(win) -= SWM_RESIZE_STEPS;
+               resize_step = 1;
+               break;
+       case SWM_ARG_ID_WIDTHGROW:
+               WIDTH(win) += SWM_RESIZE_STEPS;
+               resize_step = 1;
+               break;
+       case SWM_ARG_ID_HEIGHTSHRINK:
+               HEIGHT(win) -= SWM_RESIZE_STEPS;
+               resize_step = 1;
+               break;
+       case SWM_ARG_ID_HEIGHTGROW:
+               HEIGHT(win) += SWM_RESIZE_STEPS;
+               resize_step = 1;
+               break;
+       default:
+               break;
+       }
+       if (resize_step) {
+               constrain_window(win, r, 1);
+               update_window(win);
+               store_float_geom(win,r);
+               return;
+       }
+
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+
+       /* get cursor offset from window root */
+       if (!XQueryPointer(display, win->id, &rr, &cr, &x, &y, &wx, &wy, &mask))
+           return;
+
+       g = win->g;
+
+       if (wx < WIDTH(win) / 2)
+               left = 1;
+
+       if (wy < HEIGHT(win) / 2)
+               top = 1;
+
+       if (args->id == SWM_ARG_ID_CENTER)
+               shape = XC_sizing;
+       else if (top)
+               shape = (left) ? XC_top_left_corner : XC_top_right_corner;
+       else
+               shape = (left) ? XC_bottom_left_corner : XC_bottom_right_corner;
+
+       cursor = XCreateFontCursor(display, shape);
+
+       if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
+           GrabModeAsync, None, cursor, CurrentTime) != GrabSuccess) {
+               XFreeCursor(display, cursor);
+               return;
+       }
+
+       do {
+               XMaskEvent(display, MOUSEMASK | ExposureMask |
+                   SubstructureRedirectMask, &ev);
+               switch (ev.type) {
+               case ConfigureRequest:
+               case Expose:
+               case MapRequest:
+                       handler[ev.type](&ev);
+                       break;
+               case MotionNotify:
+                       /* cursor offset/delta from start of the operation */
+                       dx = ev.xmotion.x_root - x;
+                       dy = ev.xmotion.y_root - y;
+
+                       /* vertical */
+                       if (top)
+                               dy = -dy;
+
+                       if (args->id == SWM_ARG_ID_CENTER) {
+                               if (g.h / 2 + dy < 1)
+                                       dy = 1 - g.h / 2;
+
+                               Y(win) = g.y - dy;
+                               HEIGHT(win) = g.h + 2 * dy;
+                       } else {
+                               if (g.h + dy < 1)
+                                       dy = 1 - g.h;
+
+                               if (top)
+                                       Y(win) = g.y - dy;
+
+                               HEIGHT(win) = g.h + dy;
+                       }
+
+                       /* horizontal */
+                       if (left)
+                               dx = -dx;
+
+                       if (args->id == SWM_ARG_ID_CENTER) {
+                               if (g.w / 2 + dx < 1)
+                                       dx = 1 - g.w / 2;
+
+                               X(win) = g.x - dx;
+                               WIDTH(win) = g.w + 2 * dx;
+                       } else {
+                               if (g.w + dx < 1)
+                                       dx = 1 - g.w;
+
+                               if (left)
+                                       X(win) = g.x - dx;
+
+                               WIDTH(win) = g.w + dx;
+                       }
+
+                       constrain_window(win, r, 1);
+
+                       /* not free, don't sync more than 120 times / second */
+                       if ((ev.xmotion.time - time) > (1000 / 120) ) {
+                               time = ev.xmotion.time;
+                               XSync(display, False);
+                               update_window(win);
+                       }
+                       break;
+               }
+       } while (ev.type != ButtonRelease);
+       if (time) {
+               XSync(display, False);
+               update_window(win);
+       }
+       store_float_geom(win,r);
+
+       XUngrabPointer(display, CurrentTime);
+       XFreeCursor(display, cursor);
+
+       /* drain events */
+       drain_enter_notify();
+}
+
+void
+resize_step(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *win = NULL;
+
+       if (r && r->ws && r->ws->focus)
+               win = r->ws->focus;
+       else
+               return;
+
+       resize(win, args);
+}
+
+#define SWM_MOVE_STEPS (50)
+
+void
+move(struct ws_win *win, union arg *args)
+{
+       XEvent                  ev;
+       Time                    time = 0;
+       int                     move_step = 0;
+       struct swm_region       *r = NULL;
+
+       Window                  rr, cr;
+       int                     x, y, wx, wy;
+       unsigned int            mask;
+
+       if (win == NULL)
+               return;
+       r = win->ws->r;
+
+       DNPRINTF(SWM_D_MOUSE, "move: window: 0x%lx, floating: %s, transient: "
+           "0x%lx\n", win->id, YESNO(win->floating), win->transient);
+
+       /* in max_stack mode should only move transients */
+       if (win->ws->cur_layout == &layouts[SWM_MAX_STACK] && !win->transient)
+               return;
+
+       win->manual = 1;
+       if (win->floating == 0 && !win->transient) {
+               store_float_geom(win,r);
+               ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
+                   _NET_WM_STATE_ADD);
+       }
+       ewmh_update_win_state(win, ewmh[_SWM_WM_STATE_MANUAL].atom,
+           _NET_WM_STATE_ADD);
+
+       stack();
+
+       move_step = 0;
+       switch (args->id) {
+       case SWM_ARG_ID_MOVELEFT:
+               X(win) -= (SWM_MOVE_STEPS - border_width);
+               move_step = 1;
+               break;
+       case SWM_ARG_ID_MOVERIGHT:
+               X(win) += (SWM_MOVE_STEPS - border_width);
+               move_step = 1;
+               break;
+       case SWM_ARG_ID_MOVEUP:
+               Y(win) -= (SWM_MOVE_STEPS - border_width);
+               move_step = 1;
+               break;
+       case SWM_ARG_ID_MOVEDOWN:
+               Y(win) += (SWM_MOVE_STEPS - border_width);
+               move_step = 1;
+               break;
+       default:
+               break;
+       }
+       if (move_step) {
+               constrain_window(win, r, 0);
+               update_window(win);
+               store_float_geom(win, r);
+               return;
+       }
+
+       if (XGrabPointer(display, win->id, False, MOUSEMASK, GrabModeAsync,
+           GrabModeAsync, None, XCreateFontCursor(display, XC_fleur),
+           CurrentTime) != GrabSuccess)
+               return;
+
+       /* get cursor offset from window root */
+       if (!XQueryPointer(display, win->id, &rr, &cr, &x, &y, &wx, &wy, &mask))
+           return;
+
+       do {
+               XMaskEvent(display, MOUSEMASK | ExposureMask |
+                   SubstructureRedirectMask, &ev);
+               switch (ev.type) {
+               case ConfigureRequest:
+               case Expose:
+               case MapRequest:
+                       handler[ev.type](&ev);
+                       break;
+               case MotionNotify:
+                       X(win) = ev.xmotion.x_root - wx - border_width;
+                       Y(win) = ev.xmotion.y_root - wy - border_width;
+
+                       constrain_window(win, r, 0);
+
+                       /* not free, don't sync more than 120 times / second */
+                       if ((ev.xmotion.time - time) > (1000 / 120) ) {
+                               time = ev.xmotion.time;
+                               XSync(display, False);
+                               update_window(win);
+                       }
+                       break;
+               }
+       } while (ev.type != ButtonRelease);
+       if (time) {
+               XSync(display, False);
+               update_window(win);
+       }
+       store_float_geom(win,r);
+       XUngrabPointer(display, CurrentTime);
+
+       /* drain events */
+       drain_enter_notify();
+}
+
+void
+move_step(struct swm_region *r, union arg *args)
+{
+       struct ws_win           *win = NULL;
+
+       if (r && r->ws && r->ws->focus)
+               win = r->ws->focus;
+       else
+               return;
+
+       if (!(win->transient != 0 || win->floating != 0))
+               return;
+
+       move(win, args);
+}
+
+
+/* user/key callable function IDs */
+enum keyfuncid {
+       kf_cycle_layout,
+       kf_flip_layout,
+       kf_stack_reset,
+       kf_master_shrink,
+       kf_master_grow,
+       kf_master_add,
+       kf_master_del,
+       kf_stack_inc,
+       kf_stack_dec,
+       kf_swap_main,
+       kf_focus_next,
+       kf_focus_prev,
+       kf_swap_next,
+       kf_swap_prev,
+       kf_spawn_term,
+       kf_spawn_menu,
+       kf_quit,
+       kf_restart,
+       kf_focus_main,
+       kf_ws_1,
+       kf_ws_2,
+       kf_ws_3,
+       kf_ws_4,
+       kf_ws_5,
+       kf_ws_6,
+       kf_ws_7,
+       kf_ws_8,
+       kf_ws_9,
+       kf_ws_10,
+       kf_ws_next,
+       kf_ws_prev,
+       kf_ws_next_all,
+       kf_ws_prev_all,
+       kf_ws_prior,
+       kf_screen_next,
+       kf_screen_prev,
+       kf_mvws_1,
+       kf_mvws_2,
+       kf_mvws_3,
+       kf_mvws_4,
+       kf_mvws_5,
+       kf_mvws_6,
+       kf_mvws_7,
+       kf_mvws_8,
+       kf_mvws_9,
+       kf_mvws_10,
+       kf_bar_toggle,
+       kf_wind_kill,
+       kf_wind_del,
+       kf_screenshot_all,
+       kf_screenshot_wind,
+       kf_float_toggle,
+       kf_version,
+       kf_spawn_lock,
+       kf_spawn_initscr,
+       kf_spawn_custom,
+       kf_iconify,
+       kf_uniconify,
+       kf_raise_toggle,
+       kf_button2,
+       kf_width_shrink,
+       kf_width_grow,
+       kf_height_shrink,
+       kf_height_grow,
+       kf_move_left,
+       kf_move_right,
+       kf_move_up,
+       kf_move_down,
+       kf_name_workspace,
+       kf_search_workspace,
+       kf_search_win,
+       kf_dumpwins, /* MUST BE LAST */
+       kf_invalid
+};
+
+/* key definitions */
+void
+dummykeyfunc(struct swm_region *r, union arg *args)
+{
+};
+
+void
+legacyfunc(struct swm_region *r, union arg *args)
+{
+};
+
+struct keyfunc {
+       char                    name[SWM_FUNCNAME_LEN];
+       void                    (*func)(struct swm_region *r, union arg *);
+       union arg               args;
+} keyfuncs[kf_invalid + 1] = {
+       /* name                 function        argument */
+       { "cycle_layout",       cycle_layout,   {0} },
+       { "flip_layout",        stack_config,   {.id = SWM_ARG_ID_FLIPLAYOUT} },
+       { "stack_reset",        stack_config,   {.id = SWM_ARG_ID_STACKRESET} },
+       { "master_shrink",      stack_config,   {.id = SWM_ARG_ID_MASTERSHRINK} },
+       { "master_grow",        stack_config,   {.id = SWM_ARG_ID_MASTERGROW} },
+       { "master_add",         stack_config,   {.id = SWM_ARG_ID_MASTERADD} },
+       { "master_del",         stack_config,   {.id = SWM_ARG_ID_MASTERDEL} },
+       { "stack_inc",          stack_config,   {.id = SWM_ARG_ID_STACKINC} },
+       { "stack_dec",          stack_config,   {.id = SWM_ARG_ID_STACKDEC} },
+       { "swap_main",          swapwin,        {.id = SWM_ARG_ID_SWAPMAIN} },
+       { "focus_next",         focus,          {.id = SWM_ARG_ID_FOCUSNEXT} },
+       { "focus_prev",         focus,          {.id = SWM_ARG_ID_FOCUSPREV} },
+       { "swap_next",          swapwin,        {.id = SWM_ARG_ID_SWAPNEXT} },
+       { "swap_prev",          swapwin,        {.id = SWM_ARG_ID_SWAPPREV} },
+       { "spawn_term",         spawnterm,      {.argv = spawn_term} },
+       { "spawn_menu",         legacyfunc,     {0} },
+       { "quit",               quit,           {0} },
+       { "restart",            restart,        {0} },
+       { "focus_main",         focus,          {.id = SWM_ARG_ID_FOCUSMAIN} },
+       { "ws_1",               switchws,       {.id = 0} },
+       { "ws_2",               switchws,       {.id = 1} },
+       { "ws_3",               switchws,       {.id = 2} },
+       { "ws_4",               switchws,       {.id = 3} },
+       { "ws_5",               switchws,       {.id = 4} },
+       { "ws_6",               switchws,       {.id = 5} },
+       { "ws_7",               switchws,       {.id = 6} },
+       { "ws_8",               switchws,       {.id = 7} },
+       { "ws_9",               switchws,       {.id = 8} },
+       { "ws_10",              switchws,       {.id = 9} },
+       { "ws_next",            cyclews,        {.id = SWM_ARG_ID_CYCLEWS_UP} },
+       { "ws_prev",            cyclews,        {.id = SWM_ARG_ID_CYCLEWS_DOWN} },
+       { "ws_next_all",        cyclews,        {.id = SWM_ARG_ID_CYCLEWS_UP_ALL} },
+       { "ws_prev_all",        cyclews,        {.id = SWM_ARG_ID_CYCLEWS_DOWN_ALL} },
+       { "ws_prior",           priorws,        {0} },
+       { "screen_next",        cyclescr,       {.id = SWM_ARG_ID_CYCLESC_UP} },
+       { "screen_prev",        cyclescr,       {.id = SWM_ARG_ID_CYCLESC_DOWN} },
+       { "mvws_1",             send_to_ws,     {.id = 0} },
+       { "mvws_2",             send_to_ws,     {.id = 1} },
+       { "mvws_3",             send_to_ws,     {.id = 2} },
+       { "mvws_4",             send_to_ws,     {.id = 3} },
+       { "mvws_5",             send_to_ws,     {.id = 4} },
+       { "mvws_6",             send_to_ws,     {.id = 5} },
+       { "mvws_7",             send_to_ws,     {.id = 6} },
+       { "mvws_8",             send_to_ws,     {.id = 7} },
+       { "mvws_9",             send_to_ws,     {.id = 8} },
+       { "mvws_10",            send_to_ws,     {.id = 9} },
+       { "bar_toggle",         bar_toggle,     {0} },
+       { "wind_kill",          wkill,          {.id = SWM_ARG_ID_KILLWINDOW} },
+       { "wind_del",           wkill,          {.id = SWM_ARG_ID_DELETEWINDOW} },
+       { "screenshot_all",     legacyfunc,     {0} },
+       { "screenshot_wind",    legacyfunc,     {0} },
+       { "float_toggle",       floating_toggle,{0} },
+       { "version",            version,        {0} },
+       { "spawn_lock",         legacyfunc,     {0} },
+       { "spawn_initscr",      legacyfunc,     {0} },
+       { "spawn_custom",       dummykeyfunc,   {0} },
+       { "iconify",            iconify,        {0} },
+       { "uniconify",          uniconify,      {0} },
+       { "raise_toggle",       raise_toggle,   {0} },
+       { "button2",            pressbutton,    {2} },
+       { "width_shrink",       resize_step,    {.id = SWM_ARG_ID_WIDTHSHRINK} },
+       { "width_grow",         resize_step,    {.id = SWM_ARG_ID_WIDTHGROW} },
+       { "height_shrink",      resize_step,    {.id = SWM_ARG_ID_HEIGHTSHRINK} },
+       { "height_grow",        resize_step,    {.id = SWM_ARG_ID_HEIGHTGROW} },
+       { "move_left",          move_step,      {.id = SWM_ARG_ID_MOVELEFT} },
+       { "move_right",         move_step,      {.id = SWM_ARG_ID_MOVERIGHT} },
+       { "move_up",            move_step,      {.id = SWM_ARG_ID_MOVEUP} },
+       { "move_down",          move_step,      {.id = SWM_ARG_ID_MOVEDOWN} },
+       { "name_workspace",     name_workspace, {0} },
+       { "search_workspace",   search_workspace,       {0} },
+       { "search_win",         search_win,     {0} },
+       { "dumpwins",           dumpwins,       {0} }, /* MUST BE LAST */
+       { "invalid key func",   NULL,           {0} },
+};
+struct key {
+       RB_ENTRY(key)           entry;
+       unsigned int            mod;
+       KeySym                  keysym;
+       enum keyfuncid          funcid;
+       char                    *spawn_name;
+};
+RB_HEAD(key_list, key);
+
+int
+key_cmp(struct key *kp1, struct key *kp2)
+{
+       if (kp1->keysym < kp2->keysym)
+               return (-1);
+       if (kp1->keysym > kp2->keysym)
+               return (1);
+
+       if (kp1->mod < kp2->mod)
+               return (-1);
+       if (kp1->mod > kp2->mod)
+               return (1);
+
+       return (0);
+}
+
+RB_GENERATE_STATIC(key_list, key, entry, key_cmp);
+struct key_list                        keys;
+
+/* mouse */
+enum { client_click, root_click };
+struct button {
+       unsigned int            action;
+       unsigned int            mask;
+       unsigned int            button;
+       void                    (*func)(struct ws_win *, union arg *);
+       union arg               args;
+} buttons[] = {
+         /* action     key             mouse button    func    args */
+       { client_click, MODKEY,         Button3,        resize, {.id = SWM_ARG_ID_DONTCENTER} },
+       { client_click, MODKEY | ShiftMask, Button3,    resize, {.id = SWM_ARG_ID_CENTER} },
+       { client_click, MODKEY,         Button1,        move,   {0} },
+};
+
+void
+update_modkey(unsigned int mod)
+{
+       int                     i;
+       struct key              *kp;
+
+       mod_key = mod;
+       RB_FOREACH(kp, key_list, &keys)
+               if (kp->mod & ShiftMask)
+                       kp->mod = mod | ShiftMask;
+               else
+                       kp->mod = mod;
+
+       for (i = 0; i < LENGTH(buttons); i++)
+               if (buttons[i].mask & ShiftMask)
+                       buttons[i].mask = mod | ShiftMask;
+               else
+                       buttons[i].mask = mod;
+}
+
+/* spawn */
+struct spawn_prog {
+       TAILQ_ENTRY(spawn_prog) entry;
+       char                    *name;
+       int                     argc;
+       char                    **argv;
+};
+TAILQ_HEAD(spawn_list, spawn_prog);
+struct spawn_list              spawns = TAILQ_HEAD_INITIALIZER(spawns);
+
+int
+spawn_expand(struct swm_region *r, union arg *args, char *spawn_name,
+    char ***ret_args)
+{
+       struct spawn_prog       *prog = NULL;
+       int                     i;
+       char                    *ap, **real_args;
+
+       DNPRINTF(SWM_D_SPAWN, "spawn_expand: %s\n", spawn_name);
+
+       /* find program */
+       TAILQ_FOREACH(prog, &spawns, entry) {
+               if (!strcasecmp(spawn_name, prog->name))
+                       break;
+       }
+       if (prog == NULL) {
+               warnx("spawn_custom: program %s not found", spawn_name);
+               return (-1);
+       }
+
+       /* make room for expanded args */
+       if ((real_args = calloc(prog->argc + 1, sizeof(char *))) == NULL)
+               err(1, "spawn_custom: calloc real_args");
+
+       /* expand spawn_args into real_args */
+       for (i = 0; i < prog->argc; i++) {
+               ap = prog->argv[i];
+               DNPRINTF(SWM_D_SPAWN, "spawn_custom: raw arg: %s\n", ap);
+               if (!strcasecmp(ap, "$bar_border")) {
+                       if ((real_args[i] =
+                           strdup(r->s->c[SWM_S_COLOR_BAR_BORDER].name))
+                           == NULL)
+                               err(1,  "spawn_custom border color");
+               } else if (!strcasecmp(ap, "$bar_color")) {
+                       if ((real_args[i] =
+                           strdup(r->s->c[SWM_S_COLOR_BAR].name))
+                           == NULL)
+                               err(1, "spawn_custom bar color");
+               } else if (!strcasecmp(ap, "$bar_font")) {
+                       if ((real_args[i] = strdup(bar_fonts))
+                           == NULL)
+                               err(1, "spawn_custom bar fonts");
+               } else if (!strcasecmp(ap, "$bar_font_color")) {
+                       if ((real_args[i] =
+                           strdup(r->s->c[SWM_S_COLOR_BAR_FONT].name))
+                           == NULL)
+                               err(1, "spawn_custom color font");
+               } else if (!strcasecmp(ap, "$color_focus")) {
+                       if ((real_args[i] =
+                           strdup(r->s->c[SWM_S_COLOR_FOCUS].name))
+                           == NULL)
+                               err(1, "spawn_custom color focus");
+               } else if (!strcasecmp(ap, "$color_unfocus")) {
+                       if ((real_args[i] =
+                           strdup(r->s->c[SWM_S_COLOR_UNFOCUS].name))
+                           == NULL)
+                               err(1, "spawn_custom color unfocus");
+               } else {
+                       /* no match --> copy as is */
+                       if ((real_args[i] = strdup(ap)) == NULL)
+                               err(1, "spawn_custom strdup(ap)");
+               }
+               DNPRINTF(SWM_D_SPAWN, "spawn_custom: cooked arg: %s\n",
+                   real_args[i]);
+       }
+
+#ifdef SWM_DEBUG
+       DNPRINTF(SWM_D_SPAWN, "spawn_custom: result: ");
+       for (i = 0; i < prog->argc; i++)
+               DNPRINTF(SWM_D_SPAWN, "\"%s\" ", real_args[i]);
+       DNPRINTF(SWM_D_SPAWN, "\n");
+#endif
+       *ret_args = real_args;
+       return (prog->argc);
+}
+
+void
+spawn_custom(struct swm_region *r, union arg *args, char *spawn_name)
+{
+       union arg               a;
+       char                    **real_args;
+       int                     spawn_argc, i;
+
+       if ((spawn_argc = spawn_expand(r, args, spawn_name, &real_args)) < 0)
+               return;
+       a.argv = real_args;
+       if (fork() == 0)
+               spawn(r->ws->idx, &a, 1);
+
+       for (i = 0; i < spawn_argc; i++)
+               free(real_args[i]);
+       free(real_args);
+}
+
+void
+spawn_select(struct swm_region *r, union arg *args, char *spawn_name, int *pid)
+{
+       union arg               a;
+       char                    **real_args;
+       int                     i, spawn_argc;
+
+       if ((spawn_argc = spawn_expand(r, args, spawn_name, &real_args)) < 0)
+               return;
+       a.argv = real_args;
+
+       if (pipe(select_list_pipe) == -1)
+               err(1, "pipe error");
+       if (pipe(select_resp_pipe) == -1)
+               err(1, "pipe error");
+
+       if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+               err(1, "could not disable SIGPIPE");
+       switch (*pid = fork()) {
+       case -1:
+               err(1, "cannot fork");
+               break;
+       case 0: /* child */
+               if (dup2(select_list_pipe[0], 0) == -1)
+                       err(1, "dup2");
+               if (dup2(select_resp_pipe[1], 1) == -1)
+                       err(1, "dup2");
+               close(select_list_pipe[1]);
+               close(select_resp_pipe[0]);
+               spawn(r->ws->idx, &a, 0);
+               break;
+       default: /* parent */
+               close(select_list_pipe[0]);
+               close(select_resp_pipe[1]);
+               break;
+       }
+
+       for (i = 0; i < spawn_argc; i++)
+               free(real_args[i]);
+       free(real_args);
+}
+
+void
+spawn_insert(char *name, char *args)
+{
+       char                    *arg, *cp, *ptr;
+       struct spawn_prog       *sp;
+
+       DNPRINTF(SWM_D_SPAWN, "spawn_insert: %s\n", name);
+
+       if ((sp = calloc(1, sizeof *sp)) == NULL)
+               err(1, "spawn_insert: malloc");
+       if ((sp->name = strdup(name)) == NULL)
+               err(1, "spawn_insert: strdup");
+
+       /* convert the arguments to an argument list */
+       if ((ptr = cp = strdup(args)) == NULL)
+               err(1, "spawn_insert: strdup");
+       while ((arg = strsep(&ptr, " \t")) != NULL) {
+               /* empty field; skip it */
+               if (*arg == '\0')
+                       continue;
+
+               sp->argc++;
+               if ((sp->argv = realloc(sp->argv, sp->argc *
+                   sizeof *sp->argv)) == NULL)
+                       err(1, "spawn_insert: realloc");
+               if ((sp->argv[sp->argc - 1] = strdup(arg)) == NULL)
+                       err(1, "spawn_insert: strdup");
+       }
+       free(cp);
+
+       TAILQ_INSERT_TAIL(&spawns, sp, entry);
+       DNPRINTF(SWM_D_SPAWN, "spawn_insert: leave\n");
+}
+
+void
+spawn_remove(struct spawn_prog *sp)
+{
+       int                     i;
+
+       DNPRINTF(SWM_D_SPAWN, "spawn_remove: %s\n", sp->name);
+
+       TAILQ_REMOVE(&spawns, sp, entry);
+       for (i = 0; i < sp->argc; i++)
+               free(sp->argv[i]);
+       free(sp->argv);
+       free(sp->name);
+       free(sp);
+
+       DNPRINTF(SWM_D_SPAWN, "spawn_remove: leave\n");
+}
+
+void
+spawn_replace(struct spawn_prog *sp, char *name, char *args)
+{
+       DNPRINTF(SWM_D_SPAWN, "spawn_replace: %s [%s]\n", sp->name, name);
+
+       spawn_remove(sp);
+       spawn_insert(name, args);
+
+       DNPRINTF(SWM_D_SPAWN, "spawn_replace: leave\n");
+}
+
+void
+setspawn(char *name, char *args)
+{
+       struct spawn_prog       *sp;
+
+       DNPRINTF(SWM_D_SPAWN, "setspawn: %s\n", name);
+
+       if (name == NULL)
+               return;
+
+       TAILQ_FOREACH(sp, &spawns, entry) {
+               if (!strcmp(sp->name, name)) {
+                       if (*args == '\0')
+                               spawn_remove(sp);
+                       else
+                               spawn_replace(sp, name, args);
+                       DNPRINTF(SWM_D_SPAWN, "setspawn: leave\n");
+                       return;
+               }
+       }
+       if (*args == '\0') {
+               warnx("error: setspawn: cannot find program: %s", name);
+               return;
+       }
+
+       spawn_insert(name, args);
+       DNPRINTF(SWM_D_SPAWN, "setspawn: leave\n");
+}
+
+int
+setconfspawn(char *selector, char *value, int flags)
+{
+       DNPRINTF(SWM_D_SPAWN, "setconfspawn: [%s] [%s]\n", selector, value);
+
+       setspawn(selector, value);
+
+       DNPRINTF(SWM_D_SPAWN, "setconfspawn: done\n");
+       return (0);
+}
+
+void
+setup_spawn(void)
+{
+       setconfspawn("term",            "xterm",                0);
+       setconfspawn("screenshot_all",  "screenshot.sh full",   0);
+       setconfspawn("screenshot_wind", "screenshot.sh window", 0);
+       setconfspawn("lock",            "xlock",                0);
+       setconfspawn("initscr",         "initscreen.sh",        0);
+       setconfspawn("menu",            "dmenu_run"
+                                       " -fn $bar_font"
+                                       " -nb $bar_color"
+                                       " -nf $bar_font_color"
+                                       " -sb $bar_border"
+                                       " -sf $bar_color",      0);
+       setconfspawn("search",          "dmenu"
+                                       " -i"
+                                       " -fn $bar_font"
+                                       " -nb $bar_color"
+                                       " -nf $bar_font_color"
+                                       " -sb $bar_border"
+                                       " -sf $bar_color",      0);
+       setconfspawn("name_workspace",  "dmenu"
+                                       " -p Workspace"
+                                       " -fn $bar_font"
+                                       " -nb $bar_color"
+                                       " -nf $bar_font_color"
+                                       " -sb $bar_border"
+                                       " -sf $bar_color",      0);
+}
+
+/* key bindings */
+#define SWM_MODNAME_SIZE       32
+#define        SWM_KEY_WS              "\n+ \t"
+int
+parsekeys(char *keystr, unsigned int currmod, unsigned int *mod, KeySym *ks)
+{
+       char                    *cp, *name;
+       KeySym                  uks;
+       DNPRINTF(SWM_D_KEY, "parsekeys: enter [%s]\n", keystr);
+       if (mod == NULL || ks == NULL) {
+               DNPRINTF(SWM_D_KEY, "parsekeys: no mod or key vars\n");
+               return (1);
+       }
+       if (keystr == NULL || strlen(keystr) == 0) {
+               DNPRINTF(SWM_D_KEY, "parsekeys: no keystr\n");
+               return (1);
+       }
+       cp = keystr;
+       *ks = NoSymbol;
+       *mod = 0;
+       while ((name = strsep(&cp, SWM_KEY_WS)) != NULL) {
+               DNPRINTF(SWM_D_KEY, "parsekeys: key [%s]\n", name);
+               if (cp)
+                       cp += (long)strspn(cp, SWM_KEY_WS);
+               if (strncasecmp(name, "MOD", SWM_MODNAME_SIZE) == 0)
+                       *mod |= currmod;
+               else if (!strncasecmp(name, "Mod1", SWM_MODNAME_SIZE))
+                       *mod |= Mod1Mask;
+               else if (!strncasecmp(name, "Mod2", SWM_MODNAME_SIZE))
+                       *mod += Mod2Mask;
+               else if (!strncmp(name, "Mod3", SWM_MODNAME_SIZE))
+                       *mod |= Mod3Mask;
+               else if (!strncmp(name, "Mod4", SWM_MODNAME_SIZE))
+                       *mod |= Mod4Mask;
+               else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0)
+                       *mod |= ShiftMask;
+               else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0)
+                       *mod |= ControlMask;
+               else {
+                       *ks = XStringToKeysym(name);
+                       XConvertCase(*ks, ks, &uks);
+                       if (ks == NoSymbol) {
+                               DNPRINTF(SWM_D_KEY,
+                                   "parsekeys: invalid key %s\n",
+                                   name);
+                               return (1);
+                       }
+               }
+       }
+       DNPRINTF(SWM_D_KEY, "parsekeys: leave ok\n");
+       return (0);
+}
+
+char *
+strdupsafe(char *str)
+{
+       if (str == NULL)
+               return (NULL);
+       else
+               return (strdup(str));
+}
+
+void
+key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid, char *spawn_name)
+{
+       struct key              *kp;
+
+       DNPRINTF(SWM_D_KEY, "key_insert: enter %s [%s]\n",
+           keyfuncs[kfid].name, spawn_name);
+
+       if ((kp = malloc(sizeof *kp)) == NULL)
+               err(1, "key_insert: malloc");
+
+       kp->mod = mod;
+       kp->keysym = ks;
+       kp->funcid = kfid;
+       kp->spawn_name = strdupsafe(spawn_name);
+       RB_INSERT(key_list, &keys, kp);
+
+       DNPRINTF(SWM_D_KEY, "key_insert: leave\n");
+}
+
+struct key *
+key_lookup(unsigned int mod, KeySym ks)
+{
+       struct key              kp;
+
+       kp.keysym = ks;
+       kp.mod = mod;
+
+       return (RB_FIND(key_list, &keys, &kp));
+}
+
+void
+key_remove(struct key *kp)
+{
+       DNPRINTF(SWM_D_KEY, "key_remove: %s\n", keyfuncs[kp->funcid].name);
+
+       RB_REMOVE(key_list, &keys, kp);
+       free(kp->spawn_name);
+       free(kp);
+
+       DNPRINTF(SWM_D_KEY, "key_remove: leave\n");
+}
+
+void
+key_replace(struct key *kp, unsigned int mod, KeySym ks, enum keyfuncid kfid,
+    char *spawn_name)
+{
+       DNPRINTF(SWM_D_KEY, "key_replace: %s [%s]\n", keyfuncs[kp->funcid].name,
+           spawn_name);
+
+       key_remove(kp);
+       key_insert(mod, ks, kfid, spawn_name);
+
+       DNPRINTF(SWM_D_KEY, "key_replace: leave\n");
+}
+
+void
+setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid,
+    char *spawn_name)
+{
+       struct key              *kp;
+
+       DNPRINTF(SWM_D_KEY, "setkeybinding: enter %s [%s]\n",
+           keyfuncs[kfid].name, spawn_name);
+
+       if ((kp = key_lookup(mod, ks)) != NULL) {
+               if (kfid == kf_invalid)
+                       key_remove(kp);
+               else
+                       key_replace(kp, mod, ks, kfid, spawn_name);
+               DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
+               return;
+       }
+       if (kfid == kf_invalid) {
+               warnx("error: setkeybinding: cannot find mod/key combination");
+               DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
+               return;
+       }
+
+       key_insert(mod, ks, kfid, spawn_name);
+       DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
+}
+
+int
+setconfbinding(char *selector, char *value, int flags)
+{
+       enum keyfuncid          kfid;
+       unsigned int            mod;
+       KeySym                  ks;
+       struct spawn_prog       *sp;
+       DNPRINTF(SWM_D_KEY, "setconfbinding: enter\n");
+       if (selector == NULL) {
+               DNPRINTF(SWM_D_KEY, "setconfbinding: unbind %s\n", value);
+               if (parsekeys(value, mod_key, &mod, &ks) == 0) {
+                       kfid = kf_invalid;
+                       setkeybinding(mod, ks, kfid, NULL);
+                       return (0);
+               } else
+                       return (1);
+       }
+       /* search by key function name */
+       for (kfid = 0; kfid < kf_invalid; (kfid)++) {
+               if (strncasecmp(selector, keyfuncs[kfid].name,
+                   SWM_FUNCNAME_LEN) == 0) {
+                       DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match\n",
+                           selector);
+                       if (parsekeys(value, mod_key, &mod, &ks) == 0) {
+                               setkeybinding(mod, ks, kfid, NULL);
+                               return (0);
+                       } else
+                               return (1);
+               }
+       }
+       /* search by custom spawn name */
+       TAILQ_FOREACH(sp, &spawns, entry) {
+               if (strcasecmp(selector, sp->name) == 0) {
+                       DNPRINTF(SWM_D_KEY, "setconfbinding: %s: match\n",
+                           selector);
+                       if (parsekeys(value, mod_key, &mod, &ks) == 0) {
+                               setkeybinding(mod, ks, kf_spawn_custom,
+                                   sp->name);
+                               return (0);
+                       } else
+                               return (1);
+               }
+       }
+       DNPRINTF(SWM_D_KEY, "setconfbinding: no match\n");
+       return (1);
+}
+
+void
+setup_keys(void)
+{
+       setkeybinding(MODKEY,           XK_space,       kf_cycle_layout,NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_backslash,   kf_flip_layout, NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_space,       kf_stack_reset, NULL);
+       setkeybinding(MODKEY,           XK_h,           kf_master_shrink,NULL);
+       setkeybinding(MODKEY,           XK_l,           kf_master_grow, NULL);
+       setkeybinding(MODKEY,           XK_comma,       kf_master_add,  NULL);
+       setkeybinding(MODKEY,           XK_period,      kf_master_del,  NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_comma,       kf_stack_inc,   NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_period,      kf_stack_dec,   NULL);
+       setkeybinding(MODKEY,           XK_Return,      kf_swap_main,   NULL);
+       setkeybinding(MODKEY,           XK_j,           kf_focus_next,  NULL);
+       setkeybinding(MODKEY,           XK_k,           kf_focus_prev,  NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_j,           kf_swap_next,   NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_k,           kf_swap_prev,   NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_Return,      kf_spawn_term,  NULL);
+       setkeybinding(MODKEY,           XK_p,           kf_spawn_custom,"menu");
+       setkeybinding(MODKEY|ShiftMask, XK_q,           kf_quit,        NULL);
+       setkeybinding(MODKEY,           XK_q,           kf_restart,     NULL);
+       setkeybinding(MODKEY,           XK_m,           kf_focus_main,  NULL);
+       setkeybinding(MODKEY,           XK_1,           kf_ws_1,        NULL);
+       setkeybinding(MODKEY,           XK_2,           kf_ws_2,        NULL);
+       setkeybinding(MODKEY,           XK_3,           kf_ws_3,        NULL);
+       setkeybinding(MODKEY,           XK_4,           kf_ws_4,        NULL);
+       setkeybinding(MODKEY,           XK_5,           kf_ws_5,        NULL);
+       setkeybinding(MODKEY,           XK_6,           kf_ws_6,        NULL);
+       setkeybinding(MODKEY,           XK_7,           kf_ws_7,        NULL);
+       setkeybinding(MODKEY,           XK_8,           kf_ws_8,        NULL);
+       setkeybinding(MODKEY,           XK_9,           kf_ws_9,        NULL);
+       setkeybinding(MODKEY,           XK_0,           kf_ws_10,       NULL);
+       setkeybinding(MODKEY,           XK_Right,       kf_ws_next,     NULL);
+       setkeybinding(MODKEY,           XK_Left,        kf_ws_prev,     NULL);
+       setkeybinding(MODKEY,           XK_Up,          kf_ws_next_all, NULL);
+       setkeybinding(MODKEY,           XK_Down,        kf_ws_prev_all, NULL);
+       setkeybinding(MODKEY,           XK_a,           kf_ws_prior,    NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_Right,       kf_screen_next, NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_Left,        kf_screen_prev, NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_1,           kf_mvws_1,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_2,           kf_mvws_2,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_3,           kf_mvws_3,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_4,           kf_mvws_4,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_5,           kf_mvws_5,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_6,           kf_mvws_6,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_7,           kf_mvws_7,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_8,           kf_mvws_8,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_9,           kf_mvws_9,      NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_0,           kf_mvws_10,     NULL);
+       setkeybinding(MODKEY,           XK_b,           kf_bar_toggle,  NULL);
+       setkeybinding(MODKEY,           XK_Tab,         kf_focus_next,  NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_Tab,         kf_focus_prev,  NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_x,           kf_wind_kill,   NULL);
+       setkeybinding(MODKEY,           XK_x,           kf_wind_del,    NULL);
+       setkeybinding(MODKEY,           XK_s,           kf_spawn_custom,"screenshot_all");
+       setkeybinding(MODKEY|ShiftMask, XK_s,           kf_spawn_custom,"screenshot_wind");
+       setkeybinding(MODKEY,           XK_t,           kf_float_toggle,NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_v,           kf_version,     NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_Delete,      kf_spawn_custom,"lock");
+       setkeybinding(MODKEY|ShiftMask, XK_i,           kf_spawn_custom,"initscr");
+       setkeybinding(MODKEY,           XK_w,           kf_iconify,     NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_w,           kf_uniconify,   NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_r,           kf_raise_toggle,NULL);
+       setkeybinding(MODKEY,           XK_v,           kf_button2,     NULL);
+       setkeybinding(MODKEY,           XK_equal,       kf_width_grow,  NULL);
+       setkeybinding(MODKEY,           XK_minus,       kf_width_shrink,NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_equal,       kf_height_grow, NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_minus,       kf_height_shrink,NULL);
+       setkeybinding(MODKEY,           XK_bracketleft, kf_move_left,   NULL);
+       setkeybinding(MODKEY,           XK_bracketright,kf_move_right,  NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_bracketleft, kf_move_up,     NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_bracketright,kf_move_down,   NULL);
+       setkeybinding(MODKEY|ShiftMask, XK_slash,       kf_name_workspace,NULL);
+       setkeybinding(MODKEY,           XK_slash,       kf_search_workspace,NULL);
+       setkeybinding(MODKEY,           XK_f,           kf_search_win,  NULL);
+#ifdef SWM_DEBUG
+       setkeybinding(MODKEY|ShiftMask, XK_d,           kf_dumpwins,    NULL);
+#endif
+}
+
+void
+clear_keys(void)
+{
+       struct key              *kp;
+
+       while (RB_EMPTY(&keys) == 0) {
+               kp = RB_ROOT(&keys);
+               key_remove(kp);
+       }
+}
+
+int
+setkeymapping(char *selector, char *value, int flags)
+{
+       char                    keymapping_file[PATH_MAX];
+       DNPRINTF(SWM_D_KEY, "setkeymapping: enter\n");
+       if (value[0] == '~')
+               snprintf(keymapping_file, sizeof keymapping_file, "%s/%s",
+                   pwd->pw_dir, &value[1]);
+       else
+               strlcpy(keymapping_file, value, sizeof keymapping_file);
+       clear_keys();
+       /* load new key bindings; if it fails, revert to default bindings */
+       if (conf_load(keymapping_file, SWM_CONF_KEYMAPPING)) {
+               clear_keys();
+               setup_keys();
+       }
+       DNPRINTF(SWM_D_KEY, "setkeymapping: leave\n");
+       return (0);
+}
+
+void
+updatenumlockmask(void)
+{
+       unsigned int            i, j;
+       XModifierKeymap         *modmap;
+
+       DNPRINTF(SWM_D_MISC, "updatenumlockmask\n");
+       numlockmask = 0;
+       modmap = XGetModifierMapping(display);
+       for (i = 0; i < 8; i++)
+               for (j = 0; j < modmap->max_keypermod; j++)
+                       if (modmap->modifiermap[i * modmap->max_keypermod + j]
+                           == XKeysymToKeycode(display, XK_Num_Lock))
+                               numlockmask = (1 << i);
+
+       XFreeModifiermap(modmap);
+}
+
+void
+grabkeys(void)
+{
+       unsigned int            j, k;
+       KeyCode                 code;
+       unsigned int            modifiers[] =
+           { 0, LockMask, numlockmask, numlockmask | LockMask };
+       struct key              *kp;
+
+       DNPRINTF(SWM_D_MISC, "grabkeys\n");
+       updatenumlockmask();
+
+       for (k = 0; k < ScreenCount(display); k++) {
+               if (TAILQ_EMPTY(&screens[k].rl))
+                       continue;
+               XUngrabKey(display, AnyKey, AnyModifier, screens[k].root);
+               RB_FOREACH(kp, key_list, &keys) {
+                       if ((code = XKeysymToKeycode(display, kp->keysym)))
+                               for (j = 0; j < LENGTH(modifiers); j++)
+                                       XGrabKey(display, code,
+                                           kp->mod | modifiers[j],
+                                           screens[k].root, True,
+                                           GrabModeAsync, GrabModeAsync);
+               }
+       }
+}
+
+void
+grabbuttons(struct ws_win *win, int focused)
+{
+       unsigned int            i, j;
+       unsigned int            modifiers[] =
+           { 0, LockMask, numlockmask, numlockmask|LockMask };
+
+       updatenumlockmask();
+       XUngrabButton(display, AnyButton, AnyModifier, win->id);
+       if (focused) {
+               for (i = 0; i < LENGTH(buttons); i++)
+                       if (buttons[i].action == client_click)
+                               for (j = 0; j < LENGTH(modifiers); j++)
+                                       XGrabButton(display, buttons[i].button,
+                                           buttons[i].mask | modifiers[j],
+                                           win->id, False, BUTTONMASK,
+                                           GrabModeAsync, GrabModeSync, None,
+                                           None);
+       } else
+               XGrabButton(display, AnyButton, AnyModifier, win->id, False,
+                   BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
+}
+
+const char *quirkname[] = {
+       "NONE",         /* config string for "no value" */
+       "FLOAT",
+       "TRANSSZ",
+       "ANYWHERE",
+       "XTERM_FONTADJ",
+       "FULLSCREEN",
+       "FOCUSPREV",
+};
+
+/* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */
+#define        SWM_Q_WS                "\n|+ \t"
+int
+parsequirks(char *qstr, unsigned long *quirk)
+{
+       char                    *cp, *name;
+       int                     i;
+
+       if (quirk == NULL)
+               return (1);
+
+       cp = qstr;
+       *quirk = 0;
+       while ((name = strsep(&cp, SWM_Q_WS)) != NULL) {
+               if (cp)
+                       cp += (long)strspn(cp, SWM_Q_WS);
+               for (i = 0; i < LENGTH(quirkname); i++) {
+                       if (!strncasecmp(name, quirkname[i], SWM_QUIRK_LEN)) {
+                               DNPRINTF(SWM_D_QUIRK,
+                                   "parsequirks: %s\n", name);
+                               if (i == 0) {
+                                       *quirk = 0;
+                                       return (0);
+                               }
+                               *quirk |= 1 << (i-1);
+                               break;
+                       }
+               }
+               if (i >= LENGTH(quirkname)) {
+                       DNPRINTF(SWM_D_QUIRK,
+                           "parsequirks: invalid quirk [%s]\n", name);
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+void
+quirk_insert(const char *class, const char *name, unsigned long quirk)
+{
+       struct quirk            *qp;
+
+       DNPRINTF(SWM_D_QUIRK, "quirk_insert: %s:%s [%lu]\n", class, name,
+           quirk);
+
+       if ((qp = malloc(sizeof *qp)) == NULL)
+               err(1, "quirk_insert: malloc");
+       if ((qp->class = strdup(class)) == NULL)
+               err(1, "quirk_insert: strdup");
+       if ((qp->name = strdup(name)) == NULL)
+               err(1, "quirk_insert: strdup");
+
+       qp->quirk = quirk;
+       TAILQ_INSERT_TAIL(&quirks, qp, entry);
+
+       DNPRINTF(SWM_D_QUIRK, "quirk_insert: leave\n");
+}
+
+void
+quirk_remove(struct quirk *qp)
+{
+       DNPRINTF(SWM_D_QUIRK, "quirk_remove: %s:%s [%lu]\n", qp->class,
+           qp->name, qp->quirk);
+
+       TAILQ_REMOVE(&quirks, qp, entry);
+       free(qp->class);
+       free(qp->name);
+       free(qp);
+
+       DNPRINTF(SWM_D_QUIRK, "quirk_remove: leave\n");
+}
+
+void
+quirk_replace(struct quirk *qp, const char *class, const char *name,
+    unsigned long quirk)
+{
+       DNPRINTF(SWM_D_QUIRK, "quirk_replace: %s:%s [%lu]\n", qp->class,
+           qp->name, qp->quirk);
+
+       quirk_remove(qp);
+       quirk_insert(class, name, quirk);
+
+       DNPRINTF(SWM_D_QUIRK, "quirk_replace: leave\n");
+}
+
+void
+setquirk(const char *class, const char *name, unsigned long quirk)
+{
+       struct quirk            *qp;
+
+       DNPRINTF(SWM_D_QUIRK, "setquirk: enter %s:%s [%lu]\n", class, name,
+          quirk);
+
+       TAILQ_FOREACH(qp, &quirks, entry) {
+               if (!strcmp(qp->class, class) && !strcmp(qp->name, name)) {
+                       if (!quirk)
+                               quirk_remove(qp);
+                       else
+                               quirk_replace(qp, class, name, quirk);
+                       DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
+                       return;
+               }
+       }
+       if (!quirk) {
+               warnx("error: setquirk: cannot find class/name combination");
+               return;
+       }
+
+       quirk_insert(class, name, quirk);
+       DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
+}
+
+int
+setconfquirk(char *selector, char *value, int flags)
+{
+       char                    *cp, *class, *name;
+       int                     retval;
+       unsigned long           quirks;
+       if (selector == NULL)
+               return (0);
+       if ((cp = strchr(selector, ':')) == NULL)
+               return (0);
+       *cp = '\0';
+       class = selector;
+       name = cp + 1;
+       if ((retval = parsequirks(value, &quirks)) == 0)
+               setquirk(class, name, quirks);
+       return (retval);
+}
+
+void
+setup_quirks(void)
+{
+       setquirk("MPlayer",             "xv",           SWM_Q_FLOAT | SWM_Q_FULLSCREEN | SWM_Q_FOCUSPREV);
+       setquirk("OpenOffice.org 3.2",  "VCLSalFrame",  SWM_Q_FLOAT);
+       setquirk("Firefox-bin",         "firefox-bin",  SWM_Q_TRANSSZ);
+       setquirk("Firefox",             "Dialog",       SWM_Q_FLOAT);
+       setquirk("Gimp",                "gimp",         SWM_Q_FLOAT | SWM_Q_ANYWHERE);
+       setquirk("XTerm",               "xterm",        SWM_Q_XTERM_FONTADJ);
+       setquirk("xine",                "Xine Window",  SWM_Q_FLOAT | SWM_Q_ANYWHERE);
+       setquirk("Xitk",                "Xitk Combo",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
+       setquirk("xine",                "xine Panel",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
+       setquirk("Xitk",                "Xine Window",  SWM_Q_FLOAT | SWM_Q_ANYWHERE);
+       setquirk("xine",                "xine Video Fullscreen Window", SWM_Q_FULLSCREEN | SWM_Q_FLOAT);
+       setquirk("pcb",                 "pcb",          SWM_Q_FLOAT);
+       setquirk("SDL_App",             "SDL_App",      SWM_Q_FLOAT | SWM_Q_FULLSCREEN);
+}
+
+/* conf file stuff */
+#define SWM_CONF_FILE          "spectrwm.conf"
+#define SWM_CONF_FILE_OLD      "scrotwm.conf"
+
+enum   { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_BAR_BORDER_WIDTH,
+         SWM_S_STACK_ENABLED, SWM_S_CLOCK_ENABLED, SWM_S_CLOCK_FORMAT,
+         SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, SWM_S_SS_ENABLED,
+         SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED,
+         SWM_S_TITLE_NAME_ENABLED, SWM_S_WINDOW_NAME_ENABLED, SWM_S_URGENT_ENABLED,
+         SWM_S_FOCUS_MODE, SWM_S_DISABLE_BORDER, SWM_S_BORDER_WIDTH,
+         SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM,
+         SWM_S_SS_APP, SWM_S_DIALOG_RATIO, SWM_S_BAR_AT_BOTTOM,
+         SWM_S_VERBOSE_LAYOUT, SWM_S_BAR_JUSTIFY
+       };
+
+int
+setconfvalue(char *selector, char *value, int flags)
+{
+       int     i;
+       char    *b;
+
+       switch (flags) {
+       case SWM_S_BAR_DELAY:
+               bar_delay = atoi(value);
+               break;
+       case SWM_S_BAR_ENABLED:
+               bar_enabled = atoi(value);
+               break;
+       case SWM_S_BAR_BORDER_WIDTH:
+               bar_border_width = atoi(value);
+               break;
+       case SWM_S_BAR_AT_BOTTOM:
+               bar_at_bottom = atoi(value);
+               break;
+       case SWM_S_BAR_JUSTIFY:
+               if (!strcmp(value, "left"))
+                       bar_justify = SWM_BAR_JUSTIFY_LEFT;
+               else if (!strcmp(value, "center"))
+                       bar_justify = SWM_BAR_JUSTIFY_CENTER;
+               else if (!strcmp(value, "right"))
+                       bar_justify = SWM_BAR_JUSTIFY_RIGHT;
+               else
+                       errx(1, "invalid bar_justify");
+               break;
+       case SWM_S_STACK_ENABLED:
+               stack_enabled = atoi(value);
+               break;
+       case SWM_S_CLOCK_ENABLED:
+               clock_enabled = atoi(value);
+               break;
+       case SWM_S_CLOCK_FORMAT:
+#ifndef SWM_DENY_CLOCK_FORMAT
+               free(clock_format);
+               if ((clock_format = strdup(value)) == NULL)
+                       err(1, "setconfvalue: clock_format");
+#endif
+               break;
+       case SWM_S_CYCLE_EMPTY:
+               cycle_empty = atoi(value);
+               break;
+       case SWM_S_CYCLE_VISIBLE:
+               cycle_visible = atoi(value);
+               break;
+       case SWM_S_SS_ENABLED:
+               ss_enabled = atoi(value);
+               break;
+       case SWM_S_TERM_WIDTH:
+               term_width = atoi(value);
+               break;
+       case SWM_S_TITLE_CLASS_ENABLED:
+               title_class_enabled = atoi(value);
+               break;
+       case SWM_S_WINDOW_NAME_ENABLED:
+               window_name_enabled = atoi(value);
+               break;
+       case SWM_S_TITLE_NAME_ENABLED:
+               title_name_enabled = atoi(value);
+               break;
+       case SWM_S_URGENT_ENABLED:
+               urgent_enabled = atoi(value);
+               break;
+       case SWM_S_FOCUS_MODE:
+               if (!strcmp(value, "default"))
+                       focus_mode = SWM_FOCUS_DEFAULT;
+               else if (!strcmp(value, "follow_cursor"))
+                       focus_mode = SWM_FOCUS_FOLLOW;
+               else if (!strcmp(value, "synergy"))
+                       focus_mode = SWM_FOCUS_SYNERGY;
+               else
+                       errx(1, "focus_mode");
+               break;
+       case SWM_S_DISABLE_BORDER:
+               disable_border = atoi(value);
+               break;
+       case SWM_S_BORDER_WIDTH:
+               border_width = atoi(value);
+               break;
+       case SWM_S_BAR_FONT:
+               b = bar_fonts;
+               if (asprintf(&bar_fonts, "%s,%s", value, bar_fonts) == -1)
+                       err(1, "setconfvalue: asprintf: failed to allocate "
+                               "memory for bar_fonts.");
+
+               free(b);
+               break;
+       case SWM_S_BAR_ACTION:
+               free(bar_argv[0]);
+               if ((bar_argv[0] = strdup(value)) == NULL)
+                       err(1, "setconfvalue: bar_action");
+               break;
+       case SWM_S_SPAWN_TERM:
+               free(spawn_term[0]);
+               if ((spawn_term[0] = strdup(value)) == NULL)
+                       err(1, "setconfvalue: spawn_term");
+               break;
+       case SWM_S_SS_APP:
+               break;
+       case SWM_S_DIALOG_RATIO:
+               dialog_ratio = atof(value);
+               if (dialog_ratio > 1.0 || dialog_ratio <= .3)
+                       dialog_ratio = .6;
+               break;
+       case SWM_S_VERBOSE_LAYOUT:
+               verbose_layout = atoi(value);
+               for (i = 0; layouts[i].l_stack != NULL; i++) {
+                       if (verbose_layout)
+                               layouts[i].l_string = fancy_stacker;
+                       else
+                               layouts[i].l_string = plain_stacker;
+               }
+               break;
+       default:
+               return (1);
+       }
+       return (0);
+}
+
+int
+setconfmodkey(char *selector, char *value, int flags)
+{
+       if (!strncasecmp(value, "Mod1", strlen("Mod1")))
+               update_modkey(Mod1Mask);
+       else if (!strncasecmp(value, "Mod2", strlen("Mod2")))
+               update_modkey(Mod2Mask);
+       else if (!strncasecmp(value, "Mod3", strlen("Mod3")))
+               update_modkey(Mod3Mask);
+       else if (!strncasecmp(value, "Mod4", strlen("Mod4")))
+               update_modkey(Mod4Mask);
+       else
+               return (1);
+       return (0);
+}
+
+int
+setconfcolor(char *selector, char *value, int flags)
+{
+       setscreencolor(value, ((selector == NULL)?-1:atoi(selector)), flags);
+       return (0);
+}
+
+int
+setconfregion(char *selector, char *value, int flags)
+{
+       custom_region(value);
+       return (0);
+}
+
+int
+setautorun(char *selector, char *value, int flags)
+{
+       int                     ws_id;
+       char                    s[1024];
+       char                    *ap, *sp = s;
+       union arg               a;
+       int                     argc = 0;
+       long                    pid;
+       struct pid_e            *p;
+
+       if (getenv("SWM_STARTED"))
+               return (0);
+
+       bzero(s, sizeof s);
+       if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2)
+               errx(1, "invalid autorun entry, should be 'ws[<idx>]:command'");
+       ws_id--;
+       if (ws_id < 0 || ws_id >= SWM_WS_MAX)
+               errx(1, "autorun: invalid workspace %d", ws_id + 1);
+
+       /*
+        * This is a little intricate
+        *
+        * If the pid already exists we simply reuse it because it means it was
+        * used before AND not claimed by manage_window.  We get away with
+        * altering it in the parent after INSERT because this can not be a race
+        */
+       a.argv = NULL;
+       while ((ap = strsep(&sp, " \t")) != NULL) {
+               if (*ap == '\0')
+                       continue;
+               DNPRINTF(SWM_D_SPAWN, "setautorun: arg [%s]\n", ap);
+               argc++;
+               if ((a.argv = realloc(a.argv, argc * sizeof(char *))) == NULL)
+                       err(1, "setautorun: realloc");
+               a.argv[argc - 1] = ap;
+       }
+
+       if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL)
+               err(1, "setautorun: realloc");
+       a.argv[argc] = NULL;
+
+       if ((pid = fork()) == 0) {
+               spawn(ws_id, &a, 1);
+               /* NOTREACHED */
+               _exit(1);
+       }
+       free(a.argv);
+
+       /* parent */
+       p = find_pid(pid);
+       if (p == NULL) {
+               p = calloc(1, sizeof *p);
+               if (p == NULL)
+                       return (1);
+               TAILQ_INSERT_TAIL(&pidlist, p, entry);
+       }
+
+       p->pid = pid;
+       p->ws = ws_id;
+
+       return (0);
+}
+
+int
+setlayout(char *selector, char *value, int flags)
+{
+       int                     ws_id, i, x, mg, ma, si, raise;
+       int                     st = SWM_V_STACK;
+       char                    s[1024];
+       struct workspace        *ws;
+
+       if (getenv("SWM_STARTED"))
+               return (0);
+
+       bzero(s, sizeof s);
+       if (sscanf(value, "ws[%d]:%d:%d:%d:%d:%1023c",
+           &ws_id, &mg, &ma, &si, &raise, s) != 6)
+               errx(1, "invalid layout entry, should be 'ws[<idx>]:"
+                   "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
+                   "<type>'");
+       ws_id--;
+       if (ws_id < 0 || ws_id >= SWM_WS_MAX)
+               errx(1, "layout: invalid workspace %d", ws_id + 1);
+
+       if (!strcasecmp(s, "vertical"))
+               st = SWM_V_STACK;
+       else if (!strcasecmp(s, "horizontal"))
+               st = SWM_H_STACK;
+       else if (!strcasecmp(s, "fullscreen"))
+               st = SWM_MAX_STACK;
+       else
+               errx(1, "invalid layout entry, should be 'ws[<idx>]:"
+                   "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
+                   "<type>'");
+
+       for (i = 0; i < ScreenCount(display); i++) {
+               ws = (struct workspace *)&screens[i].ws;
+               ws[ws_id].cur_layout = &layouts[st];
+
+               ws[ws_id].always_raise = raise;
+               if (st == SWM_MAX_STACK)
+                       continue;
+
+               /* master grow */
+               for (x = 0; x < abs(mg); x++) {
+                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
+                           mg >= 0 ?  SWM_ARG_ID_MASTERGROW :
+                           SWM_ARG_ID_MASTERSHRINK);
+                       stack();
+               }
+               /* master add */
+               for (x = 0; x < abs(ma); x++) {
+                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
+                           ma >= 0 ?  SWM_ARG_ID_MASTERADD :
+                           SWM_ARG_ID_MASTERDEL);
+                       stack();
+               }
+               /* stack inc */
+               for (x = 0; x < abs(si); x++) {
+                       ws[ws_id].cur_layout->l_config(&ws[ws_id],
+                           si >= 0 ?  SWM_ARG_ID_STACKINC :
+                           SWM_ARG_ID_STACKDEC);
+                       stack();
+               }
+       }
+
+       return (0);
+}
+
+/* config options */
+struct config_option {
+       char                    *optname;
+       int                     (*func)(char*, char*, int);
+       int                     funcflags;
+};
+struct config_option configopt[] = {
+       { "bar_enabled",                setconfvalue,   SWM_S_BAR_ENABLED },
+       { "bar_at_bottom",              setconfvalue,   SWM_S_BAR_AT_BOTTOM },
+       { "bar_border",                 setconfcolor,   SWM_S_COLOR_BAR_BORDER },
+       { "bar_border_width",           setconfvalue,   SWM_S_BAR_BORDER_WIDTH },
+       { "bar_color",                  setconfcolor,   SWM_S_COLOR_BAR },
+       { "bar_font_color",             setconfcolor,   SWM_S_COLOR_BAR_FONT },
+       { "bar_font",                   setconfvalue,   SWM_S_BAR_FONT },
+       { "bar_action",                 setconfvalue,   SWM_S_BAR_ACTION },
+       { "bar_delay",                  setconfvalue,   SWM_S_BAR_DELAY },
+       { "bar_justify",                setconfvalue,   SWM_S_BAR_JUSTIFY },
+       { "keyboard_mapping",           setkeymapping,  0 },
+       { "bind",                       setconfbinding, 0 },
+       { "stack_enabled",              setconfvalue,   SWM_S_STACK_ENABLED },
+       { "clock_enabled",              setconfvalue,   SWM_S_CLOCK_ENABLED },
+       { "clock_format",               setconfvalue,   SWM_S_CLOCK_FORMAT },
+       { "color_focus",                setconfcolor,   SWM_S_COLOR_FOCUS },
+       { "color_unfocus",              setconfcolor,   SWM_S_COLOR_UNFOCUS },
+       { "cycle_empty",                setconfvalue,   SWM_S_CYCLE_EMPTY },
+       { "cycle_visible",              setconfvalue,   SWM_S_CYCLE_VISIBLE },
+       { "dialog_ratio",               setconfvalue,   SWM_S_DIALOG_RATIO },
+       { "verbose_layout",             setconfvalue,   SWM_S_VERBOSE_LAYOUT },
+       { "modkey",                     setconfmodkey,  0 },
+       { "program",                    setconfspawn,   0 },
+       { "quirk",                      setconfquirk,   0 },
+       { "region",                     setconfregion,  0 },
+       { "spawn_term",                 setconfvalue,   SWM_S_SPAWN_TERM },
+       { "screenshot_enabled",         setconfvalue,   SWM_S_SS_ENABLED },
+       { "screenshot_app",             setconfvalue,   SWM_S_SS_APP },
+       { "window_name_enabled",        setconfvalue,   SWM_S_WINDOW_NAME_ENABLED },
+       { "urgent_enabled",             setconfvalue,   SWM_S_URGENT_ENABLED },
+       { "term_width",                 setconfvalue,   SWM_S_TERM_WIDTH },
+       { "title_class_enabled",        setconfvalue,   SWM_S_TITLE_CLASS_ENABLED },
+       { "title_name_enabled",         setconfvalue,   SWM_S_TITLE_NAME_ENABLED },
+       { "focus_mode",                 setconfvalue,   SWM_S_FOCUS_MODE },
+       { "disable_border",             setconfvalue,   SWM_S_DISABLE_BORDER },
+       { "border_width",               setconfvalue,   SWM_S_BORDER_WIDTH },
+       { "autorun",                    setautorun,     0 },
+       { "layout",                     setlayout,      0 },
+};
+
+
+int
+conf_load(char *filename, int keymapping)
+{
+       FILE                    *config;
+       char                    *line, *cp, *optsub, *optval;
+       size_t                  linelen, lineno = 0;
+       int                     wordlen, i, optind;
+       struct config_option    *opt;
+
+       DNPRINTF(SWM_D_CONF, "conf_load: begin\n");
+
+       if (filename == NULL) {
+               warnx("conf_load: no filename");
+               return (1);
+       }
+       if ((config = fopen(filename, "r")) == NULL) {
+               warn("conf_load: fopen: %s", filename);
+               return (1);
+       }
+
+       while (!feof(config)) {
+               if ((line = fparseln(config, &linelen, &lineno, NULL, 0))
+                   == NULL) {
+                       if (ferror(config))
+                               err(1, "%s", filename);
+                       else
+                               continue;
+               }
+               cp = line;
+               cp += strspn(cp, " \t\n"); /* eat whitespace */
+               if (cp[0] == '\0') {
+                       /* empty line */
+                       free(line);
+                       continue;
+               }
+               /* get config option */
+               wordlen = strcspn(cp, "=[ \t\n");
+               if (wordlen == 0) {
+                       warnx("%s: line %zd: no option found",
+                           filename, lineno);
+                       goto out;
+               }
+               optind = -1;
+               for (i = 0; i < LENGTH(configopt); i++) {
+                       opt = &configopt[i];
+                       if (!strncasecmp(cp, opt->optname, wordlen) &&
+                           strlen(opt->optname) == wordlen) {
+                               optind = i;
+                               break;
+                       }
+               }
+               if (optind == -1) {
+                       warnx("%s: line %zd: unknown option %.*s",
+                           filename, lineno, wordlen, cp);
+                       goto out;
+               }
+               if (keymapping && strcmp(opt->optname, "bind")) {
+                       warnx("%s: line %zd: invalid option %.*s",
+                           filename, lineno, wordlen, cp);
+                       goto out;
+               }
+               cp += wordlen;
+               cp += strspn(cp, " \t\n"); /* eat whitespace */
+               /* get [selector] if any */
+               optsub = NULL;
+               if (*cp == '[') {
+                       cp++;
+                       wordlen = strcspn(cp, "]");
+                       if (*cp != ']') {
+                               if (wordlen == 0) {
+                                       warnx("%s: line %zd: syntax error",
+                                           filename, lineno);
+                                       goto out;
+                               }
+
+                               if (asprintf(&optsub, "%.*s", wordlen, cp) ==
+                                   -1) {
+                                       warnx("%s: line %zd: unable to allocate"
+                                           "memory for selector", filename,
+                                           lineno);
+                                       goto out;
+                               }
+                       }
+                       cp += wordlen;
+                       cp += strspn(cp, "] \t\n"); /* eat trailing */
+               }
+               cp += strspn(cp, "= \t\n"); /* eat trailing */
+               /* get RHS value */
+               optval = strdup(cp);
+               /* call function to deal with it all */
+               if (configopt[optind].func(optsub, optval,
+                   configopt[optind].funcflags) != 0)
+                       errx(1, "%s: line %zd: invalid data for %s",
+                           filename, lineno, configopt[optind].optname);
+               free(optval);
+               free(optsub);
+               free(line);
+       }
+
+       fclose(config);
+       DNPRINTF(SWM_D_CONF, "conf_load: end\n");
+
+       return (0);
+
+out:
+       free(line);
+       fclose(config);
+       DNPRINTF(SWM_D_CONF, "conf_load: end with error.\n");
+
+       return (1);
+}
+
+void
+set_child_transient(struct ws_win *win, Window *trans)
+{
+       struct ws_win           *parent, *w;
+       XWMHints                *wmh = NULL;
+       struct swm_region       *r;
+       struct workspace        *ws;
+
+       parent = find_window(win->transient);
+       if (parent)
+               parent->child_trans = win;
+       else {
+               DNPRINTF(SWM_D_MISC, "set_child_transient: parent doesn't exist"
+                   " for 0x%lx trans 0x%lx\n", win->id, win->transient);
+
+               if (win->hints == NULL) {
+                       warnx("no hints for 0x%lx", win->id);
+                       return;
+               }
+
+               r = root_to_region(win->wa.root);
+               ws = r->ws;
+               /* parent doen't exist in our window list */
+               TAILQ_FOREACH(w, &ws->winlist, entry) {
+                       if (wmh)
+                               XFree(wmh);
+
+                       if ((wmh = XGetWMHints(display, w->id)) == NULL) {
+                               warnx("can't get hints for 0x%lx", w->id);
+                               continue;
+                       }
+
+                       if (win->hints->window_group != wmh->window_group)
+                               continue;
+
+                       w->child_trans = win;
+                       win->transient = w->id;
+                       *trans = w->id;
+                       DNPRINTF(SWM_D_MISC, "set_child_transient: asjusting "
+                           "transient to 0x%lx\n", win->transient);
+                       break;
+               }
+       }
+
+       if (wmh)
+               XFree(wmh);
+}
+
+long
+window_get_pid(Window win)
+{
+       Atom                    actual_type_return;
+       int                     actual_format_return = 0;
+       unsigned long           nitems_return = 0;
+       unsigned long           bytes_after_return = 0;
+       long                    *pid = NULL;
+       long                    ret = 0;
+       const char              *errstr;
+       unsigned char           *prop = NULL;
+
+       if (XGetWindowProperty(display, win,
+           XInternAtom(display, "_NET_WM_PID", False), 0, 1, False,
+           XA_CARDINAL, &actual_type_return, &actual_format_return,
+           &nitems_return, &bytes_after_return,
+           (unsigned char**)(void*)&pid) != Success)
+               goto tryharder;
+       if (actual_type_return != XA_CARDINAL)
+               goto tryharder;
+       if (pid == NULL)
+               goto tryharder;
+
+       ret = *pid;
+       XFree(pid);
+
+       return (ret);
+
+tryharder:
+       if (XGetWindowProperty(display, win,
+           XInternAtom(display, "_SWM_PID", False), 0, SWM_PROPLEN, False,
+           XA_STRING, &actual_type_return, &actual_format_return,
+           &nitems_return, &bytes_after_return, &prop) != Success)
+               return (0);
+       if (actual_type_return != XA_STRING)
+               return (0);
+       if (prop == NULL)
+               return (0);
+
+       ret = strtonum((const char *)prop, 0, UINT_MAX, &errstr);
+       /* ignore error because strtonum returns 0 anyway */
+       XFree(prop);
+
+       return (ret);
+}
+
+struct ws_win *
+manage_window(Window id)
+{
+       Window                  trans = 0;
+       struct workspace        *ws;
+       struct ws_win           *win, *ww;
+       int                     format, i, ws_idx, n, border_me = 0;
+       unsigned long           nitems, bytes;
+       Atom                    ws_idx_atom = 0, type;
+       Atom                    *prot = NULL, *pp;
+       unsigned char           ws_idx_str[SWM_PROPLEN], *prop = NULL;
+       struct swm_region       *r;
+       long                    mask;
+       const char              *errstr;
+       XWindowChanges          wc;
+       struct pid_e            *p;
+       struct quirk            *qp;
+
+       if ((win = find_window(id)) != NULL)
+               return (win);   /* already being managed */
+
+       /* see if we are on the unmanaged list */
+       if ((win = find_unmanaged_window(id)) != NULL) {
+               DNPRINTF(SWM_D_MISC, "manage_window: previously unmanaged "
+                   "window: 0x%lx\n", win->id);
+               TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
+               if (win->transient) {
+                       set_child_transient(win, &trans);
+               } if (trans && (ww = find_window(trans)))
+                       TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
+               else
+                       TAILQ_INSERT_TAIL(&win->ws->winlist, win, entry);
+               ewmh_update_actions(win);
+               return (win);
+       }
+
+       if ((win = calloc(1, sizeof(struct ws_win))) == NULL)
+               err(1, "manage_window: calloc: failed to allocate memory for "
+                   "new window");
+
+       win->id = id;
+
+       /* see if we need to override the workspace */
+       p = find_pid(window_get_pid(id));
+
+       /* Get all the window data in one shot */
+       ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
+       if (ws_idx_atom) {
+               XGetWindowProperty(display, id, ws_idx_atom, 0, SWM_PROPLEN,
+                   False, XA_STRING, &type, &format, &nitems, &bytes, &prop);
+       }
+       XGetWindowAttributes(display, id, &win->wa);
+       XGetWMNormalHints(display, id, &win->sh, &win->sh_mask);
+       win->hints = XGetWMHints(display, id);
+       XGetTransientForHint(display, id, &trans);
+       if (trans) {
+               win->transient = trans;
+               set_child_transient(win, &trans);
+               DNPRINTF(SWM_D_MISC, "manage_window: window: 0x%lx, "
+                   "transient: 0x%lx\n", win->id, win->transient);
+       }
+
+       /* get supported protocols */
+       if (XGetWMProtocols(display, id, &prot, &n)) {
+               for (i = 0, pp = prot; i < n; i++, pp++) {
+                       if (*pp == takefocus)
+                               win->take_focus = 1;
+                       if (*pp == adelete)
+                               win->can_delete = 1;
+               }
+               if (prot)
+                       XFree(prot);
+       }
+
+       win->iconic = get_iconic(win);
+
+       /*
+        * Figure out where to put the window. If it was previously assigned to
+        * a workspace (either by spawn() or manually moving), and isn't
+        * transient, * put it in the same workspace
+        */
+       r = root_to_region(win->wa.root);
+       if (p) {
+               ws = &r->s->ws[p->ws];
+               TAILQ_REMOVE(&pidlist, p, entry);
+               free(p);
+               p = NULL;
+       } else if (prop && win->transient == 0) {
+               DNPRINTF(SWM_D_PROP, "manage_window: get _SWM_WS: %s\n", prop);
+               ws_idx = strtonum((const char *)prop, 0, 9, &errstr);
+               if (errstr) {
+                       DNPRINTF(SWM_D_EVENT, "manage_window: window: #%s: %s",
+                           errstr, prop);
+               }
+               ws = &r->s->ws[ws_idx];
+       } else {
+               ws = r->ws;
+               /* this should launch transients in the same ws as parent */
+               if (id && trans)
+                       if ((ww = find_window(trans)) != NULL)
+                               if (ws->r) {
+                                       ws = ww->ws;
+                                       if (ww->ws->r)
+                                               r = ww->ws->r;
+                                       else
+                                               warnx("manage_window: fix this "
+                                                   "bug mcbride");
+                                       border_me = 1;
+                               }
+       }
+
+       /* set up the window layout */
+       win->id = id;
+       win->ws = ws;
+       win->s = r->s;  /* this never changes */
+       if (trans && (ww = find_window(trans)))
+               TAILQ_INSERT_AFTER(&ws->winlist, ww, win, entry);
+       else
+               TAILQ_INSERT_TAIL(&ws->winlist, win, entry);
+
+       WIDTH(win) = win->wa.width;
+       HEIGHT(win) = win->wa.height;
+       X(win) = win->wa.x;
+       Y(win) = win->wa.y;
+       win->g_floatvalid = 0;
+       win->floatmaxed = 0;
+       win->ewmh_flags = 0;
+
+       /* Set window properties so we can remember this after reincarnation */
+       if (ws_idx_atom && prop == NULL &&
+           snprintf((char *)ws_idx_str, SWM_PROPLEN, "%d", ws->idx) <
+               SWM_PROPLEN) {
+               DNPRINTF(SWM_D_PROP, "manage_window: set _SWM_WS: %s\n",
+                   ws_idx_str);
+               XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
+                   PropModeReplace, ws_idx_str, strlen((char *)ws_idx_str));
+       }
+       if (prop)
+               XFree(prop);
+
+       ewmh_autoquirk(win);
+
+       if (XGetClassHint(display, win->id, &win->ch)) {
+               DNPRINTF(SWM_D_CLASS, "manage_window: class: %s, name: %s\n",
+                   win->ch.res_class, win->ch.res_name);
+
+               /* java is retarded so treat it special */
+               if (strstr(win->ch.res_name, "sun-awt")) {
+                       win->java = 1;
+                       border_me = 1;
+               }
+
+               TAILQ_FOREACH(qp, &quirks, entry) {
+                       if (!strcmp(win->ch.res_class, qp->class) &&
+                           !strcmp(win->ch.res_name, qp->name)) {
+                               DNPRINTF(SWM_D_CLASS, "manage_window: found: "
+                                   "class: %s, name: %s\n", win->ch.res_class,
+                                   win->ch.res_name);
+                               if (qp->quirk & SWM_Q_FLOAT) {
+                                       win->floating = 1;
+                                       border_me = 1;
+                               }
+                               win->quirks = qp->quirk;
+                       }
+               }
+       }
+
+       /* alter window position if quirky */
+       if (win->quirks & SWM_Q_ANYWHERE) {
+               win->manual = 1; /* don't center the quirky windows */
+               bzero(&wc, sizeof wc);
+               mask = 0;
+               if (bar_enabled && Y(win) < bar_height) {
+                       Y(win) = wc.y = bar_height;
+                       mask |= CWY;
+               }
+               if (WIDTH(win) + X(win) > WIDTH(r)) {
+                       X(win) = wc.x = WIDTH(r) - WIDTH(win) - 2;
+                       mask |= CWX;
+               }
+               border_me = 1;
+       }
+
+       /* Reset font sizes (the bruteforce way; no default keybinding). */
+       if (win->quirks & SWM_Q_XTERM_FONTADJ) {
+               for (i = 0; i < SWM_MAX_FONT_STEPS; i++)
+                       fake_keypress(win, XK_KP_Subtract, ShiftMask);
+               for (i = 0; i < SWM_MAX_FONT_STEPS; i++)
+                       fake_keypress(win, XK_KP_Add, ShiftMask);
+       }
+
+       ewmh_get_win_state(win);
+       ewmh_update_actions(win);
+       ewmh_update_win_state(win, None, _NET_WM_STATE_REMOVE);
+
+       /* border me */
+       if (border_me) {
+               bzero(&wc, sizeof wc);
+               wc.border_width = border_width;
+               mask = CWBorderWidth;
+               XConfigureWindow(display, win->id, mask, &wc);
+       }
+
+       XSelectInput(display, id, EnterWindowMask | FocusChangeMask |
+           PropertyChangeMask | StructureNotifyMask);
+
+       /* floaters need to be mapped if they are in the current workspace */
+       if ((win->floating || win->transient) && (ws->idx == r->ws->idx))
+               XMapRaised(display, win->id);
+
+       return (win);
+}
+
+void
+free_window(struct ws_win *win)
+{
+       DNPRINTF(SWM_D_MISC, "free_window: window: 0x%lx\n", win->id);
+
+       if (win == NULL)
+               return;
+
+       /* needed for restart wm */
+       set_win_state(win, WithdrawnState);
+
+       TAILQ_REMOVE(&win->ws->unmanagedlist, win, entry);
+
+       if (win->ch.res_class)
+               XFree(win->ch.res_class);
+       if (win->ch.res_name)
+               XFree(win->ch.res_name);
+
+       kill_refs(win);
+
+       /* paint memory */
+       memset(win, 0xff, sizeof *win); /* XXX kill later */
+
+       free(win);
+}
+
+void
+unmanage_window(struct ws_win *win)
+{
+       struct ws_win           *parent;
+
+       if (win == NULL)
+               return;
+
+       DNPRINTF(SWM_D_MISC, "unmanage_window: window: 0x%lx\n", win->id);
+
+       if (win->transient) {
+               parent = find_window(win->transient);
+               if (parent)
+                       parent->child_trans = NULL;
+       }
+
+       /* focus on root just in case */
+       XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
+
+       focus_prev(win);
+
+       if (win->hints) {
+               XFree(win->hints);
+               win->hints = NULL;
+       }
+
+       TAILQ_REMOVE(&win->ws->winlist, win, entry);
+       TAILQ_INSERT_TAIL(&win->ws->unmanagedlist, win, entry);
+
+       kill_refs(win);
+}
+
+void
+focus_magic(struct ws_win *win)
+{
+       DNPRINTF(SWM_D_FOCUS, "focus_magic: window: 0x%lx\n", WINID(win));
+
+       if (win == NULL) {
+               /* if there are no windows clear the status-bar */
+               bar_check_opts();
+               return;
+       }
+
+       if (win->child_trans) {
+               /* win = parent & has a transient so focus on that */
+               if (win->java) {
+                       focus_win(win->child_trans);
+                       if (win->child_trans->take_focus)
+                               client_msg(win, takefocus);
+               } else {
+                       /* make sure transient hasn't disappeared */
+                       if (validate_win(win->child_trans) == 0) {
+                               focus_win(win->child_trans);
+                               if (win->child_trans->take_focus)
+                                       client_msg(win->child_trans, takefocus);
+                       } else {
+                               win->child_trans = NULL;
+                               focus_win(win);
+                               if (win->take_focus)
+                                       client_msg(win, takefocus);
+                       }
+               }
+       } else {
+               /* regular focus */
+               focus_win(win);
+               if (win->take_focus)
+                       client_msg(win, takefocus);
+       }
+}
+
+void
+expose(XEvent *e)
+{
+       DNPRINTF(SWM_D_EVENT, "expose: window: 0x%lx\n", e->xexpose.window);
+}
+
+void
+keypress(XEvent *e)
+{
+       KeySym                  keysym;
+       XKeyEvent               *ev = &e->xkey;
+       struct key              *kp;
+       struct swm_region       *r;
+
+       keysym = XKeycodeToKeysym(display, (KeyCode)ev->keycode, 0);
+       if ((kp = key_lookup(CLEANMASK(ev->state), keysym)) == NULL)
+               return;
+       if (keyfuncs[kp->funcid].func == NULL)
+               return;
+
+       r = root_to_region(ev->root);
+       if (kp->funcid == kf_spawn_custom)
+               spawn_custom(r, &(keyfuncs[kp->funcid].args), kp->spawn_name);
+       else
+               keyfuncs[kp->funcid].func(r, &(keyfuncs[kp->funcid].args));
+}
+
+void
+buttonpress(XEvent *e)
+{
+       struct ws_win           *win;
+       int                     i, action;
+       XButtonPressedEvent     *ev = &e->xbutton;
+
+       if ((win = find_window(ev->window)) == NULL)
+               return;
+
+       focus_magic(win);
+       action = client_click;
+
+       for (i = 0; i < LENGTH(buttons); i++)
+               if (action == buttons[i].action && buttons[i].func &&
+                   buttons[i].button == ev->button &&
+                   CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
+                       buttons[i].func(win, &buttons[i].args);
+}
+
+void
+configurerequest(XEvent *e)
+{
+       XConfigureRequestEvent  *ev = &e->xconfigurerequest;
+       struct ws_win           *win;
+       int                     new = 0;
+       XWindowChanges          wc;
+
+       if ((win = find_window(ev->window)) == NULL)
+               if ((win = find_unmanaged_window(ev->window)) == NULL)
+                       new = 1;
+
+       DNPRINTF(SWM_D_EVENT, "configurerequest: window: 0x%lx, new: %s\n",
+           ev->window, YESNO(new));
+
+       if (new) {
+               bzero(&wc, sizeof wc);
+               wc.x = ev->x;
+               wc.y = ev->y;
+               wc.width = ev->width;
+               wc.height = ev->height;
+               wc.border_width = ev->border_width;
+               wc.sibling = ev->above;
+               wc.stack_mode = ev->detail;
+               XConfigureWindow(display, ev->window, ev->value_mask, &wc);
+       } else {
+               config_win(win, ev);
+       }
+}
+
+void
+configurenotify(XEvent *e)
+{
+       struct ws_win           *win;
+
+       DNPRINTF(SWM_D_EVENT, "configurenotify: window: 0x%lx\n",
+           e->xconfigure.window);
+
+       win = find_window(e->xconfigure.window);
+       if (win) {
+               XGetWMNormalHints(display, win->id, &win->sh, &win->sh_mask);
+               adjust_font(win);
+               if (font_adjusted)
+                       stack();
+               if (focus_mode == SWM_FOCUS_DEFAULT)
+                       drain_enter_notify();
+       }
+}
+
+void
+destroynotify(XEvent *e)
+{
+       struct ws_win           *win;
+       XDestroyWindowEvent     *ev = &e->xdestroywindow;
+
+       DNPRINTF(SWM_D_EVENT, "destroynotify: window: 0x%lx\n", ev->window);
+
+       if ((win = find_window(ev->window)) == NULL) {
+               if ((win = find_unmanaged_window(ev->window)) == NULL)
+                       return;
+               free_window(win);
+               return;
+       }
+
+       /* make sure we focus on something */
+       win->floating = 0;
+
+       unmanage_window(win);
+       stack();
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+       free_window(win);
+}
+
+void
+enternotify(XEvent *e)
+{
+       XCrossingEvent          *ev = &e->xcrossing;
+       XEvent                  cne;
+       struct ws_win           *win;
+#if 0
+       struct ws_win           *w;
+       Window                  focus_return;
+       int                     revert_to_return;
+#endif
+       DNPRINTF(SWM_D_FOCUS, "enternotify: window: 0x%lx, mode: %d, detail: "
+           "%d, root: 0x%lx, subwindow: 0x%lx, same_screen: %s, focus: %s, "
+           "state: %d\n", ev->window, ev->mode, ev->detail, ev->root,
+           ev->subwindow, YESNO(ev->same_screen), YESNO(ev->focus), ev->state);
+
+       if (ev->mode != NotifyNormal) {
+               DNPRINTF(SWM_D_EVENT, "skip enternotify: generated by "
+                   "cursor grab.\n");
+               return;
+       }
+
+       switch (focus_mode) {
+       case SWM_FOCUS_DEFAULT:
+               break;
+       case SWM_FOCUS_FOLLOW:
+               break;
+       case SWM_FOCUS_SYNERGY:
+#if 0
+       /*
+        * all these checks need to be in this order because the
+        * XCheckTypedWindowEvent relies on weeding out the previous events
+        *
+        * making this code an option would enable a follow mouse for focus
+        * feature
+        */
+
+       /*
+        * state is set when we are switching workspaces and focus is set when
+        * the window or a subwindow already has focus (occurs during restart).
+        *
+        * Only honor the focus flag if last_focus_event is not FocusOut,
+        * this allows spectrwm to continue to control focus when another
+        * program is also playing with it.
+        */
+       if (ev->state || (ev->focus && last_focus_event != FocusOut)) {
+               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: focus\n");
+               return;
+       }
+
+       /*
+        * happens when a window is created or destroyed and the border
+        * crosses the mouse pointer and when switching ws
+        *
+        * we need the subwindow test to see if we came from root in order
+        * to give focus to floaters
+        */
+       if (ev->mode == NotifyNormal && ev->detail == NotifyVirtual &&
+           ev->subwindow == 0) {
+               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: NotifyVirtual\n");
+               return;
+       }
+
+       /* this window already has focus */
+       if (ev->mode == NotifyNormal && ev->detail == NotifyInferior) {
+               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: win has focus\n");
+               return;
+       }
+
+       /* this window is being deleted or moved to another ws */
+       if (XCheckTypedWindowEvent(display, ev->window, ConfigureNotify,
+           &cne) == True) {
+               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: configurenotify\n");
+               XPutBackEvent(display, &cne);
+               return;
+       }
+
+       if ((win = find_window(ev->window)) == NULL) {
+               DNPRINTF(SWM_D_EVENT, "ignoring enternotify: win == NULL\n");
+               return;
+       }
+
+       /*
+        * In fullstack kill all enters unless they come from a different ws
+        * (i.e. another region) or focus has been grabbed externally.
+        */
+       if (win->ws->cur_layout->flags & SWM_L_FOCUSPREV &&
+           last_focus_event != FocusOut) {
+               XGetInputFocus(display, &focus_return, &revert_to_return);
+               if ((w = find_window(focus_return)) == NULL ||
+                   w->ws == win->ws) {
+                       DNPRINTF(SWM_D_EVENT, "ignoring event: fullstack\n");
+                       return;
+               }
+       }
+#endif
+               break;
+       }
+
+       if ((win = find_window(ev->window)) == NULL) {
+               DNPRINTF(SWM_D_EVENT, "skip enternotify: window is NULL\n");
+               return;
+       }
+
+       /*
+        * if we have more enternotifies let them handle it in due time
+        */
+       if (XCheckTypedEvent(display, EnterNotify, &cne) == True) {
+               DNPRINTF(SWM_D_EVENT,
+                   "ignoring enternotify: got more enternotify\n");
+               XPutBackEvent(display, &cne);
+               return;
+       }
+
+       focus_magic(win);
+}
+
+/* lets us use one switch statement for arbitrary mode/detail combinations */
+#define MERGE_MEMBERS(a,b)     (((a & 0xffff) << 16) | (b & 0xffff))
+
+void
+focusevent(XEvent *e)
+{
+#if 0
+       struct ws_win           *win;
+       u_int32_t               mode_detail;
+       XFocusChangeEvent       *ev = &e->xfocus;
+
+       DNPRINTF(SWM_D_EVENT, "focusevent: %s window: 0x%lx mode: %d "
+           "detail: %d\n", ev->type == FocusIn ? "entering" : "leaving",
+           ev->window, ev->mode, ev->detail);
+
+       if (last_focus_event == ev->type) {
+               DNPRINTF(SWM_D_FOCUS, "ignoring focusevent: bad ordering\n");
+               return;
+       }
+
+       last_focus_event = ev->type;
+       mode_detail = MERGE_MEMBERS(ev->mode, ev->detail);
+
+       switch (mode_detail) {
+       /* synergy client focus operations */
+       case MERGE_MEMBERS(NotifyNormal, NotifyNonlinear):
+       case MERGE_MEMBERS(NotifyNormal, NotifyNonlinearVirtual):
+
+       /* synergy server focus operations */
+       case MERGE_MEMBERS(NotifyWhileGrabbed, NotifyNonlinear):
+
+       /* Entering applications like rdesktop that mangle the pointer */
+       case MERGE_MEMBERS(NotifyNormal, NotifyPointer):
+
+               if ((win = find_window(e->xfocus.window)) != NULL && win->ws->r)
+                       XSetWindowBorder(display, win->id,
+                           win->ws->r->s->c[ev->type == FocusIn ?
+                           SWM_S_COLOR_FOCUS : SWM_S_COLOR_UNFOCUS].color);
+               break;
+       default:
+               warnx("ignoring focusevent");
+               DNPRINTF(SWM_D_FOCUS, "ignoring focusevent\n");
+               break;
+       }
+#endif
+}
+
+void
+mapnotify(XEvent *e)
+{
+       struct ws_win           *win;
+       XMapEvent               *ev = &e->xmap;
+
+       DNPRINTF(SWM_D_EVENT, "mapnotify: window: 0x%lx\n", ev->window);
+
+       win = manage_window(ev->window);
+       if (win)
+               set_win_state(win, NormalState);
+}
+
+void
+mappingnotify(XEvent *e)
+{
+       XMappingEvent           *ev = &e->xmapping;
+
+       XRefreshKeyboardMapping(ev);
+       if (ev->request == MappingKeyboard)
+               grabkeys();
+}
+
+void
+maprequest(XEvent *e)
+{
+       struct ws_win           *win;
+       struct swm_region       *r;
+       XWindowAttributes       wa;
+       XMapRequestEvent        *ev = &e->xmaprequest;
+
+       DNPRINTF(SWM_D_EVENT, "maprequest: window: 0x%lx\n",
+           e->xmaprequest.window);
+
+       if (!XGetWindowAttributes(display, ev->window, &wa))
+               return;
+       if (wa.override_redirect)
+               return;
+
+       win = manage_window(e->xmaprequest.window);
+       if (win == NULL)
+               return; /* can't happen */
+
+       stack();
+
+       /* make new win focused */
+       r = root_to_region(win->wa.root);
+       if (win->ws == r->ws)
+               focus_magic(win);
+}
+
+void
+propertynotify(XEvent *e)
+{
+       struct ws_win           *win;
+       XPropertyEvent          *ev = &e->xproperty;
+#ifdef SWM_DEBUG
+       char                    *name;
+       name = XGetAtomName(display, ev->atom);
+       DNPRINTF(SWM_D_EVENT, "propertynotify: window: 0x%lx, atom: %s\n",
+           ev->window, name);
+       XFree(name);
+#endif
+
+       win = find_window(ev->window);
+       if (win == NULL)
+               return;
+
+       if (ev->state == PropertyDelete && ev->atom == a_swm_iconic) {
+               update_iconic(win, 0);
+               XMapRaised(display, win->id);
+               stack();
+               focus_win(win);
+               return;
+       }
+
+       switch (ev->atom) {
+#if 0
+       case XA_WM_NORMAL_HINTS:
+               long            mask;
+               XGetWMNormalHints(display, win->id, &win->sh, &mask);
+               warnx("normal hints: flag 0x%x", win->sh.flags);
+               if (win->sh.flags & PMinSize) {
+                       WIDTH(win) = win->sh.min_width;
+                       HEIGHT(win) = win->sh.min_height;
+                       warnx("min %d %d", WIDTH(win), HEIGHT(win));
+               }
+               XMoveResizeWindow(display, win->id,
+                   X(win), Y(win), WIDTH(win), HEIGHT(win));
+#endif
+       case XA_WM_CLASS:
+               if (title_name_enabled || title_class_enabled)
+                       bar_update();
+               break;
+       case XA_WM_NAME:
+               if (window_name_enabled)
+                       bar_update();
+               break;
+       default:
+               break;
+       }
+}
+
+void
+unmapnotify(XEvent *e)
+{
+       struct ws_win           *win;
+
+       DNPRINTF(SWM_D_EVENT, "unmapnotify: window: 0x%lx\n", e->xunmap.window);
+
+       /* determine if we need to help unmanage this window */
+       win = find_window(e->xunmap.window);
+       if (win == NULL)
+               return;
+
+       if (getstate(e->xunmap.window) == NormalState) {
+               unmanage_window(win);
+               stack();
+
+               /* giant hack for apps that don't destroy transient windows */
+               /* eat a bunch of events to prevent remanaging the window */
+               XEvent                  cne;
+               while (XCheckWindowEvent(display, e->xunmap.window,
+                   EnterWindowMask, &cne))
+                       ;
+               while (XCheckWindowEvent(display, e->xunmap.window,
+                   StructureNotifyMask, &cne))
+                       ;
+               while (XCheckWindowEvent(display, e->xunmap.window,
+                   SubstructureNotifyMask, &cne))
+                       ;
+               /* resend unmap because we ated it */
+               XUnmapWindow(display, e->xunmap.window);
+       }
+
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+}
+
+void
+visibilitynotify(XEvent *e)
+{
+       int                     i;
+       struct swm_region       *r;
+
+       DNPRINTF(SWM_D_EVENT, "visibilitynotify: window: 0x%lx\n",
+           e->xvisibility.window);
+       if (e->xvisibility.state == VisibilityUnobscured)
+               for (i = 0; i < ScreenCount(display); i++)
+                       TAILQ_FOREACH(r, &screens[i].rl, entry)
+                               if (e->xvisibility.window == r->bar_window)
+                                       bar_update();
+}
+
+void
+clientmessage(XEvent *e)
+{
+       XClientMessageEvent *ev;
+       struct ws_win *win;
+
+       ev = &e->xclient;
+
+       win = find_window(ev->window);
+       if (win == NULL)
+               return;
+
+       DNPRINTF(SWM_D_EVENT, "clientmessage: window: 0x%lx, type: %ld\n",
+           ev->window, ev->message_type);
+
+       if (ev->message_type == ewmh[_NET_ACTIVE_WINDOW].atom) {
+               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW\n");
+               focus_win(win);
+       }
+       if (ev->message_type == ewmh[_NET_CLOSE_WINDOW].atom) {
+               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_CLOSE_WINDOW\n");
+               if (win->can_delete)
+                       client_msg(win, adelete);
+               else
+                       XKillClient(display, win->id);
+       }
+       if (ev->message_type == ewmh[_NET_MOVERESIZE_WINDOW].atom) {
+               DNPRINTF(SWM_D_EVENT,
+                   "clientmessage: _NET_MOVERESIZE_WINDOW\n");
+               if (win->floating) {
+                       if (ev->data.l[0] & (1<<8)) /* x */
+                               X(win) = ev->data.l[1];
+                       if (ev->data.l[0] & (1<<9)) /* y */
+                               Y(win) = ev->data.l[2];
+                       if (ev->data.l[0] & (1<<10)) /* width */
+                               WIDTH(win) = ev->data.l[3];
+                       if (ev->data.l[0] & (1<<11)) /* height */
+                               HEIGHT(win) = ev->data.l[4];
+
+                       update_window(win);
+               }
+               else {
+                       /* TODO: Change stack sizes */
+                       /* notify no change was made. */
+                       config_win(win, NULL);
+               }
+       }
+       if (ev->message_type == ewmh[_NET_WM_STATE].atom) {
+               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_WM_STATE\n");
+               ewmh_update_win_state(win, ev->data.l[1], ev->data.l[0]);
+               if (ev->data.l[2])
+                       ewmh_update_win_state(win, ev->data.l[2],
+                           ev->data.l[0]);
+
+               stack();
+       }
+}
+
+int
+xerror_start(Display *d, XErrorEvent *ee)
+{
+       other_wm = 1;
+       return (-1);
+}
+
+int
+xerror(Display *d, XErrorEvent *ee)
+{
+       /* warnx("error: %p %p", display, ee); */
+       return (-1);
+}
+
+int
+active_wm(void)
+{
+       other_wm = 0;
+       xerrorxlib = XSetErrorHandler(xerror_start);
+
+       /* this causes an error if some other window manager is running */
+       XSelectInput(display, DefaultRootWindow(display),
+           SubstructureRedirectMask);
+       XSync(display, False);
+       if (other_wm)
+               return (1);
+
+       XSetErrorHandler(xerror);
+       XSync(display, False);
+       return (0);
+}
+
+void
+new_region(struct swm_screen *s, int x, int y, int w, int h)
+{
+       struct swm_region       *r, *n;
+       struct workspace        *ws = NULL;
+       int                     i;
+
+       DNPRINTF(SWM_D_MISC, "new region: screen[%d]:%dx%d+%d+%d\n",
+            s->idx, w, h, x, y);
+
+       /* remove any conflicting regions */
+       n = TAILQ_FIRST(&s->rl);
+       while (n) {
+               r = n;
+               n = TAILQ_NEXT(r, entry);
+               if (X(r) < (x + w) &&
+                   (X(r) + WIDTH(r)) > x &&
+                   Y(r) < (y + h) &&
+                   (Y(r) + HEIGHT(r)) > y) {
+                       if (r->ws->r != NULL)
+                               r->ws->old_r = r->ws->r;
+                       r->ws->r = NULL;
+                       XDestroyWindow(display, r->bar_window);
+                       TAILQ_REMOVE(&s->rl, r, entry);
+                       TAILQ_INSERT_TAIL(&s->orl, r, entry);
+               }
+       }
+
+       /* search old regions for one to reuse */
+
+       /* size + location match */
+       TAILQ_FOREACH(r, &s->orl, entry)
+               if (X(r) == x && Y(r) == y &&
+                   HEIGHT(r) == h && WIDTH(r) == w)
+                       break;
+
+       /* size match */
+       TAILQ_FOREACH(r, &s->orl, entry)
+               if (HEIGHT(r) == h && WIDTH(r) == w)
+                       break;
+
+       if (r != NULL) {
+               TAILQ_REMOVE(&s->orl, r, entry);
+               /* try to use old region's workspace */
+               if (r->ws->r == NULL)
+                       ws = r->ws;
+       } else
+               if ((r = calloc(1, sizeof(struct swm_region))) == NULL)
+                       err(1, "new_region: calloc: failed to allocate memory "
+                           "for screen");
+
+       /* if we don't have a workspace already, find one */
+       if (ws == NULL) {
+               for (i = 0; i < SWM_WS_MAX; i++)
+                       if (s->ws[i].r == NULL) {
+                               ws = &s->ws[i];
+                               break;
+                       }
+       }
+
+       if (ws == NULL)
+               errx(1, "new_region: no free workspaces");
+
+       X(r) = x;
+       Y(r) = y;
+       WIDTH(r) = w;
+       HEIGHT(r) = h;
+       r->s = s;
+       r->ws = ws;
+       r->ws_prior = NULL;
+       ws->r = r;
+       outputs++;
+       TAILQ_INSERT_TAIL(&s->rl, r, entry);
+}
+
+void
+scan_xrandr(int i)
+{
+#ifdef SWM_XRR_HAS_CRTC
+       XRRCrtcInfo             *ci;
+       XRRScreenResources      *sr;
+       int                     c;
+       int                     ncrtc = 0;
+#endif /* SWM_XRR_HAS_CRTC */
+       struct swm_region       *r;
+
+
+       if (i >= ScreenCount(display))
+               errx(1, "scan_xrandr: invalid screen");
+
+       /* remove any old regions */
+       while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) {
+               r->ws->old_r = r->ws->r = NULL;
+               XDestroyWindow(display, r->bar_window);
+               TAILQ_REMOVE(&screens[i].rl, r, entry);
+               TAILQ_INSERT_TAIL(&screens[i].orl, r, entry);
+       }
+       outputs = 0;
+
+       /* map virtual screens onto physical screens */
+#ifdef SWM_XRR_HAS_CRTC
+       if (xrandr_support) {
+               sr = XRRGetScreenResources(display, screens[i].root);
+               if (sr == NULL)
+                       new_region(&screens[i], 0, 0,
+                           DisplayWidth(display, i),
+                           DisplayHeight(display, i));
+               else
+                       ncrtc = sr->ncrtc;
+
+               for (c = 0, ci = NULL; c < ncrtc; c++) {
+                       ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]);
+                       if (ci->noutput == 0)
+                               continue;
+
+                       if (ci != NULL && ci->mode == None)
+                               new_region(&screens[i], 0, 0,
+                                   DisplayWidth(display, i),
+                                   DisplayHeight(display, i));
+                       else
+                               new_region(&screens[i],
+                                   ci->x, ci->y, ci->width, ci->height);
+               }
+               if (ci)
+                       XRRFreeCrtcInfo(ci);
+               XRRFreeScreenResources(sr);
+       } else
+#endif /* SWM_XRR_HAS_CRTC */
+       {
+               new_region(&screens[i], 0, 0, DisplayWidth(display, i),
+                   DisplayHeight(display, i));
+       }
+}
+
+void
+screenchange(XEvent *e) {
+       XRRScreenChangeNotifyEvent      *xe = (XRRScreenChangeNotifyEvent *)e;
+       struct swm_region               *r;
+       int                             i;
+
+       DNPRINTF(SWM_D_EVENT, "screenchange: root: 0x%lx\n", xe->root);
+
+       if (!XRRUpdateConfiguration(e))
+               return;
+
+       /* silly event doesn't include the screen index */
+       for (i = 0; i < ScreenCount(display); i++)
+               if (screens[i].root == xe->root)
+                       break;
+       if (i >= ScreenCount(display))
+               errx(1, "screenchange: screen not found");
+
+       /* brute force for now, just re-enumerate the regions */
+       scan_xrandr(i);
+
+       /* add bars to all regions */
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry)
+                       bar_setup(r);
+       stack();
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+}
+
+void
+grab_windows(void)
+{
+       Window                  d1, d2, *wins = NULL;
+       XWindowAttributes       wa;
+       unsigned int            no;
+       int                     i, j;
+       long                    state, manage;
+
+       for (i = 0; i < ScreenCount(display); i++) {
+               if (!XQueryTree(display, screens[i].root, &d1, &d2, &wins, &no))
+                       continue;
+
+               /* attach windows to a region */
+               /* normal windows */
+               for (j = 0; j < no; j++) {
+                       if (!XGetWindowAttributes(display, wins[j], &wa) ||
+                           wa.override_redirect ||
+                           XGetTransientForHint(display, wins[j], &d1))
+                               continue;
+
+                       state = getstate(wins[j]);
+                       manage = state == IconicState;
+                       if (wa.map_state == IsViewable || manage)
+                               manage_window(wins[j]);
+               }
+               /* transient windows */
+               for (j = 0; j < no; j++) {
+                       if (!XGetWindowAttributes(display, wins[j], &wa) ||
+                           wa.override_redirect)
+                               continue;
+
+                       state = getstate(wins[j]);
+                       manage = state == IconicState;
+                       if (XGetTransientForHint(display, wins[j], &d1) &&
+                           manage)
+                               manage_window(wins[j]);
+               }
+               if (wins) {
+                       XFree(wins);
+                       wins = NULL;
+               }
+       }
+}
+
+void
+setup_screens(void)
+{
+       int                     i, j, k;
+       int                     errorbase, major, minor;
+       struct workspace        *ws;
+       XGCValues               gcv;
+
+       if ((screens = calloc(ScreenCount(display),
+            sizeof(struct swm_screen))) == NULL)
+               err(1, "setup_screens: calloc: failed to allocate memory for "
+                   "screens");
+
+       /* initial Xrandr setup */
+       xrandr_support = XRRQueryExtension(display,
+           &xrandr_eventbase, &errorbase);
+       if (xrandr_support)
+               if (XRRQueryVersion(display, &major, &minor) && major < 1)
+                       xrandr_support = 0;
+
+       /* map physical screens */
+       for (i = 0; i < ScreenCount(display); i++) {
+               DNPRINTF(SWM_D_WS, "setup_screens: init screen: %d\n", i);
+               screens[i].idx = i;
+               TAILQ_INIT(&screens[i].rl);
+               TAILQ_INIT(&screens[i].orl);
+               screens[i].root = RootWindow(display, i);
+
+               /* set default colors */
+               setscreencolor("red", i + 1, SWM_S_COLOR_FOCUS);
+               setscreencolor("rgb:88/88/88", i + 1, SWM_S_COLOR_UNFOCUS);
+               setscreencolor("rgb:00/80/80", i + 1, SWM_S_COLOR_BAR_BORDER);
+               setscreencolor("black", i + 1, SWM_S_COLOR_BAR);
+               setscreencolor("rgb:a0/a0/a0", i + 1, SWM_S_COLOR_BAR_FONT);
+
+               /* create graphics context on screen with default font color */
+               screens[i].bar_gc = XCreateGC(display, screens[i].root, 0,
+                   &gcv);
+
+               XSetForeground(display, screens[i].bar_gc,
+                   screens[i].c[SWM_S_COLOR_BAR_FONT].color);
+
+               /* set default cursor */
+               XDefineCursor(display, screens[i].root,
+                   XCreateFontCursor(display, XC_left_ptr));
+
+               /* init all workspaces */
+               /* XXX these should be dynamically allocated too */
+               for (j = 0; j < SWM_WS_MAX; j++) {
+                       ws = &screens[i].ws[j];
+                       ws->idx = j;
+                       ws->name = NULL;
+                       ws->focus = NULL;
+                       ws->r = NULL;
+                       ws->old_r = NULL;
+                       TAILQ_INIT(&ws->winlist);
+                       TAILQ_INIT(&ws->unmanagedlist);
+
+                       for (k = 0; layouts[k].l_stack != NULL; k++)
+                               if (layouts[k].l_config != NULL)
+                                       layouts[k].l_config(ws,
+                                           SWM_ARG_ID_STACKINIT);
+                       ws->cur_layout = &layouts[0];
+                       ws->cur_layout->l_string(ws);
+               }
+
+               scan_xrandr(i);
+
+               if (xrandr_support)
+                       XRRSelectInput(display, screens[i].root,
+                           RRScreenChangeNotifyMask);
+       }
+}
+
+void
+setup_globals(void)
+{
+       if ((bar_fonts = strdup(SWM_BAR_FONTS)) == NULL)
+               err(1, "setup_globals: strdup: failed to allocate memory.");
+
+       if ((spawn_term[0] = strdup("xterm")) == NULL)
+               err(1, "setup_globals: strdup: failed to allocate memory.");
+
+       if ((clock_format = strdup("%a %b %d %R %Z %Y")) == NULL)
+               err(1, "setup_globals: strdup: failed to allocate memory.");
+}
+
+void
+workaround(void)
+{
+       int                     i;
+       Atom                    netwmcheck, netwmname, utf8_string;
+       Window                  root, win;
+
+       /* work around sun jdk bugs, code from wmname */
+       netwmcheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
+       netwmname = XInternAtom(display, "_NET_WM_NAME", False);
+       utf8_string = XInternAtom(display, "UTF8_STRING", False);
+       for (i = 0; i < ScreenCount(display); i++) {
+               root = screens[i].root;
+               win = XCreateSimpleWindow(display,root, 0, 0, 1, 1, 0,
+                   screens[i].c[SWM_S_COLOR_UNFOCUS].color,
+                   screens[i].c[SWM_S_COLOR_UNFOCUS].color);
+
+               XChangeProperty(display, root, netwmcheck, XA_WINDOW, 32,
+                   PropModeReplace, (unsigned char *)&win,1);
+               XChangeProperty(display, win, netwmcheck, XA_WINDOW, 32,
+                   PropModeReplace, (unsigned char *)&win,1);
+               XChangeProperty(display, win, netwmname, utf8_string, 8,
+                   PropModeReplace, (unsigned char*)"LG3D", strlen("LG3D"));
+       }
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct swm_region       *r, *rr;
+       struct ws_win           *winfocus = NULL;
+       struct timeval          tv;
+       union arg               a;
+       char                    conf[PATH_MAX], *cfile = NULL;
+       struct stat             sb;
+       XEvent                  e;
+       int                     xfd, i;
+       fd_set                  rd;
+       struct sigaction        sact;
+
+       start_argv = argv;
+       warnx("Welcome to spectrwm V%s Build: %s", SPECTRWM_VERSION, buildstr);
+       if (!setlocale(LC_CTYPE, "") || !setlocale(LC_TIME, "") ||
+           !XSupportsLocale())
+               warnx("no locale support");
+
+       if (!X_HAVE_UTF8_STRING)
+               warnx("no UTF-8 support");
+
+       if (!(display = XOpenDisplay(0)))
+               errx(1, "can not open display");
+
+       if (active_wm())
+               errx(1, "other wm running");
+
+       /* handle some signals */
+       bzero(&sact, sizeof(sact));
+       sigemptyset(&sact.sa_mask);
+       sact.sa_flags = 0;
+       sact.sa_handler = sighdlr;
+       sigaction(SIGINT, &sact, NULL);
+       sigaction(SIGQUIT, &sact, NULL);
+       sigaction(SIGTERM, &sact, NULL);
+       sigaction(SIGHUP, &sact, NULL);
+
+       sact.sa_handler = sighdlr;
+       sact.sa_flags = SA_NOCLDSTOP;
+       sigaction(SIGCHLD, &sact, NULL);
+
+       astate = XInternAtom(display, "WM_STATE", False);
+       aprot = XInternAtom(display, "WM_PROTOCOLS", False);
+       adelete = XInternAtom(display, "WM_DELETE_WINDOW", False);
+       takefocus = XInternAtom(display, "WM_TAKE_FOCUS", False);
+       a_wmname = XInternAtom(display, "WM_NAME", False);
+       a_netwmname = XInternAtom(display, "_NET_WM_NAME", False);
+       a_utf8_string = XInternAtom(display, "UTF8_STRING", False);
+       a_string = XInternAtom(display, "STRING", False);
+       a_swm_iconic = XInternAtom(display, "_SWM_ICONIC", False);
+
+       /* look for local and global conf file */
+       pwd = getpwuid(getuid());
+       if (pwd == NULL)
+               errx(1, "invalid user: %d", getuid());
+
+       setup_globals();
+       setup_screens();
+       setup_keys();
+       setup_quirks();
+       setup_spawn();
+
+       /* load config */
+       snprintf(conf, sizeof conf, "%s/.%s", pwd->pw_dir, SWM_CONF_FILE);
+       if (stat(conf, &sb) != -1) {
+               if (S_ISREG(sb.st_mode))
+                       cfile = conf;
+       } else {
+               /* try global conf file */
+               snprintf(conf, sizeof conf, "/etc/%s", SWM_CONF_FILE);
+               if (!stat(conf, &sb))
+                       if (S_ISREG(sb.st_mode))
+                               cfile = conf;
+       }
+
+       /* load conf (if any) and refresh font color in bar graphics contexts */
+       if (cfile && conf_load(cfile, SWM_CONF_DEFAULT) == 0)
+               for (i = 0; i < ScreenCount(display); ++i)
+                       XSetForeground(display, screens[i].bar_gc,
+                           screens[i].c[SWM_S_COLOR_BAR_FONT].color);
+
+       setup_ewmh();
+       /* set some values to work around bad programs */
+       workaround();
+       /* grab existing windows (before we build the bars) */
+       grab_windows();
+
+       if (getenv("SWM_STARTED") == NULL)
+               setenv("SWM_STARTED", "YES", 1);
+
+       /* setup all bars */
+       for (i = 0; i < ScreenCount(display); i++)
+               TAILQ_FOREACH(r, &screens[i].rl, entry) {
+                       if (winfocus == NULL)
+                               winfocus = TAILQ_FIRST(&r->ws->winlist);
+                       bar_setup(r);
+               }
+
+       unfocus_all();
+
+       grabkeys();
+       stack();
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               drain_enter_notify();
+
+       xfd = ConnectionNumber(display);
+       while (running) {
+               while (XPending(display)) {
+                       XNextEvent(display, &e);
+                       if (running == 0)
+                               goto done;
+                       if (e.type < LASTEvent) {
+                               DNPRINTF(SWM_D_EVENTQ ,"XEvent: handled: %s, "
+                                   "window: 0x%lx, type: %s (%d), %d remaining"
+                                   "\n", YESNO(handler[e.type]),
+                                   e.xany.window, geteventname(&e),
+                                   e.type, QLength(display));
+
+                               if (handler[e.type])
+                                       handler[e.type](&e);
+                       } else {
+                               DNPRINTF(SWM_D_EVENTQ, "XRandr Event: window: "
+                                   "0x%lx, type: %s (%d)\n", e.xany.window,
+                                   xrandr_geteventname(&e), e.type);
+
+                               switch (e.type - xrandr_eventbase) {
+                               case RRScreenChangeNotify:
+                                       screenchange(&e);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+               }
+
+               /* if we are being restarted go focus on first window */
+               if (winfocus) {
+                       rr = winfocus->ws->r;
+                       if (rr == NULL) {
+                               /* not a visible window */
+                               winfocus = NULL;
+                               continue;
+                       }
+                       /* move pointer to first screen if multi screen */
+                       if (ScreenCount(display) > 1 || outputs > 1)
+                               XWarpPointer(display, None, rr->s[0].root,
+                                   0, 0, 0, 0, X(rr),
+                                   Y(rr) + (bar_enabled ? bar_height : 0));
+
+                       a.id = SWM_ARG_ID_FOCUSCUR;
+                       focus(rr, &a);
+                       winfocus = NULL;
+                       continue;
+               }
+
+               FD_ZERO(&rd);
+               FD_SET(xfd, &rd);
+               tv.tv_sec = 1;
+               tv.tv_usec = 0;
+               if (select(xfd + 1, &rd, NULL, NULL, &tv) == -1)
+                       if (errno != EINTR)
+                               DNPRINTF(SWM_D_MISC, "select failed");
+               if (restart_wm == 1)
+                       restart(NULL, NULL);
+               if (search_resp == 1)
+                       search_do_resp();
+               if (running == 0)
+                       goto done;
+               if (bar_alarm) {
+                       bar_alarm = 0;
+                       bar_update();
+               }
+       }
+done:
+       teardown_ewmh();
+       bar_extra_stop();
+
+       for (i = 0; i < ScreenCount(display); ++i)
+               if (screens[i].bar_gc != NULL)
+                       XFreeGC(display, screens[i].bar_gc);
+
+       XFreeFontSet(display, bar_fs);
+       XCloseDisplay(display);
+
+       return (0);
+}
diff --git a/spectrwm.conf b/spectrwm.conf
new file mode 100644 (file)
index 0000000..5e460d5
--- /dev/null
@@ -0,0 +1,84 @@
+# PLEASE READ THE MAN PAGE BEFORE EDITING THIS FILE!
+# http://opensource.conformal.com/cgi-bin/man-cgi?spectrwm
+
+# colors for focussed and unfocussed window borders
+# NOTE: all colors in this file are in hex! see XQueryColor for examples
+# color_focus          = red
+# color_unfocus                = rgb:88/88/88
+
+# bar settings
+# bar_enabled          = 1
+# bar_border_width     = 1
+# bar_border[1]                = rgb:00/80/80
+# bar_color[1]         = black
+# bar_font_color[1]    = rgb:a0/a0/a0
+# bar_font             = -*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*
+# bar_action           = baraction.sh
+# bar_delay            = 1
+# bar_justify          = left
+# bar_at_bottom                = 1
+# stack_enabled                = 1
+# clock_enabled                = 1
+# clock_format         = %a %b %d %R %Z %Y
+# title_name_enabled   = 0
+# title_class_enabled  = 0
+# window_name_enabled  = 0
+# verbose_layout               = 1
+# focus_mode           = default
+# disable_border               = 1
+# border_width         = 1
+# urgent_enabled               = 1
+
+# spawn app
+# program[term]                = xterm
+# program[screenshot_all]      = screenshot.sh full
+# program[screenshot_wind]     = screenshot.sh window
+# program[lock]                = xlock
+# program[initscr]     = initscreen.sh
+# program[menu]                = dmenu_run -fn $bar_font -nb $bar_color -nf $bar_font_color -sb $bar_border -sf $bar_color
+# spawn_term           = xterm
+
+# dialog box size ratio .3 >= r < 1
+# dialog_ratio         = 0.6
+
+# Split a non-Xrandr dual head setup into one region per monitor
+# (non-standard driver-based multihead is not seen by spectrwm)
+# region               = screen[1]:1280x1024+0+0
+# region               = screen[1]:1280x1024+1280+0
+
+# Launch applications in a workspace of choice
+# autorun              = ws[1]:xterm
+# autorun              = ws[2]:xxxterm http://www.openbsd.org
+
+# workspace layout
+# layout               = ws[1]:4:0:0:0:vertical
+# layout               = ws[2]:0:0:0:0:horizontal
+# layout               = ws[3]:0:0:0:0:fullscreen
+
+# mod key, (windows key is Mod4) (apple key on OSX is Mod2)
+# modkey = Mod1
+
+# Clear key bindings and load new key bindings from the specified file.
+# This allows you to load pre-defined key bindings for your keyboard layout.
+# keyboard_mapping = ~/.spectrwm_us.conf
+
+# quirks
+# remove with: quirk[class:name] = NONE
+# quirk[MPlayer:xv]                    = FLOAT + FULLSCREEN + FOCUSPREV
+# quirk[OpenOffice.org 2.4:VCLSalFrame]        = FLOAT
+# quirk[OpenOffice.org 3.0:VCLSalFrame]        = FLOAT
+# quirk[OpenOffice.org 3.1:VCLSalFrame]        = FLOAT
+# quirk[Firefox-bin:firefox-bin]               = TRANSSZ
+# quirk[Firefox:Dialog]                        = FLOAT
+# quirk[Gimp:gimp]                     = FLOAT + ANYWHERE
+# quirk[XTerm:xterm]                   = XTERM_FONTADJ
+# quirk[xine:Xine Window]                      = FLOAT + ANYWHERE
+# quirk[Xitk:Xitk Combo]                       = FLOAT + ANYWHERE
+# quirk[xine:xine Panel]                       = FLOAT + ANYWHERE
+# quirk[Xitk:Xine Window]                      = FLOAT + ANYWHERE
+# quirk[xine:xine Video Fullscreen Window] = FULLSCREEN + FLOAT
+# quirk[pcb:pcb]                               = FLOAT
+
+# EXAMPLE: define firefox program and bind to key
+# program[firefox]     = firefox http://spectrwm.org/
+# bind[firefox]                = MOD+Shift+b
diff --git a/spectrwm_cz.conf b/spectrwm_cz.conf
new file mode 100644 (file)
index 0000000..37baeb7
--- /dev/null
@@ -0,0 +1,74 @@
+# Key bindings for Czech Republic (cz) keyboards
+# unbind with: bind[] = <keys>
+bind[cycle_layout]     = MOD+space
+bind[flip_layout]      = MOD+Shift+backslash
+bind[stack_reset]      = MOD+Shift+space
+bind[master_shrink]    = MOD+h
+bind[master_grow]      = MOD+l
+bind[master_add]       = MOD+comma
+bind[master_del]       = MOD+period
+bind[stack_inc]                = MOD+Shift+comma
+bind[stack_dec]                = MOD+Shift+period
+bind[swap_main]                = MOD+Return
+bind[focus_next]       = MOD+j
+bind[focus_prev]       = MOD+k
+bind[swap_next]                = MOD+Shift+j
+bind[swap_prev]                = MOD+Shift+k
+bind[spawn_term]       = MOD+Shift+Return
+bind[menu]             = MOD+p
+bind[quit]             = MOD+Shift+q
+bind[restart]          = MOD+q
+bind[focus_main]       = MOD+m
+bind[ws_1]             = MOD+plus
+bind[ws_2]             = MOD+ecaron
+bind[ws_3]             = MOD+scaron
+bind[ws_4]             = MOD+ccaron
+bind[ws_5]             = MOD+rcaron
+bind[ws_6]             = MOD+zcaron
+bind[ws_7]             = MOD+yacute
+bind[ws_8]             = MOD+aacute
+bind[ws_9]             = MOD+iacute
+bind[ws_10]            = MOD+eacute
+bind[ws_next]          = MOD+Right
+bind[ws_prev]          = MOD+Left
+bind[ws_next_all]      = MOD+Up
+bind[ws_prev_all]      = MOD+Down
+bind[ws_prior]         = MOD+a
+bind[screen_next]      = MOD+Shift+Right
+bind[screen_prev]      = MOD+Shift+Left
+bind[mvws_1]           = MOD+Shift+plus
+bind[mvws_2]           = MOD+Shift+ecaron
+bind[mvws_3]           = MOD+Shift+scaron
+bind[mvws_4]           = MOD+Shift+ccaron
+bind[mvws_5]           = MOD+Shift+rcaron
+bind[mvws_6]           = MOD+Shift+zcaron
+bind[mvws_7]           = MOD+Shift+yacute
+bind[mvws_8]           = MOD+Shift+aacute
+bind[mvws_9]           = MOD+Shift+iacute
+bind[mvws_10]          = MOD+Shift+eacute
+bind[bar_toggle]       = MOD+b
+bind[focus_next]       = MOD+Tab
+bind[focus_prev]       = MOD+Shift+Tab
+bind[wind_kill]                = MOD+Shift+x
+bind[wind_del]         = MOD+x
+bind[screenshot_all]   = MOD+s
+bind[screenshot_wind]  = MOD+Shift+s
+bind[float_toggle]     = MOD+t
+bind[version]          = MOD+Shift+v
+bind[lock]             = MOD+Shift+Delete
+bind[initscr]          = MOD+Shift+i
+bind[iconify]          = MOD+w
+bind[uniconify]                = MOD+Shift+w
+bind[raise_toggle]     = MOD+Shift+r
+bind[button2]          = MOD+v
+bind[width_shrink]     = MOD+equal
+bind[width_grow]       = MOD+dead_acute
+bind[height_shrink]    = MOD+Shift+equal
+bind[height_grow]      = MOD+Shift+dead_acute
+bind[move_left]                = MOD+uacute
+bind[move_right]       = MOD+parenright
+bind[move_up]          = MOD+Shift+uacute
+bind[move_down]                = MOD+Shift+parenright
+bind[name_workspace]   = MOD+Shift+slash
+bind[search_workspace] = MOD+slash
+bind[search_win]       = MOD+f
diff --git a/spectrwm_es.1 b/spectrwm_es.1
new file mode 100644 (file)
index 0000000..003487a
--- /dev/null
@@ -0,0 +1,746 @@
+.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate$
+.Dt SPECTRWM 1
+.Os
+.Sh NOMBRE
+.Nm spectrwm
+.Nd es un manejador de ventanas para X11
+.Sh SYNOPSIS
+.Nm spectrwm
+.Sh DESCRIPCIÓN
+.Nm
+es un manejador de ventanas super minimalista para X11. Intenta no superponer 
+las ventanas para que las mismas puedan usarse de manera eficiente y para cosas mas importantes. 
+Tiene configuraciones normales y no requiere que sepas un lenguaje de 
+programacion para configurarlo. Esta escrito por hackers para hackers y apunta 
+a ser pequeño, compacto y rápido. 
+.Pp
+Cuando
+.Nm
+inicia, lo primero que hace es leer el archivo de configuracion,
+.Pa spectrwm.conf .
+Ver 
+.Sx ARCHIVOS DE CONFIGURACIÓN
+.
+.Pp
+La siguiente anotacion se usa a través de esta pagina:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Cm M
+Meta
+.It Cm S
+Shift
+.It Aq Cm Name
+Nombre de tecla
+.It Cm M1
+Boton 1 del mouse
+.It Cm M3
+Boton 3 del mouse
+.El
+.Pp
+.Nm
+es muy simple de usar.
+La mayoria de las acciones se hacen con los mapeos (bindings) de mouse 
+o teclado.
+Ver la sección de
+.Sx BINDINGS
+para las personalizaciones y configuraciones por defecto.
+.Sh ARCHIVOS DE CONFIGURACIÓN
+.Nm
+primero trata de abrir el archivo por defecto en el directorio del usuario,
+.Pa ~/.spectrwm.conf .
+Si ese archivo no esta disponible,
+luego trata de abrir el archivo global de configuracion
+.Pa /etc/spectrwm.conf .
+.Pp
+El formato del archivo es \*(Lttecla\*(Gt = \*(Ltconfiguracion\*(Gt.
+Por ejemplo:
+.Pp
+.Dl color_focus = red
+.Pp
+Habilitamos o deshabilitamos la opción usando 1 o 0 respectivamente.
+.Pp
+El archivo soporta las siguientes palabras clave:
+.Pp
+.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
+.It Cm autorun
+Inicia una aplicacion en un escritorio en particular al primer inicio.
+Definido por el formato ws[<idx>]:aplicacion, ej. ws[2]:xterm lanza
+xterm en el escritorio 2.
+.It Cm color_focus
+Color del borde de la ventana en foco.
+.It Cm color_unfocus
+Color del borde de la ventana fuera de foco.
+.It Cm bar_enabled
+Habilitar o deshabilitar la barra de estado.
+.It Cm bar_border Ns Bq Ar x
+Color del borde de la barra de estado en pantalla.
+.Ar x .
+.It Cm bar_border_width
+Setea el grosor de la barra de estado en pixels.
+Deshabilitado seteando 0.
+.It Cm bar_color Ns Bq Ar x
+Color de la ventana de la barra de estado en pantalla.
+.Ar x .
+.It Cm bar_font_color Ns Bq Ar x
+Color de la fuente en la barra de estado en pantalla.
+.Ar x .
+.It Cm bar_font
+Fuente de la barra de estado.
+.It Cm bar_action
+Scripts externos con populares agregados de información para la barra 
+de estado, como la vida de la bateria.
+.It Cm bar_delay
+Frecuencia de actualización, en segundos, de los scripts de la barra de 
+estado.
+.It Cm bar_at_bottom
+Puedes posicionar la statusbar en la parte inferior de la pantalla.
+.It Cm stack_enabled
+Habilitar o deshabilitar mostrar el algoritmo de apilamiento en la barra
+de estado.
+.It Cm clock_enabled
+Habilitar o deshabilitar el reloj en la barra de estado, deshabilitado 
+por defecto con un 0, para usar el reloj de la barra de estado 
+(bar_action)
+.Pa bar_action
+script.
+.It Cm dialog_ratio
+Algunas aplicaciones tienen ventanas de dialogo muy pequeñas como para 
+ser usables. Este relación (ratio) es el tamaño de la pantalla, por 
+ejemplo 0.6 es 60% del tamaño físico de la pantalla.
+.It Cm layout
+Selecciona una disposicion para usar en el primer inicio.
+Definido con el formato
+ws[idx]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode, 
+ej.
+ws[2]:-4:0:1:0:horizontal setea el escritorio 2 en horizontal, el stack 
+principal y reduce 4 puntos agregando una ventana al stack, mientras
+mantiene el comportamiento de ventanas flotantes.
+Modos posible de stack_mode
+.Pa vertical ,
+.Pa horizontal
+and
+.Pa fullscreen .
+.Pp
+Ver
+.Pa master_grow ,
+.Pa master_shrink ,  
+.Pa master_add ,  
+.Pa master_del ,
+.Pa stack_inc ,
+.Pa stack_del ,
+y
+.Pa always_raise
+para mas informacion.
+Tenga en cuenta que las opciones de stack son complicados y tienen 
+efectos secundarios.
+Uno debe familiarizarse con estos comandos antes de experimentar con la
+opcion
+.Pa layout
+.Pp
+Esta opcion no necesita un reinicio.
+.It Cm region
+Acomodar una region personalizada, removiendo cualquier autodeteción de 
+regiones que ocupe el espacio en la pantalla. 
+Definiendo el formato screen[<idx>]:WIDTHxHEIGHT+X+Y,
+e.g.\& screen[1]:800x1200+0+0.
+.It Cm term_width
+Setear un ancho minimo preferido para la terminal.
+Si el valor es mayor que 0,
+.Nm
+intentará ajustar el tamaño de la fuente de la terminal para mantener 
+el ancho de la terminal por encima de este número cuando la ventana 
+cambia de tamaño.
+Actualmente solo es soportado por
+.Xr xterm 1
+El binario de
+.Xr xterm 1
+no debe ser un setuid o setgid, que no sea el que viene por defecto en 
+la mayoria de los sistemas.
+Los usuarios pueden necesitar setear program[term] (ver la sección
+.Sx PROGRAMAS
+) para usar una copia alternativa del binario de
+.Xr xterm 1
+sin el seteo del setgid.
+.It Cm title_class_enabled
+Habilitar o deshabilitar la clase de ventana en la barre de estado.
+Habilitado seteando 1
+.It Cm title_name_enabled
+Habilitar o deshabilita el titulo de la ventana en la barra de estado.
+Habilitado seteando 1
+.It Cm urgent_enabled
+Habilitar o deshabilitar el aviso de urgencia.
+Tenga en cuenta que muchos emuladores de terminal requieren de este
+parametro habilitado para que funcione.
+En xterm, por ejemplo, hay que agregar la siguiente linea
+.Pa xterm.urgentOnBell: true
+to
+.Pa .Xdefaults .
+.It Cm window_name_enabled
+Habilitar o deshabilita el nombre de la ventana en la barra de estado.
+Habilitado seteando 1
+.It Cm verbose_layout
+Habilitar o deshabilita la notificacion del area principal y el
+stack en la barra de estado.
+Habilitado seteandolo a 1.
+.It Cm modkey
+Cambiar mod key.
+Mod1 generalmente es la tecla ALT y Mod4 la tecla de windows en una PC.
+.It Cm focus_mode
+Usando el valor de 
+.Pa follow_cursor 
+puedes hacer que el manejador de ventanas
+se enfoque en la ventana cuando el cursor pase por arriba de las mismas o
+bien cambiando de estacion de trabajo.
+.It Cm disable_border
+Remueve el borde de una sola ventana cuando la barra de estado esta desactivada.
+.It Cm border_width
+Setea el grosor del borde de la ventana en pixels.
+Deshabilitar todos los bordes seteandolo a 0.
+.It Cm program Ns Bq Ar p
+Definir una nueva accion para ejecutar un programa.
+.Ar p .
+Ver la sección de
+.Sx PROGRAMAS
+.It Cm bind Ns Bq Ar x
+Combinación de teclas para una acción
+.Ar x .
+Ver la sección
+.Sx BINDINGS
+.It Cm quirk Ns Bq Ar c:n
+Agregar un "quirk" (o forzados) para ventanas con clase
+.Ar c
+y nombre
+.Ar n .
+Ver la sección
+.Sx QUIRKS
+.El
+.Pp
+Los colores deben ser especificados por la especificación
+.Xr XQueryColor 3
+y las fuentes por la especificación
+.Xr XQueryFont 3
+.Sh PROGRAMAS
+.Nm
+te permite definir acciones personales para lanzar los programas que 
+quieras y luego obligar a la misma con una función de acciones.
+Ver la sección
+.Sx BINDINGS
+.Pp
+Los programas por defecto se describen acá:
+.Pp
+.Bl -tag -width "screenshot_wind" -offset indent -compact
+.It Cm term
+xterm
+.It Cm screenshot_all
+screenshot.sh completo
+.It Cm screenshot_wind
+screenshot.sh por ventana
+.It Cm lock
+xlock
+.It Cm initscr
+initscreen.sh
+.It Cm menu
+dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
+.El
+.Pp
+Los programas en la configuración personal, se especifican aca:
+.Pp
+.Dl program[<nombre>] = <progpath> [<arg> [... <arg>]]
+.Pp
+.Aq nombre
+es un identificador, no genera conflictos con ninguna accion o palabra 
+clave,
+.Aq progpath
+es la ruta al programa, y
+.Aq arg
+es ninguno o mas de un argumento para el programa.
+.Pp
+Las siguientes variables de configuracion en
+.Nm
+(ver 
+.Sx ARCHIVOS DE CONFIGURACIÓN
+),
+y pueden ser usadas en los campos de
+.Aq arg
+como asi tambien sustituidas por valores al momento del inicio de un 
+programa:
+.Pp
+.Bl -tag -width "$bar_font_color" -offset indent -compact
+.It Cm $bar_border
+.It Cm $bar_color
+.It Cm $bar_font
+.It Cm $bar_font_color
+.It Cm $color_focus
+.It Cm $color_unfocus
+.El
+.Pp
+Ejemplo:
+.Bd -literal -offset indent
+program[ff] = /usr/local/bin/firefox http://spectrwm.com.ar/
+bind[ff] = Mod+f # Ahora Mod+F inicia firefox
+.Ed
+.Pp
+Para deshacer lo anterior:
+.Bd -literal -offset indent
+bind[] = Mod+f
+program[ff] =
+.Ed
+.Sh BINDINGS
+.Nm
+provee muchas funciones (o acciones) accesibles por medio de la 
+asignación (bindings) de teclas o el mouse.
+.Pp
+Las corrientes asignaciones (bindings) del mouse son:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M1
+Enfoco una ventana
+.It Cm M-M1
+Muevo una ventana
+.It Cm M-M3
+Redimenciono una ventana
+.It Cm M-S-M3
+Redimenciono una ventana hasta que quede centrada
+.El
+.Pp
+Las corrientes asignaciones (bindings) de teclas son:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M-S- Ns Aq Cm Return
+term
+.It Cm M-p
+menu
+.It Cm M-S-q
+quit
+.It Cm M-q
+restart
+.Nm
+.It Cm M- Ns Aq Cm Space
+cycle_layout
+.It Cm M-S- Ns Aq Cm Space
+reset_layout
+.It Cm M-h
+master_shrink
+.It Cm M-l
+master_grow
+.It Cm M-,
+master_add
+.It Cm M-.
+master_del
+.It Cm M-S-,
+stack_inc
+.It Cm M-S-.
+stack_del
+.It Cm M- Ns Aq Cm Return
+swap_main
+.It Xo
+.Cm M-j ,
+.Cm M- Ns Aq Cm TAB
+.Xc
+focus_next
+.It Xo
+.Cm M-k ,
+.Cm M-S- Ns Aq Cm TAB
+.Xc
+focus_prev
+.It Cm M-m
+focus_main
+.It Cm M-S-j
+swap_next
+.It Cm M-S-k
+swap_prev
+.It Cm M-b
+bar_toggle
+.It Cm M-x
+wind_del
+.It Cm M-S-x
+wind_kill
+.It Cm M- Ns Aq Ar n
+.Ns ws_ Ns Ar n
+.It Cm M-S- Ns Aq Ar n
+.Ns mvws_ Ns Ar n
+.It Cm M- Ns Aq Cm Right
+ws_next
+.It Cm M- Ns Aq Cm Left
+ws_prev
+.It Cm M-a
+ws_prior
+.It Cm M-S- Ns Aq Cm Right
+screen_next
+.It Cm M-S- Ns Aq Cm Left
+screen_prev
+.It Cm M-s
+screenshot_all
+.It Cm M-S-s
+screenshot_wind
+.It Cm M-S-v
+version
+.It Cm M-t
+float_toggle
+.It Cm M-S Aq Cm Delete
+lock
+.It Cm M-S-i
+initscr
+.It Cm M-w                    
+iconify
+.It Cm M-S-w
+uniconify
+.It Cm M-S-r
+always_raise
+.It Cm M-v
+button2
+.It Cm M--
+width_shrink
+.It Cm M-=
+width_grow
+.It Cm M-S-
+height_shrink
+.It Cm M-S-=
+height_grow
+.It Cm M-[
+move_left
+.It Cm M-]
+move_right
+.It Cm M-S-[
+move_up
+.It Cm M-S-]
+move_down
+.El
+.Pp
+El nombre de las acciónes descripta a continuación:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm term
+Ejecutar una terminal
+(ver
+.Sx PROGRAMAS
+)
+.It Cm menu
+Menu
+(ver
+.Sx PROGRAMAS
+)
+.It Cm quit
+Salir
+.Nm
+.It Cm restart
+Reiniciar
+.Nm
+.It Cm cycle_layout
+Disposición de las ventanas
+.It Cm reset_layout
+Reiniciar la disposición de las ventanas
+.It Cm master_shrink
+Achicar la region principal
+.It Cm master_grow
+Agrandar la region principal
+.It Cm master_add
+Agregar una ventana a la region principal
+.It Cm master_del
+Quitar una ventana de la region principal
+.It Cm stack_inc
+Agregar columnas/filas a las pilas
+.It Cm stack_del
+Quitar columnas/filas de las pilas
+.It Cm swap_main
+Mover la ventana corriente a la region principal
+.It Cm focus_next
+Enfocar la proxima ventana en la estación de trabajo
+.It Cm focus_prev
+Enfocar la anterior ventana en la estación de trabajo
+.It Cm focus_main
+Enfocar en la ventana principal de la estación de trabajo
+.It Cm swap_next
+Ejecutar con la siguiente ventana en la estación de trabajo
+.It Cm swap_prev
+Ejecutar con la anterior ventana en la estación de trabajo
+.It Cm bar_toggle
+Cambiar la barra de estado en todas las estaciones de trabajo
+.It Cm wind_del
+Borrar la ventana corriente en la estación de trabajo
+.It Cm wind_kill
+Destruir la ventana corriente en la estación de trabajo
+.It Cm ws_ Ns Ar n
+Cambiar entre estaciones de trabajo
+.Ar n ,
+donde
+.Ar n
+es 1 por 10
+.It Cm mvws_ Ns Ar n
+Mover la ventana corriente a una estación de trabajo
+.Ar n ,
+donde
+.Ar n
+es 1 por 10
+.It Cm ws_next
+Cambiar a la proxima estación de trabajo con una ventana en ella
+.It Cm ws_prev
+Cambiar a la anterior estación de trabajo con una ventana en ella
+.It Cm screen_next
+Mover el puntero a la proxima region
+.It Cm screen_prev
+Mover el puntero a la anterior region
+.It Cm screenshot_all
+Tomar una captura de pantalla de todo la pantalla (si esta habilitado)
+(ver
+.Sx PROGRAMAS
+)
+.It Cm screenshot_wind
+Tomar una captura de pantalla de la ventana seleccionada (si esta habilitado)
+(ver
+.Sx PROGRAMAS
+)
+.It Cm version
+Mostrar la version en la barra de estado
+.It Cm float_toggle
+Mostar la ventana en foco entre las flotantes y acomodadas
+.It Cm lock
+Bloquear pantalla
+(ver
+.Sx PROGRAMAS
+)
+.It Cm initscr
+Reiniciar la pantalla
+(ver
+.Sx PROGRAMAS
+)
+.It Cm iconify
+Minimiza (unmap) la ventana en foco.
+.It Cm uniconify
+Maximiza (map) la ventana seleccionada por dmenu.
+.It Cm always_raise
+Cuando se establece las ventanas en cascada se esconden las 
+ventanas flotantes.
+.It Cm button2
+Falsifica el boton del medio del mouse.
+.It Cm width_shrink
+Reducir el ancho de una ventana flotante.
+.It Cm width_grow  
+Agranda el ancho de una ventana flotante.
+.It Cm height_shrink
+Reducir la altura de una ventana flotante.
+.It Cm height_grow
+Agranda la altura de una ventana flotante.
+.It Cm move_left
+Mueve la ventana flotante un paso a la izquierda.
+.It Cm move_right
+Mueve la ventana flotante un paso a la derecha.
+.It Cm move_up
+Mueve la ventana flotante un paso arriba.
+.It Cm move_down
+Mueve la ventana flotante un paso abajo.
+.El
+.Pp
+Personalizar mapeos (bindings) en el archivo de configuración:
+.Pp
+.Dl bind[<accion>] = <teclas>
+.Pp
+.Aq accion
+una de las acciones listadas (o ninguna) y
+.Aq teclas
+una o mas teclas modificadas (puede ser ninguna tambien)
+(MOD, Mod1, Shift, etc.) y una o mas teclas normales
+(b, barra espaciadora, etc.), separadas por un "+".
+Por ejemplo:
+.Bd -literal -offset indent
+bind[reset] = Mod4+q # combinación Tecla de Windows + q reinicia
+bind[] = Mod1+q # des-hace la combinación Alt + q
+.Ed
+.Pp
+Multiples combinaciones de teclas pueden hacer lo mismo.
+.Sh QUIRKS
+.Nm
+te da "quirks" (o forzados) ventanas que tienen que ser tratas de manera especial,
+como por ejemplo, popups, aplicaciones de pantalla completa, etc.
+.Pp
+Los "quirks" (o forzados) por defecto son:
+.Pp
+.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
+.It Firefox\-bin:firefox\-bin
+TRANSSZ
+.It Firefox:Dialog
+FLOAT
+.It Gimp:gimp
+FLOAT + ANYWHERE
+.It MPlayer:xv
+FLOAT + FULLSCREEN
+.It OpenOffice.org 2.4:VCLSalFrame
+FLOAT
+.It OpenOffice.org 3.1:VCLSalFrame
+FLOAT
+.It pcb:pcb
+FLOAT
+.It xine:Xine Window
+FLOAT + ANYWHERE
+.It xine:xine Panel
+FLOAT + ANYWHERE
+.It xine:xine Video Fullscreen Window
+FULLSCREEN + FLOAT
+.It Xitk:Xitk Combo
+FLOAT + ANYWHERE
+.It Xitk:Xine Window
+FLOAT + ANYWHERE
+.It XTerm:xterm
+XTERM_FONTADJ
+.El
+.Pp
+Los "quirks" (o forzados) se describen a continuación:
+.Pp
+.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
+.It FLOAT
+Esta ventana no tiene que ser acomodada, pero le permitimos flotar libremente.
+.It TRANSSZ
+Ajusta el tamaño de las ventanas transitorias que son demasiado pequeñas utilizando dialog_ratio
+(ver
+.Sx ARCHIVOS DE CONFIGURACIÓN ) .
+.It ANYWHERE
+Permite que la ventana se ponga donde quiera.
+.It XTERM_FONTADJ
+Ajusta las fuentes de xterm cuando se redimenciona.
+.It FULLSCREEN
+Quita el borde para permitir las ventanas en pantalla completa.
+.It FOCUSPREV
+El enfoque de salida fuerza la solicitud de aplicacisn que 
+anteriormente se centraba en la aplicacion anterior del stack.
+.El
+.Pp
+Las configuraciones de "quirks" (o forzados) en el archivo de configuración se ven a continuación:
+.Pp
+.Dl quirk[<clases>:<nombre>] = <quirk> [ + <quirk> ... ]
+.Pp
+.Aq clases
+y
+.Aq nombre
+especifica la ventana en la cual el "quirk(s)" (o forzados) se aplica, y
+.Aq quirk
+es uno de los "quirks" (o forzados) de la lista.
+Por ejemplo:
+.Bd -literal -offset indent
+quirk[MPlayer:xv] = FLOAT + FULLSCREEN # dejamos que mplayer funcione libremente
+quirk[pcb:pcb] = NONE  # borramos el quirk existente
+.Ed
+.Pp
+Podes obtener
+.Aq clases
+y
+.Aq nombre
+corriendo el programa xprop(1) y luego clickear en la ventana que quieras.
+En el proximo ejemplo, podremos verlo en acción con una ventana de Firefox:
+.Bd -literal -offset indent
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "Navigator", "Firefox"
+.Ed
+.Sh EWMH
+.Nm
+parcialmente implementa los Consejos de ventana extendido Manager (EWMH) especificacion.
+Esto permite el control de las ventanas, asi como
+.Nm
+si a partir de scripts y programas externos. Esto se logra mediante
+.Nm
+responder a ciertos eventos ClientMessage. Desde la terminal de estos eventos
+se puede enviar facilmente el uso de herramientas tales como
+.Xr wmctrl 1
+y
+.Xr xdotool 1 .
+para el
+formato real de estos eventos ClientMessage, consulte la especificacion EWMH.
+.Pp
+La Identificacion de la ventana actualmente enfocada se almacena en el _NET_ACTIVE_WINDOW
+propiedad de la ventana raiz. Esto puede ser usado por ejemplo para recuperar el
+titulo de la ventana activa con
+.Xr xprop 1
+y
+.Xr grep 1 :
+.Bd -literal -offset indent
+$ WINDOWID=`xprop \-root _NET_ACTIVE_WINDOW | grep \-o "0x.*"`
+$ xprop \-id $WINDOWID WM_NAME | grep \-o "\\".*\\""
+.Ed
+.Pp
+Una ventana se puede enfocar mediante el envio de un mensaje del cliente _NET_ACTIVE_WINDOW
+a la ventana principal. Por ejemplo, usando
+.Xr wmctrl 1
+para enviar el mensaje
+(suponiendo que 0x4a0000b es el ID de la ventana para ser especifico):
+.Bd -literal -offset indent
+$ wmctrl \-i \-a 0x4a0000b
+.Ed
+.Pp
+Ventanas se pueden cerrar mediante el envmo de un mensaje del cliente _NET_CLOSE_WINDOW
+a la ventana principal. Por ejemplo, usando
+.Xr wmctrl 1
+para enviar el mensaje
+(suponiendo que 0x4a0000b es el ID de la ventana se cierre):
+.Bd -literal -offset indent
+$ wmctrl \-i \-c 0x4a0000b
+.Ed
+.Pp
+Las ventanas se pueden flotar y flotar sin-mediante la adicion o eliminacion de la
+_NET_WM_STATE_ABOVE atom desde _NET_WM_STATE la propiedad de la ventana
+Esto se puede lograr mediante el envio de un mensaje a los clientes _NET_WM_STATE
+raiz de la ventana. Por ejemplo, el siguiente cambia el estado de la flota.
+.Xr wmctrl 1
+para enviar el mensaje (suponiendo que 0x4a0000b es el ID de la ventana flotante
+o no-flotante):
+.Bd -literal -offset indent
+$ wmctrl \-i \-r 0x4a0000b \-b toggle,_NET_WM_STATE_ABOVE
+.Ed
+.Pp
+Ventanas flotantes tambien se puede cambiar el tamano y movido por el envio de un
+_NET_MOVERESIZE_WINDOW Mensaje del cliente de la ventana raiz. Por ejemplo,
+uso
+.Xr wmctrl 1
+para enviar el mensaje (suponiendo que 0x4a0000b es el ID de
+la ventana a redimensionar / mover):
+.Bd -literal -offset indent
+$ wmctrl \-i \-r 0x4a0000b \-e 0,100,50,640,480
+.Ed
+.Pp
+Esto mueve la ventana de (100,50) y cambia el tamaqo a 640x480.
+.Pp
+Todos los eventos _NET_MOVERESIZE_WINDOW recibido por las ventanas apiladas se ignoran.
+.Pp
+.Sh SIGNALS
+Enviando
+.Nm
+una senal de HUP reinicia spectrwm.
+.Pp
+.Sh ARCHIVOS
+.Bl -tag -width "/etc/spectrwm.confXXX" -compact
+.It Pa ~/.spectrwm.conf
+.Nm
+archivo de configuración especifico del usuario.
+.It Pa /etc/spectrwm.conf
+.Nm
+configuraciones globales.
+.El
+.Sh HISTORIA
+.Nm
+fue inspirado en xmonad y dwm.
+.Sh AUTORES
+.An -nosplit
+.Pp
+.Nm
+fue escrito por
+.An Marco Peereboom Aq marco@peereboom.us ,
+.An Ryan Thomas McBride Aq mcbride@countersiege.com
+and
+.An Darrin Chandler Aq dwchandler@stilyagin.com .
+.Sh BUGS
+Actualmente el menu, se llama con
+.Cm M-p ,
+depende de dmenu.
diff --git a/spectrwm_es.conf b/spectrwm_es.conf
new file mode 100644 (file)
index 0000000..b585381
--- /dev/null
@@ -0,0 +1,74 @@
+# Key bindings for Spanish (es) keyboards
+# unbind with: bind[] = <keys>
+bind[cycle_layout]     = MOD+space
+bind[flip_layout]      = MOD+Shift+backslash
+bind[stack_reset]      = MOD+Shift+space
+bind[master_shrink]    = MOD+h
+bind[master_grow]      = MOD+l
+bind[master_add]       = MOD+comma
+bind[master_del]       = MOD+period
+bind[stack_inc]                = MOD+Shift+comma
+bind[stack_dec]                = MOD+Shift+period
+bind[swap_main]                = MOD+Return
+bind[focus_next]       = MOD+j
+bind[focus_prev]       = MOD+k
+bind[swap_next]                = MOD+Shift+j
+bind[swap_prev]                = MOD+Shift+k
+bind[spawn_term]       = MOD+Shift+Return
+bind[menu]             = MOD+p
+bind[quit]             = MOD+Shift+q
+bind[restart]          = MOD+q
+bind[focus_main]       = MOD+m
+bind[ws_1]             = MOD+1
+bind[ws_2]             = MOD+2
+bind[ws_3]             = MOD+3
+bind[ws_4]             = MOD+4
+bind[ws_5]             = MOD+5
+bind[ws_6]             = MOD+6
+bind[ws_7]             = MOD+7
+bind[ws_8]             = MOD+8
+bind[ws_9]             = MOD+9
+bind[ws_10]            = MOD+0
+bind[ws_next]          = MOD+Right
+bind[ws_prev]          = MOD+Left
+bind[ws_next_all]      = MOD+Up
+bind[ws_prev_all]      = MOD+Down
+bind[ws_prior]         = MOD+a
+bind[screen_next]      = MOD+Shift+Right
+bind[screen_prev]      = MOD+Shift+Left
+bind[mvws_1]           = MOD+Shift+1
+bind[mvws_2]           = MOD+Shift+2
+bind[mvws_3]           = MOD+Shift+3
+bind[mvws_4]           = MOD+Shift+4
+bind[mvws_5]           = MOD+Shift+5
+bind[mvws_6]           = MOD+Shift+6
+bind[mvws_7]           = MOD+Shift+7
+bind[mvws_8]           = MOD+Shift+8
+bind[mvws_9]           = MOD+Shift+9
+bind[mvws_10]          = MOD+Shift+0
+bind[bar_toggle]       = MOD+b
+bind[focus_next]       = MOD+Tab
+bind[focus_prev]       = MOD+Shift+Tab
+bind[wind_kill]                = MOD+Shift+x
+bind[wind_del]         = MOD+x
+bind[screenshot_all]   = MOD+s
+bind[screenshot_wind]  = MOD+Shift+s
+bind[float_toggle]     = MOD+t
+bind[version]          = MOD+Shift+v
+bind[lock]             = MOD+Shift+Delete
+bind[initscr]          = MOD+Shift+i
+bind[iconify]          = MOD+w
+bind[uniconify]                = MOD+Shift+w
+bind[raise_toggle]     = MOD+Shift+r
+bind[button2]          = MOD+v
+bind[width_shrink]     = MOD+apostrophe
+bind[width_grow]       = MOD+exclamdown
+bind[height_shrink]    = MOD+Shift+apostrophe
+bind[height_grow]      = MOD+Shift+exclamdown
+bind[move_left]                = MOD+dead_grave
+bind[move_right]       = MOD+plus
+bind[move_up]          = MOD+Shift+dead_grave
+bind[move_down]                = MOD+Shift+plus
+bind[name_workspace]   = MOD+Shift+slash
+bind[search_workspace] = MOD+slash
+bind[search_win]       = MOD+f
diff --git a/spectrwm_fr.conf b/spectrwm_fr.conf
new file mode 100644 (file)
index 0000000..d56aabb
--- /dev/null
@@ -0,0 +1,74 @@
+# Key bindings for French (fr) keyboards
+# unbind with: bind[] = <keys>
+bind[cycle_layout]     = MOD+space
+bind[flip_layout]      = MOD+Shift+backslash
+bind[stack_reset]      = MOD+Shift+space
+bind[master_shrink]    = MOD+h
+bind[master_grow]      = MOD+l
+bind[master_add]       = MOD+comma
+bind[master_del]       = MOD+semicolon
+bind[stack_inc]                = MOD+Shift+comma
+bind[stack_dec]                = MOD+Shift+semicolon
+bind[swap_main]                = MOD+Return
+bind[focus_next]       = MOD+j
+bind[focus_prev]       = MOD+k
+bind[swap_next]                = MOD+Shift+j
+bind[swap_prev]                = MOD+Shift+k
+bind[spawn_term]       = MOD+Shift+Return
+bind[menu]             = MOD+p
+bind[quit]             = MOD+Shift+q
+bind[restart]          = MOD+q
+bind[focus_main]       = MOD+m
+bind[ws_1]             = MOD+ampersand
+bind[ws_2]             = MOD+eacute
+bind[ws_3]             = MOD+quotedbl
+bind[ws_4]             = MOD+apostrophe
+bind[ws_5]             = MOD+parenleft
+bind[ws_6]             = MOD+hyphen
+bind[ws_7]             = MOD+egrave
+bind[ws_8]             = MOD+underscore
+bind[ws_9]             = MOD+ccedilla
+bind[ws_10]            = MOD+agrave
+bind[ws_next]          = MOD+Right
+bind[ws_prev]          = MOD+Left
+bind[ws_next_all]      = MOD+Up
+bind[ws_prev_all]      = MOD+Down
+bind[ws_prior]         = MOD+a
+bind[screen_next]      = MOD+Shift+Right
+bind[screen_prev]      = MOD+Shift+Left
+bind[mvws_1]           = MOD+Shift+ampersand
+bind[mvws_2]           = MOD+Shift+eacute
+bind[mvws_3]           = MOD+Shift+quotedbl
+bind[mvws_4]           = MOD+Shift+apostrophe
+bind[mvws_5]           = MOD+Shift+parenleft
+bind[mvws_6]           = MOD+Shift+hyphen
+bind[mvws_7]           = MOD+Shift+egrave
+bind[mvws_8]           = MOD+Shift+underscore
+bind[mvws_9]           = MOD+Shift+ccedilla
+bind[mvws_10]          = MOD+Shift+agrave
+bind[bar_toggle]       = MOD+b
+bind[focus_next]       = MOD+Tab
+bind[focus_prev]       = MOD+Shift+Tab
+bind[wind_kill]                = MOD+Shift+x
+bind[wind_del]         = MOD+x
+bind[screenshot_all]   = MOD+s
+bind[screenshot_wind]  = MOD+Shift+s
+bind[float_toggle]     = MOD+t
+bind[version]          = MOD+Shift+v
+bind[lock]             = MOD+Shift+Delete
+bind[initscr]          = MOD+Shift+i
+bind[iconify]          = MOD+w
+bind[uniconify]                = MOD+Shift+w
+bind[raise_toggle]     = MOD+Shift+r
+bind[button2]          = MOD+v
+bind[width_shrink]     = MOD+minus
+bind[width_grow]       = MOD+equal
+bind[height_shrink]    = MOD+Shift+minus
+bind[height_grow]      = MOD+Shift+equal
+bind[move_left]                = MOD+ugrave
+bind[move_right]       = MOD+asterisk
+bind[move_up]          = MOD+Shift+ugrave
+bind[move_down]                = MOD+Shift+asterisk
+bind[name_workspace]   = MOD+Shift+slash
+bind[search_workspace] = MOD+slash
+bind[search_win]       = MOD+f
diff --git a/spectrwm_fr_ch.conf b/spectrwm_fr_ch.conf
new file mode 100644 (file)
index 0000000..f78c5bb
--- /dev/null
@@ -0,0 +1,74 @@
+# Key bindings for Swiss French (FR_CH) keyboards
+# unbind with: bind[] = <keys>
+bind[cycle_layout]     = MOD+space
+bind[flip_layout]      = MOD+Shift+backslash
+bind[stack_reset]      = MOD+Shift+space
+bind[master_shrink]    = MOD+h
+bind[master_grow]      = MOD+l
+bind[master_add]       = MOD+comma
+bind[master_del]       = MOD+period
+bind[stack_inc]                = MOD+Shift+comma
+bind[stack_dec]                = MOD+Shift+period
+bind[swap_main]                = MOD+Return
+bind[focus_next]       = MOD+j
+bind[focus_prev]       = MOD+k
+bind[swap_next]                = MOD+Shift+j
+bind[swap_prev]                = MOD+Shift+k
+bind[spawn_term]       = MOD+Shift+Return
+bind[menu]             = MOD+p
+bind[quit]             = MOD+Shift+q
+bind[restart]          = MOD+q
+bind[focus_main]       = MOD+m
+bind[ws_1]             = MOD+1
+bind[ws_2]             = MOD+2
+bind[ws_3]             = MOD+3
+bind[ws_4]             = MOD+4
+bind[ws_5]             = MOD+5
+bind[ws_6]             = MOD+6
+bind[ws_7]             = MOD+7
+bind[ws_8]             = MOD+8
+bind[ws_9]             = MOD+9
+bind[ws_10]            = MOD+0
+bind[ws_next]          = MOD+Right
+bind[ws_prev]          = MOD+Left
+bind[ws_next_all]      = MOD+Up
+bind[ws_prev_all]      = MOD+Down
+bind[ws_prior]         = MOD+a
+bind[screen_next]      = MOD+Shift+Right
+bind[screen_prev]      = MOD+Shift+Left
+bind[mvws_1]           = MOD+Shift+1
+bind[mvws_2]           = MOD+Shift+2
+bind[mvws_3]           = MOD+Shift+3
+bind[mvws_4]           = MOD+Shift+4
+bind[mvws_5]           = MOD+Shift+5
+bind[mvws_6]           = MOD+Shift+6
+bind[mvws_7]           = MOD+Shift+7
+bind[mvws_8]           = MOD+Shift+8
+bind[mvws_9]           = MOD+Shift+9
+bind[mvws_10]          = MOD+Shift+0
+bind[bar_toggle]       = MOD+b
+bind[focus_next]       = MOD+Tab
+bind[focus_prev]       = MOD+Shift+Tab
+bind[wind_kill]                = MOD+Shift+x
+bind[wind_del]         = MOD+x
+bind[screenshot_all]   = MOD+s
+bind[screenshot_wind]  = MOD+Shift+s
+bind[float_toggle]     = MOD+t
+bind[version]          = MOD+Shift+v
+bind[lock]             = MOD+Shift+Delete
+bind[initscr]          = MOD+Shift+i
+bind[iconify]          = MOD+w
+bind[uniconify]                = MOD+Shift+w
+bind[raise_toggle]     = MOD+Shift+r
+bind[button2]          = MOD+v
+bind[width_shrink]     = MOD+minus
+bind[width_grow]       = MOD+egrave
+bind[height_shrink]    = MOD+Shift+minus
+bind[height_grow]      = MOD+Shift+egrave
+bind[move_left]                = MOD+eacute
+bind[move_right]       = MOD+agrave
+bind[move_up]          = MOD+Shift+eacute
+bind[move_down]                = MOD+Shift+agrave
+bind[name_workspace]   = MOD+Shift+apostrophe
+bind[search_workspace] = MOD+apostrophe
+bind[search_win]       = MOD+f
diff --git a/spectrwm_it.1 b/spectrwm_it.1
new file mode 100644 (file)
index 0000000..09d7356
--- /dev/null
@@ -0,0 +1,755 @@
+.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: September 15 2011 $
+.Dt SPECTRWM 1
+.Os
+.Sh NOME
+.Nm spectrwm
+.Nd gestore di finestre per X11
+.Sh SINTASSI
+.Nm spectrwm
+.Sh DESCRIZIONE
+.Nm
+? un gestore di finestre minimale che cerca di stare in disparte, in modo
+che il prezioso spazio sullo schermo possa essere usato per cose pi?
+importanti. Hai dei default sensati e non costringe l'utente ad imparare
+un linguaggio di programmazione per configurarlo. ? stato scritto dagli
+hacker per gli hacker e cerca di essere piccolo, compatto e veloce.
+.Pp
+Quando
+.Nm
+viene avviato, legge le impostazioni presenti nel file di configurazione
+.Pa spectrwm.conf .
+Vedere la sezione
+.Sx FILE DI CONFIGURAZIONE
+pi? sotto.
+.Pp
+In questa pagina di manuale viene usata la seguente notazione:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Cm M
+Meta
+.It Cm S
+Shift
+.It Aq Cm Nome
+Tasto nome
+.It Cm M1
+Tasto 1 (sinistro) del mouse
+.It Cm M3
+Tasto 3 (destro) del mouse
+.El
+.Pp
+.Nm
+? molto semplice da usare. La maggior parte delle operazioni vengono
+svolte usando combinazioni di tasti sulla tastiera o sul mouse.
+Vedere la sezione
+.Sx SCORCIATOIE
+pi? sotto per i default e le possibilit? di personalizzazione.
+.Sh FILE DI CONFIGURAZIONE
+.Nm
+prova per prima cosa ad aprire il file di configurazione personale
+dell'utente,
+.Pa ~/.spectrwm.conf .
+Se il file in questione non ? disponibile, prova ad usare il file di
+configurazione globale
+.Pa /etc/spectrwm.conf .
+.Pp
+Il formato di questo file ? \*(Ltchiave\*(Gt = \*(Ltvalore\*(Gt.
+Per esempio:
+.Pp
+.Dl color_focus = red
+.Pp
+Per abilitare o disabilitare un'opzione, usare i valori 1 o 0
+rispettivamente.
+.Pp
+Il file supporta le seguenti chiavi:
+.Pp
+.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
+.It Cm autorun
+Esegue un'applicazione nel workspace specificato all'avvio.
+Definito nel formato ws[<idx>]:applicazione, eg. ws[2]:xterm esegue un
+xterm nell'area di lavoro 2.
+.It Cm color_focus
+Colore del bordo della finestra che ha il focus.
+.It Cm color_unfocus
+Colore del bordo delle finestre che non hanno il focus.
+.It Cm bar_enabled
+Abilita o disabilita la barra di stato.
+.It Cm bar_border Ns Bq Ar x
+Colore del bordo della barra di stato nello schermo
+.Ar x .
+.It Cm bar_border_width
+Spessore del bordo attorno alla barra di stato in pixel. Il bordo
+pu? essere disabilitato usando il valore 0.
+.It Cm bar_color Ns Bq Ar x
+Colore della barra di stato nello schermo
+.Ar x .
+.It Cm bar_font_color Ns Bq Ar x
+Colore del testo della barra di stato nello schermo
+.Ar x .
+.It Cm bar_font
+Font della barra di stato.
+.It Cm bar_action
+Script esterno che aggiunge informazioni come la carica della batteria alla
+barra di stato.
+.It Cm bar_delay
+Frequenza di aggiornamento, in secondi, dello script esterno che aggiunge
+informazioni alla barra di stato.
+.It Cm bar_at_bottom
+Posiziona la barra di stato sul fondo dello schermo anzich? in cima.
+.It Cm stack_enabled
+Abilita o disabilita la visualizzazione dell'algoritmo di stacking
+corrente nella barra di stato.
+.It Cm clock_enabled
+Abilita o disabilita l'orologio nella barra di stato. Se disabilitato,
+usando il valore 0, ? possibile usare un orologio personalizzato nello
+script specificato in
+.Pa bar_action .
+.It Cm dialog_ratio
+Alcune applicazioni hanno finestre di dialogo troppo piccole per risultare
+utili. Questa ? la percentuale dello schermo che verr? usata per le finestre
+di dialogo: ad esempio, 0.6 indica il 60% della dimensione fisica dello
+schermo.
+.It Cm layout
+Layout da utilizzare all'avvio. Definito nel formato
+ws[<idx>]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode,
+eg. ws[2]:-4:0:1:0:horizontal assegna il layout orizzontale all'area di
+lavoro 2, riduce l'area principale di 4 unit?, aggiunge una finestra allo
+stack e mantiene il comportamento predefinito per quanto riguarda le
+finestre floating.
+I valori possibili per stack_mode sono
+.Pa vertical ,
+.Pa horizontal
+e
+.Pa fullscreen .
+.Pp
+Fare riferimento a
+.Pa master_grow ,
+.Pa master_shrink ,
+.Pa master_add ,
+.Pa master_del ,
+.Pa stack_inc ,
+.Pa stack_del
+e
+.Pa always_raise
+per ulteriori informazioni.
+Queste impostazioni sono complesse e hanno effetti secondari; ? opportuno
+familiarizzare con questi comandi prima di modificare l'opzione
+.Pa layout .
+.Pp
+Questa impostazione non viene applicata dopo il restart.
+.It Cm region
+Alloca una regione personalizzata, rimuovendo qualsiasi regione
+automaticamente rilevata stia occupando lo stesso spazio sullo schermo.
+Definita nel formato screen[<idx>]:LARGHEZZAxALTEZZA+X+Y, ad esempio
+\& screen[1]:800x1200+0+0.
+.Pp
+Per fare s? che pi? monitor vengano considerati come una singola entit?
+? sufficiente creare una regione sufficientemente grande da contenerli,
+eg. screen[1]:2048x760+0+0 unisce due monitor con risoluzione 1024x768
+posizionati uno di fianco all'altro.
+.It Cm term_width
+Imposta la dimensione minima preferita per il terminale. Se questo valore
+? maggiore di 0,
+.Nm
+cercher? di riaggiustare la dimensione del testo nel terminale in modo che
+la larghezza del terminale rimanga sopra il valore quando la finestra
+viene ridimensionata. Al momento solo
+.Xr xterm 1
+? supportato. Il binario di
+.Xr xterm 1
+deve essere setuid o setgid perch? questo funzioni: nella maggior parte dei
+sistemi, questo ? il default. L'utente potrebbe voler impostare
+program[term] (vedere la sezione
+.Sx PROGRAMMI
+pi? sotto) per usare una seconda copia del binario di
+.Xr xterm 1
+che non abbia il bit setgid impostato.
+.It Cm title_class_enabled
+Abilita o disabilita la visualizzazione della classe della finestra nella
+barra di stato. Impostare a 1 per abilitare.
+.It Cm title_name_enabled
+Abilita o disabilita la visualizzazione del titolo della finestra nella
+barra di stato. Impostare a 1 per abilitare.
+.It Cm urgent_enabled
+Abilita o disabilita l'hint "urgente".
+In molti emulatori di terminale, il supporto deve essere abilitato
+separatamente: per xterm, ad esempio, ? necessario aggiungere la riga
+.Pa xterm.urgentOnBell: true
+al file
+.Pa .Xdefaults .
+.It Cm window_name_enabled
+Abilita o disabilita la visualizzazione del nome della finestra nella
+barra di stato. Impostare a 1 per abilitare.
+.It Cm verbose_layout
+Abilita o disabilita la visualizzazione dei valori correnti di master e
+stack nella barra di stato. Impostare a 1 per abilitare.
+.It Cm modkey
+Cambia il tasto modificatore.
+Solitamente Mod1 ? il tasto ALT e Mod4 ? il tasto Windows su un PC.
+.It Cm focus_mode
+Se viene usato il valore
+.Pa follow_cursor ,
+il gestore di finestre dar? il focus alla finestra sotto il puntatore
+quando si cambia area di lavoro o si creano finestre.
+.It Cm disable_border
+Rimuovi il bordo dalle finestre se la barra di stato ? nascosta e c'?
+una sola finestra sullo schermo.
+.It Cm border_width
+Spessore del bordo delle finestre in pixel. Il valore 0 disabilita il bordo.
+.It Cm program Ns Bq Ar p
+Definisce una nuova azione per lanciare il programma
+.Ar p .
+Vedere la sezione
+.Sx PROGRAMMI
+pi? sotto.
+.It Cm bind Ns Bq Ar x
+Assegna una combinazione di tasti all'azione
+.Ar x .
+Vedere la sezione
+.Sx SCORCIATOIE
+pi? sotto.
+.It Cm quirk Ns Bq Ar c:n
+Aggiunge un "quirk" per le finestre di classe
+.Ar c
+e nome
+.Ar n .
+Vedere la sezione
+.Sx QUIRKS
+pi? sotto.
+.El
+.Pp
+I colori devono essere specificati nel formato usato da
+.Xr XQueryColor 3
+e i font in quello usato da
+.Xr XQueryFont 3 .
+.Pp
+Per avere una lista dei font disponibili sul proprio sistema utilizzare
+.Xr fc-list 1
+o
+.Xr xlsfonts 1 .
+L'applicazione
+.Xr xfontsel 1
+? utile per visualizzare la X Logical Font Description ("XLFD") usata per
+la chiave
+.Pa bar_font .
+.Sh PROGRAMMI
+.Nm
+consente la definizione di azioni personalizzate per lanciare programmi di
+propria scelta, che possono essere assegnate a combinazioni di tasti nello
+stesso modo in cui ? possibile farlo con le azioni predefinite.
+Vedere la sezione
+.Sx SCORCIATOIE
+pi? sotto.
+.Pp
+I programmi di default sono descritte qui sotto:
+.Pp
+.Bl -tag -width "screenshot_wind" -offset indent -compact
+.It Cm term
+xterm
+.It Cm screenshot_all
+screenshot.sh full
+.It Cm screenshot_wind
+screenshot.sh window
+.It Cm lock
+xlock
+.It Cm initscr
+initscreen.sh
+.It Cm menu
+dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
+.El
+.Pp
+I programmi personalizzati vengono specificati con la seguente sintassi:
+.Pp
+.Dl program[<nome>] = <percorso> [<arg> [... <arg>]]
+.Pp
+.Aq nome
+? un qualsiasi identificatore che non va in conflitto con un'azione
+predefinita o una chiave,
+.Aq percorso
+? il programma desiderato, e
+.Aq arg
+sono zero o pi? argomenti da passare al programma.
+.Pp
+Le seguenti variabili rappresentano valori impostabili in
+.Nm
+(vedere la sezione
+.Sx FILE DI CONFIGURAZIONE
+sopra), e possono essere usati nel campo
+.Aq arg
+dove saranno sostituite con il valore al momento del lancio del programma:
+.Pp
+.Bl -tag -width "$bar_font_color" -offset indent -compact
+.It Cm $bar_border
+.It Cm $bar_color
+.It Cm $bar_font
+.It Cm $bar_font_color
+.It Cm $color_focus
+.It Cm $color_unfocus
+.El
+.Pp
+Esempio:
+.Bd -literal -offset indent
+program[ff] = /usr/local/bin/firefox http://spectrwm.org/
+bind[ff] = Mod+f # adesso Mod+F lancia firefox
+.Ed
+.Pp
+Per eliminare la combinazione precedente:
+.Bd -literal -offset indent
+bind[] = Mod+f
+program[ff] =
+.Ed
+.Pp
+.Sh SCORCIATOIE
+.Nm
+fornisce molte funzioni (o azioni) accessibili tramite combinazioni di
+tasti sul mouse o sulla tastiera.
+.Pp
+Le scorciatoie assegnate al mouse sono:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M1
+D? focus alla finestra
+.It Cm M-M1
+Muove la finestra
+.It Cm M-M3
+Ridimensiona la finestra
+.It Cm M-S-M3
+Ridimensiona la finestra mantenendola centrata
+.El
+.Pp
+Le scorciatoie da tastiera di default sono:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M-S- Ns Aq Cm Return
+term
+.It Cm M-p
+menu
+.It Cm M-S-q
+quit
+.It Cm M-q
+restart
+.It Cm M- Ns Aq Cm Space
+cycle_layout
+.It Cm M-S- Ns Aq Cm Space
+reset_layout
+.It Cm M-h
+master_shrink
+.It Cm M-l
+master_grow
+.It Cm M-,
+master_add
+.It Cm M-.
+master_del
+.It Cm M-S-,
+stack_inc
+.It Cm M-S-.
+stack_del
+.It Cm M- Ns Aq Cm Return
+swap_main
+.It Xo
+.Cm M-j ,
+.Cm M- Ns Aq Cm TAB
+.Xc
+focus_next
+.It Xo
+.Cm M-k ,
+.Cm M-S- Ns Aq Cm TAB
+.Xc
+focus_prev
+.It Cm M-m
+focus_main
+.It Cm M-S-j
+swap_next
+.It Cm M-S-k
+swap_prev
+.It Cm M-b
+bar_toggle
+.It Cm M-x
+wind_del
+.It Cm M-S-x
+wind_kill
+.It Cm M- Ns Aq Ar n
+.Ns ws_ Ns Ar n
+.It Cm M-S- Ns Aq Ar n
+.Ns mvws_ Ns Ar n
+.It Cm M- Ns Aq Cm Right
+ws_next
+.It Cm M- Ns Aq Cm Left
+ws_prev
+.It Cm M-a
+ws_prior
+.It Cm M-S- Ns Aq Cm Right
+screen_next
+.It Cm M-S- Ns Aq Cm Left
+screen_prev
+.It Cm M-s
+screenshot_all
+.It Cm M-S-s
+screenshot_wind
+.It Cm M-S-v
+version
+.It Cm M-t
+float_toggle
+.It Cm M-S Aq Cm Delete
+lock
+.It Cm M-S-i
+initscr
+.It Cm M-w
+iconify
+.It Cm M-S-w
+uniconify
+.It Cm M-S-r
+always_raise
+.It Cm M-v
+button2
+.El
+.Pp
+I nomi delle azioni e le relative descrizioni sono le seguenti:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm term
+Lancia un nuovo terminale
+(vedi
+.Sx PROGRAMMI
+pi? in alto).
+.It Cm menu
+Menu
+(vedi
+.Sx PROGRAMMI
+pi? in alto).
+.It Cm quit
+Chiude
+.Nm .
+.It Cm restart
+Riavvia
+.Nm .
+.It Cm cycle_layout
+Cambia layout.
+.It Cm reset_layout
+Re-inizializza il layout.
+.It Cm master_shrink
+Restringe l'area principale.
+.It Cm master_grow
+Allarga l'area principale.
+.It Cm master_add
+Aggiunge finestre all'area principale.
+.It Cm master_del
+Rimuove finestre dall'area principale.
+.It Cm stack_inc
+Aggiunge righe/colonne all'area di stacking.
+.It Cm stack_del
+Rimuove righe/colonne dall'area di stacking.
+.It Cm swap_main
+Muove la finestra corrente nell'area principale.
+.It Cm focus_next
+D? il focus alla finestra successiva.
+.It Cm focus_prev
+D? il focus alla finestra precedente.
+.It Cm focus_main
+D? il focus alla finestra principale.
+.It Cm swap_next
+Scambia con la finestra successiva dell'area di lavoro.
+.It Cm swap_prev
+Scambia con la finestra precedente dell'area di lavoro.
+.It Cm bar_toggle
+Mostra/nascondi la barra di stato da tutte le aree di lavoro.
+.It Cm wind_del
+Chiude la finestra corrente.
+.It Cm wind_kill
+Distrugge la finestra corrente.
+.It Cm ws_ Ns Ar n
+Passa all'area di lavoro
+.Ar n ,
+dove
+.Ar n
+? compreso tra 1 e 10.
+.It Cm mvws_ Ns Ar n
+Sposta la finestra corrente nell'area di lavoro
+.Ar n ,
+dove
+.Ar n
+? compreso tra 1 e 10.
+.It Cm ws_next
+Passa all'area di lavoro non vuota successiva.
+.It Cm ws_prev
+Passa all'area di lavoro non vuota precedente.
+.It Cm ws_prior
+Passa all'ultima area di lavoro visitata.
+.It Cm screen_next
+Sposta il puntatore nella regione successiva.
+.It Cm screen_prev
+Sposta il puntatore nella regione precedente.
+.It Cm screenshot_all
+Cattura uno screenshot dell'intero schermo, se abilitato (vedere la sezione
+.Sx PROGRAMMI
+pi? in alto).
+.It Cm screenshot_wind
+Cattura uno screenshot di una singola finestra, se abilitato (vedere la
+sezione
+.Sx PROGRAMMI
+pi? in alto).
+.It Cm version
+Abilita/disabilita il numero di versione nella barra di stato.
+.It Cm float_toggle
+Passa la finestra che ha il focus da floating a tiled.
+.It Cm lock
+Blocca lo schermo (vedere la sezione
+.Sx PROGRAMMI
+pi? in alto).
+.It Cm initscr
+Re-inizializza gli schermi fisici (vedere la sezione
+.Sx PROGRAMMI
+pi? in alto).
+.It Cm iconify
+Minimizza (unmap) la finesta che ha il focus.
+.It Cm uniconify
+Massimizza (map) la finestra selezionata tramite dmenu.
+.It Cm always_raise
+Quando ? abilitato, le finestre floating possono essere oscurate da
+finestre tiled.
+.It Cm button2
+Simula la pressione del tasto centrale del mouse.
+.El
+.Pp
+Le scorciatoie personalizzate sono specificate nel file di configurazione
+come segue:
+.Pp
+.Dl bind[<azione>] = <tasti>
+.Pp
+.Aq azione
+? una delle azioni elencate sopra (oppure nulla) e
+.Aq tasti
+? dato da zero o pi? modificatori (MOD, Mod1, Shift, ecc.) e uno o pi?
+tasti normali (b, space, ecc.), separati da "+".
+Per esempio:
+.Bd -literal -offset indent
+bind[reset] = Mod4+q # assegna reset ai tasti Windows + q
+bind[] = Mod1+q # rimuovi l'assegnazione di Alt + q
+.Ed
+.Pp
+Pi? combinazioni di tasti possono essere assegnate alla stessa azione.
+.Sh QUIRK
+.Nm
+fornisce la possibilit? di specificare dei "quirk" per la gestione di
+finestre che devono subire un trattamento speciale da un gestore di finestre
+tiling, come ad esempio alcune finestre di dialogo e applicazioni a
+schermo intero.
+.Pp
+I quirk abilitati di default sono elencati qui sotto:
+.Pp
+.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
+.It Firefox\-bin:firefox\-bin
+TRANSSZ
+.It Firefox:Dialog
+FLOAT
+.It Gimp:gimp
+FLOAT + ANYWHERE
+.It MPlayer:xv
+FLOAT + FULLSCREEN + FOCUSPREV
+.It OpenOffice.org 2.4:VCLSalFrame
+FLOAT
+.It OpenOffice.org 3.1:VCLSalFrame
+FLOAT
+.It pcb:pcb
+FLOAT
+.It xine:Xine Window
+FLOAT + ANYWHERE
+.It xine:xine Panel
+FLOAT + ANYWHERE
+.It xine:xine Video Fullscreen Window
+FULLSCREEN + FLOAT
+.It Xitk:Xitk Combo
+FLOAT + ANYWHERE
+.It Xitk:Xine Window
+FLOAT + ANYWHERE
+.It XTerm:xterm
+XTERM_FONTADJ
+.El
+.Pp
+I quirk sono descritti qui sotto:
+.Pp
+.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
+.It FLOAT
+Questa finestra deve essere lasciata libera di muoversi (float).
+.It TRANSSZ
+Aggiusta la dimensione delle finestre troppo piccole usando dialog_ratio
+(vedere
+.Sx FILE DI CONFIGURAZIONE ) .
+.It ANYWHERE
+Consente alla finestra di decidere da sola dove posizionarsi.
+.It XTERM_FONTADJ
+Ridimensiona il font di xterm quando viene ridimensionata la finestra.
+.It FULLSCREEN
+Rimuove i bordi, consentendo alla finestra di usare l'intera dimensione
+dello schermo.
+.It FOCUSPREV
+Quando la finestra viene chiusa, d? il focus alla finestra che aveva il
+focus precedente anzich? all'applicazione precedente nello stack.
+.El
+.Pp
+I quirk personalizzati vanno specificati nel file di configurazione come
+segue:
+.Pp
+.Dl quirk[<classe>:<nome>] = <quirk> [ + <quirk> ... ]
+.Pp
+.Aq classe
+e
+.Aq nome
+specificano a quali finestre i quirk vanno applicati, e
+.Aq quirk
+? uno dei quirk presente nella lista sopra.
+Ad esempio:
+.Bd -literal -offset indent
+quirk[MPlayer:xv] = FLOAT + FULLSCREEN + FOCUSPREV
+quirk[pcb:pcb] = NONE  # rimuovi un quirk precedentemente specificato
+.Ed
+.Pp
+? possibile ottenere
+.Aq classe
+e
+.Aq nome
+usando xprop(1) e facendo click sulla finestra desiderata.
+Nel seguente esempio ? stato fatto click sulla finestra principale di
+Firefox:
+.Bd -literal -offset indent
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "Navigator", "Firefox"
+.Ed
+.Pp
+Bisogna tenere conto del fatto che usare grep per trovare WM_CLASS inverte
+la classe e il nome. Nell'esempio precedente, la dichiarazione del quirk
+sarebbe
+.Bd -literal -offset indent
+quirk[Firefox:Navigator] = FLOAT
+.Ed
+.Pp
+.Nm
+assegna automaticamente i quirk alle finestre in base al valore della
+propriet? _NET_WM_WINDOW_TYPE in base al seguente schema:
+.Pp
+.Bl -tag -width "_NET_WM_WINDOW_TYPE_TOOLBAR<TAB>XXX" -offset indent -compact
+.It _NET_WM_WINDOW_TYPE_DOCK
+FLOAT + ANYWHERE
+.It _NET_WM_WINDOW_TYPE_TOOLBAR
+FLOAT + ANYWHERE
+.It _NET_WM_WINDOW_TYPE_UTILITY
+FLOAT + ANYWHERE
+.It _NET_WM_WINDOW_TYPE_SPLASH
+FLOAT
+.It _NET_WM_WINDOW_TYPE_DIALOG
+FLOAT
+.El
+.Pp
+In tutti gli altri casi, nessun quirk ? automaticamente assegnato alla
+finestra. I quirk specificati nel file di configurazione hanno la precedenza
+sui quirk assegnati in automatico.
+.Sh EWMH
+.Nm
+implementa in maniera parziale la specifica Extended Window Manager Hints
+(EWMH). Ci? permette di controllare sia le finestre che
+.Nm
+stesso tramite script e programmi esterni. Per renderlo possibile,
+.Nm
+risponde ad alcuni eventi di tipo ClientMessage; questo tipo di messaggio
+pu? essere inviato da un terminale usando programmi come
+.Xr wmctrl 1
+e
+.Xr xdotool 1 .
+Per il formato esatto di questi messaggi, si veda la specifica EWMH.
+.Pp
+L'id della finestra che ha il focus ? memorizzato nella propriet?
+_NET_ACTIVE_WINDOW della root window. ? quindi possibile ottenere il titolo
+della finestra attiva usando
+.Xr xprop 1
+e
+.Xr grep 1
+.Bd -literal -offset indent
+$ WINDOWID=`xprop \-root _NET_ACTIVE_WINDOW | grep \-o "0x.*"`
+$ xprop \-id $WINDOWID WM_NAME | grep \-o "\\".*\\""
+.Ed
+.Pp
+Per dare il focus ad una finestra, ? sufficiente inviare il messaggio
+_NET_ACTIVE_WINDOW alla root window. Ad esempio, usando
+.Xr wmctrl 1
+(supponendo che 0x4a0000b sia l'id della finestra a cui dare il focus):
+.Bd -literal -offset indent
+$ wmctrl \-i \-c 0x4a0000b
+.Ed
+.Pp
+Per chiudere una finestra si pu? inviare il messaggio _NET_CLOSE_WINDOW
+alla root window. Ad esempio, usando
+.Xr wmctrl 1
+(supponendo che 0x4a0000b sia l'id della finestra da chiudere):
+.Bd -literal -offset indent
+$ wmctrl \-i \-c 0x4a0000b
+.Ed
+.Pp
+Per passare una finestra da floating a tiled si pu? aggiungere o rimuovere
+l'atomo _NET_WM_STATE_ABOVE alla propriet? _NET_WM_STATE della finestra,
+inviando il messaggio _NET_WM_STATE alla root window. Ad esempio, usando
+.Xr wmctrl 1
+(supponendo che 0x4a0000b sia l'id della finestra):
+.Bd -literal -offset indent
+$ wmctrl \-i \-r 0x4a0000b \-b toggle,_NET_WM_STATE_ABOVE
+.Ed
+.Pp
+Le finestre floating possono essere ridimensionate o spostate inviando il
+messaggio _NET_MOVERESIZE_WINDOW alla root window. Ad esempio, usando
+.Xr wmctrl 1
+(supponendo che 0x4a0000b sia l'id della finestra da spostare):
+.Bd -literal -offset indent
+$ wmctrl \-i \-r 0x4a0000b \-e 0,100,50,640,480
+.Ed
+.Pp
+Questo comando sposta la finestra in (100,50) e la ridimensiona a 640x480.
+.Pp
+I messaggi _NET_MOVERESIZE_WINDOW vengono ignorati per le finestre stacked.
+.Sh SEGNALI
+? possibile riavviare
+.Nm
+inviandogli il segnale HUP.
+.Sh FILE
+.Bl -tag -width "/etc/spectrwm.confXXX" -compact
+.It Pa ~/.spectrwm.conf
+impostazioni di
+.Nm
+dell'utente.
+.It Pa /etc/spectrwm.conf
+impostazioni globali di
+.Nm .
+.El
+.Sh ORIGINE
+.Nm
+prende ispirazione da xmonad & dwm.
+.Sh AUTORI
+.An -nosplit
+.Pp
+.Nm
+? stato scritto da:
+.Pp
+.Bl -tag -width "Ryan Thomas McBride Aq mcbride@countersiege.com " -offset indent -compact
+.It Cm Marco Peereboom Aq marco@peereboom.us
+.It Cm Ryan Thomas McBride Aq mcbride@countersiege.com
+.It Cm Darrin Chandler Aq dwchandler@stilyagin.com
+.It Cm Pierre-Yves Ritschard Aq pyr@spootnik.org
+.It Cm Tuukka Kataja Aq stuge@xor.fi
+.It Cm Jason L. Wright Aq jason@thought.net
+.El
+.Sh BUGS
+Al momento il menu, invocato usando
+.Cm M-p ,
+dipende da dmenu.
diff --git a/spectrwm_pt.1 b/spectrwm_pt.1
new file mode 100644 (file)
index 0000000..3249901
--- /dev/null
@@ -0,0 +1,584 @@
+.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate$
+.Dt SPECTRWM 1
+.Os
+.Sh NOME
+.Nm spectrwm
+.Nd gerenciador de janela para o X11
+.Sh SINOPSE
+.Nm spectrwm
+.Sh DESCRI\(,C\(~AO
+.Nm
+\('e um gerenciador de janela minimalista que tenta n\(~ao atrapalhar a
+valorosa forma real da tela para que essa possa
+ser usada para coisas muito mais importantes.
+Tem sensatos defaults e n\(~ao requer que algu\('em aprenda uma linguagem de
+programa\(,c\(~ao para fazer qualquer configura\(,c\(~ao.
+Ele foi escrito por hackers para hackers e esfor\(,ca-se em ser pequeno, compacto e 
+r\('apido.
+.Pp
+Quando o
+.Nm
+inicia, ele l\(^e as configura\(,c\(~oes do seu arquivo de configura\(,c\(~ao,
+.Pa spectrwm.conf .
+Veja a se\(,c\(~ao
+.Sx ARQUIVOS DE CONFIGURA\(,C\(~AO
+logo abaixo.
+.Pp
+A seguinte nota\(,c\(~ao \('e usada por toda essa p\('agina:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Cm M
+Meta
+.It Cm S
+Shift
+.It Aq Cm Name
+Nome da tecla
+.It Cm M1
+Bot\(~ao 1 do mouse
+.It Cm M3
+Bot\(~ao 3 do mouse
+.El
+.Pp
+.Nm
+\('e muito simples de usar.
+Muitas das a\(,c\(~oes s\(~ao iniciadas por atalhos do mouse ou do teclado.
+Veja a se\(,c\(~ao
+.Sx ATALHOS
+logo abaixo para os defaults e as personaliza\(,c\(~oes.
+.Sh ARQUIVOS DE CONFIGURA\(,C\(~AO
+.Nm
+primeiro tenta abrir o arquivo de configura\(,c\(~ao no diret\('orio do usu\('ario,
+.Pa ~/.spectrwm.conf .
+Se o arquivo n\(~ao estiver dispon\('ivel, ent\(~ao tenta abrir o arquivo de
+configura\(,c\(~ao global
+.Pa /etc/spectrwm.conf .
+.Pp
+Assim \('e o formato do arquivo:\*(Ltpalavra-chave\*(Gt = \*(Ltconfigura\(,c\(~ao\*(Gt.
+Por exemplo:
+.Pp
+.Dl color_focus = red
+.Pp
+Para habilitar ou desabilitar uma op\(,c\(~ao usa-se o 1 ou 0, respectivamente. 
+.Pp
+O arquivo suporta as seguintes palavras-chave:
+.Pp
+.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
+.It Cm color_focus
+Cor da borda da janela atualmente focada.
+.It Cm color_unfocus
+Cor da borda das janelas fora de foco.
+.It Cm bar_enabled
+Habilita ou desabilita a barra de status.
+.It Cm bar_border Ns Bq Ar x
+Cor da borda da barra de status na tela
+.Ar x .
+.It Cm bar_color Ns Bq Ar x
+Cor da janela da barra de status na tela
+.Ar x .
+.It Cm bar_font_color Ns Bq Ar x
+Cor da fonte na barra de status na tela
+.Ar x .
+.It Cm bar_font
+Fonte da barra de status.
+.It Cm bar_action
+Script externo que preenche a barra de status com informa\(,c\(~oes adicionais,
+como tempo de vida da bateria.
+.It Cm bar_delay
+Freq\(:u\(^encia da atualiza\(,c\(~ao, em segundos, do script externo que preenche
+a barra de status.
+.It Cm bar_at_bottom
+Coloca a barra de status na parte inferior de cada regi\(~ao, ao inv\('es da parte superior.
+.It Cm stack_enabled
+Habilita ou desabilita mostrar o atual algor\('itmo de empilhamento na barra de status.
+.It Cm clock_enabled
+Habilita ou desabilita mostrar o rel\('ogio na barra de status.
+Desabilite configurando para 0, ent\(~ao um rel\('ogio personalizado pode ser usado no
+script bar_action.
+.It Cm dialog_ratio
+Algumas aplica\(,c\(~oes tem janelas de di\('alogo que s\(~ao muito pequenas para serem \('uteis.
+Essa taxa \('e o tamanho da tela para o qual elas ser\(~ao redimencionadas.
+Por exemplo, 0.6 equivale a 60% do tamanho da tela f\('isica.
+.It Cm region
+Aloca uma regi\(~ao personalizada, removendo qualquer regi\(~ao automaticamente detectada
+que ocupe o mesmo espa\(,co na tela.
+Definido no formato screen[<idx>]:WIDTHxHEIGHT+X+Y,
+e.g.\& screen[1]:800x1200+0+0.
+.It Cm term_width
+Configura a largura m\('inima preferida para o terminal
+Se esse valor for maior do que 0,
+.Nm
+vai tentar ajustar os tamanhos da fonte no terminal para manter a largura
+do terminal acima desse n\('umero enquanto a janela \('e redimencionada.
+Apenas o
+.Xr xterm 1
+\('e suportado atualmente.
+O bin\('ario do
+.Xr xterm 1
+n\(~ao deve ser setuid ou setgid, que \('e o default em muitos sistemas.
+Os usu\('arios podem precisar de configurar program[term] (veja a se\(,c\(~ao
+.Sx PROGRAMAS
+) para usar uma c\('opia alternativa do bin\('ario do
+.Xr xterm 1
+sem o bit setgid ativado.
+.It Cm title_class_enabled
+Habilita ou desabilita mostrar a classe da janela na barra de status.
+Habilite configurando para 1.
+.It Cm title_name_enabled
+Habilita ou desabilita mostrar o t\('itulo da janela na barra de status.
+Habilite configurando para 1.
+.It Cm window_name_enabled
+Habilita ou desabilita mostrar a nome da janela na barra de status.
+Habilite configurando para 1.
+.It Cm modkey
+Muda a tecla de modifica\(,c\(~ao.
+Mod1 \('e geralmente a tecla ALT e Mod4 \('e a tecla windows em um PC.
+.It Cm focus_mode
+Usar um valor de follow_cursor vai fazer o gerenciador de janela focar
+a janela sob o mouse quando trocando \('areas de trabalho e criando janelas.
+.It Cm disable_border
+Remove a borda quando a barra estiver desabilitada e houver apenas uma janela na tela.
+.It Cm program Ns Bq Ar p
+Define uma nova a\(,c\(~ao para executar um programa
+.Ar p .
+Veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo abaixo.
+.It Cm bind Ns Bq Ar x
+Cria uma combina\(,c\(~ao de teclas de atalho para a a\(,c\(~ao
+.Ar x .
+Veja a se\(,c\(~ao 
+.Sx ATALHOS
+logo abaixo.
+.It Cm quirk Ns Bq Ar c:n
+Adicione "quirk" para janelas com classe
+.Ar c
+e nome
+.Ar n .
+Veja a se\(,c\(~ao
+.Sx QUIRKS
+logo abaixo.
+.El
+.Pp
+Cores precisam ser especificadas pela especifica\(,c\(~ao
+.Xr XQueryColor 3
+e fontes pela especifica\(,c\(~ao
+.Xr XQueryFont 3 .
+.Pp
+Para listar as fontes dispon\('iveis em seu sistema veja o manual do
+.Xr fc-list 1
+ou do
+.Xr xlsfonts 1 .
+A aplica\(,c\(~ao 
+.Xr xfontsel 1
+pode te ajudar a mostrar a X Logical Font Description ("XLFD") usada na
+configura\(,c\(~ao da palavra-chave bar_font.
+.Sh PROGRAMAS
+.Nm
+te permite definir a\(,c\(~oes personalizadas para executar programas de sua escolha
+e ent\(~ao criar um atalho para elas da mesma forma que as a\(,c\(~oes embutidas.
+Veja a se\(,c\(~ao
+.Sx ATALHOS
+logo abaixo.
+.Pp
+Os programas default s\(~ao descritos abaixo:
+.Pp
+.Bl -tag -width "screenshot_wind" -offset indent -compact
+.It Cm term
+xterm
+.It Cm screenshot_all
+screenshot.sh full
+.It Cm screenshot_wind
+screenshot.sh window
+.It Cm lock
+xlock
+.It Cm initscr
+initscreen.sh
+.It Cm menu
+dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
+.El
+.Pp
+Programas personalizados no arquivo de configura\(,c\(~ao s\(~ao especificados da seguinte maneira:
+.Pp
+.Dl program[<name>] = <progpath> [<arg> [... <arg>]]
+.Pp
+.Aq name
+\('e um identificador qualquer que n\(~ao conflite com uma a\(,c\(~ao ou palavra-chave embutida,
+.Aq progpath
+\('e o programa desejado, e
+.Aq arg
+\('e zero ou mais argumentos para o programa.
+.Pp
+As seguintes vari\('aveis representam valores configur\('aveis no
+.Nm
+(veja a se\(,c\(~ao
+.Sx ARQUIVOS DE CONFIGURA\(,C\(~AO
+logo acima),
+e podem ser usadas nos campos
+.Aq arg
+e ser\(~ao substitu\('idas pelos valores na hora em que o programa for executado:
+.Pp
+.Bl -tag -width "$bar_font_color" -offset indent -compact
+.It Cm $bar_border
+.It Cm $bar_color
+.It Cm $bar_font
+.It Cm $bar_font_color
+.It Cm $color_focus
+.It Cm $color_unfocus
+.El
+.Pp
+Exemplo:
+.Bd -literal -offset indent
+program[ff] = /usr/local/bin/firefox http://spectrwm.org/
+bind[ff] = Mod+f # Agora Mod+F executa o firefox
+.Ed
+.Pp
+Para desfazer a configura\(,c\(~ao anterior:
+.Bd -literal -offset indent
+bind[] = Mod+f
+program[ff] =
+.Ed
+.Pp
+.Sh ATALHOS
+.Nm
+prov\(^e muitas fun\(,c\(~oes (ou a\(,cões) acessadas pelos atalhos do teclado ou do mouse.
+.Pp
+Os atuais atalhos do mouse s\(~ao descritos abaixo:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M1
+Foca a janela
+.It Cm M-M1
+Move a janela
+.It Cm M-M3
+Redimenciona a janela
+.It Cm M-S-M3
+Redimenciona a janela enquanto a mant\('em centralizada
+.El
+.Pp
+Os atalhos default do teclado s\(~ao descritos abaixo:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M-S- Ns Aq Cm Return
+term
+.It Cm M-p
+menu
+.It Cm M-S-q
+quit
+.It Cm M-q
+restart
+.Nm
+.It Cm M- Ns Aq Cm Space
+cycle_layout
+.It Cm M-S- Ns Aq Cm Space
+reset_layout
+.It Cm M-h
+master_shrink
+.It Cm M-l
+master_grow
+.It Cm M-,
+master_add
+.It Cm M-.
+master_del
+.It Cm M-S-,
+stack_inc
+.It Cm M-S-.
+stack_del
+.It Cm M- Ns Aq Cm Return
+swap_main
+.It Xo
+.Cm M-j ,
+.Cm M- Ns Aq Cm TAB
+.Xc
+focus_next
+.It Xo
+.Cm M-k ,
+.Cm M-S- Ns Aq Cm TAB
+.Xc
+focus_prev
+.It Cm M-m
+focus_main
+.It Cm M-S-j
+swap_next
+.It Cm M-S-k
+swap_prev
+.It Cm M-b
+bar_toggle
+.It Cm M-x
+wind_del
+.It Cm M-S-x
+wind_kill
+.It Cm M- Ns Aq Ar n
+.Ns ws_ Ns Ar n
+.It Cm M-S- Ns Aq Ar n
+.Ns mvws_ Ns Ar n
+.It Cm M- Ns Aq Cm Right
+ws_next
+.It Cm M- Ns Aq Cm Left
+ws_prev
+.It Cm M-a
+ws_prior
+.It Cm M-S- Ns Aq Cm Right
+screen_next
+.It Cm M-S- Ns Aq Cm Left
+screen_prev
+.It Cm M-s
+screenshot_all
+.It Cm M-S-s
+screenshot_wind
+.It Cm M-S-v
+version
+.It Cm M-t
+float_toggle
+.It Cm M-S Aq Cm Delete
+lock
+.It Cm M-S-i
+initscr
+.El
+.Pp
+Os nomes das a\(,c\(~oes e suas descri\(,cões est\(~ao listados abaixo:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm term
+Executa um novo terminal
+(veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo acima)
+.It Cm menu
+Menu
+(veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo acima)
+.It Cm quit
+Sair
+.Nm
+.It Cm restart
+Reiniciar
+.Nm
+.It Cm cycle_layout
+Circula entre os poss\('iveis layouts
+.It Cm reset_layout
+Reinicia o layout
+.It Cm master_shrink
+Encolhe a \('area mestre
+.It Cm master_grow
+Aumenta a \('area mestre
+.It Cm master_add
+Adiciona janelas na \('area mestre
+.It Cm master_del
+Remove janelas da \('area mestre
+.It Cm stack_inc
+Adiciona colunas/linhas para a \('area de empilhamento
+.It Cm stack_del
+Remove colunas/linhas da \('area de empilhamento
+.It Cm swap_main
+Move a janela atual para a \('area mestre
+.It Cm focus_next
+Foca a pr\('oxima janela da \('area de trabalho
+.It Cm focus_prev
+Foca a janela anterior da \('area de trabalho
+.It Cm focus_main
+Foca a janela principal da \('area de trabalho
+.It Cm swap_next
+Troca com a pr\('oxima janela da \('area de trabalho
+.It Cm swap_prev
+Troca com a janela anterior da \('area de trabalho
+.It Cm bar_toggle
+Ativa/desativa a barra de status em todas as \('areas de trabalho
+.It Cm wind_del
+Apaga a janela atual da \('area de trabalho
+.It Cm wind_kill
+Destr\('oi a janela atual da \('area de trabalho
+.It Cm ws_ Ns Ar n
+Troca para a \('area de trabalho
+.Ar n ,
+onde
+.Ar n
+vai de 1 at\('e 10
+.It Cm mvws_ Ns Ar n
+Move a janela atual para a \('area de trabalho
+.Ar n ,
+onde
+.Ar n
+vai de 1 at\('e 10
+.It Cm ws_next
+Troca para a pr\('oxima \('area de trabalho que possua uma janela
+.It Cm ws_prev
+Troca para a \('area de trabalho anterior que possua uma janela
+.It Cm ws_prior
+Troca para a \('ultima \('area de trabalho visitada
+.It Cm screen_next
+Move o ponteiro para a pr\('oxima regi\(~ao
+.It Cm screen_prev
+Move o ponteiro para a regi\(~ao anterior
+.It Cm screenshot_all
+Tira screenshot da tela inteira (se habilitado)
+(veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo acima)
+.It Cm screenshot_wind
+Tira screenshot da janela selecionada (se habilitado)
+(veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo acima)
+.It Cm version
+Ativa/desativa a vers\(~ao na barras de status
+.It Cm float_toggle
+Troca o estado da janela focada entre flutuante e tiled
+.It Cm lock
+Trava a tela
+(veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo acima)
+.It Cm initscr
+Reinicializa as telas f\('isicas
+(veja a se\(,c\(~ao
+.Sx PROGRAMAS
+logo acima)
+.El
+.Pp
+Atalhos personalizados no arquivo de configura\(,c\(~ao s\(~ao especificados da seguinte maneira:
+.Pp
+.Dl bind[<action>] = <keys>
+.Pp
+.Aq action
+\('e uma das a\(,c\(~oes listadas acima (ou vazio) e
+.Aq keys
+est\('a na forma de zero ou mais teclas de modifica\(,c\(~ao
+(MOD, Mod1, Shift, etc.) e uma ou mais teclas normais
+(b, space, etc.), separadas pelo "+".
+Por exemplo:
+.Bd -literal -offset indent
+bind[reset] = Mod4+q # combina a tecla Windows + q para reiniciar
+bind[] = Mod1+q # desfaz a combina\(,c\(~ao Alt + q
+.Ed
+.Pp
+M\('ultiplas combina\(,c\(~oes de teclas podem ser usadas para a mesma a\(,c\(~ao.
+.Sh QUIRKS
+.Nm
+prov\(^e "quirks" que manipulam janelas que devem ser tratadas especialmente
+em um gerenciador de janela "tiling", tal como algumas aplica\(,c\(~oes de
+di\('alogos e tela cheia.
+.Pp
+Os quirks default est\(~ao descritos abaixo:
+.Pp
+.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
+.It Firefox\-bin:firefox\-bin
+TRANSSZ
+.It Firefox:Dialog
+FLOAT
+.It Gimp:gimp
+FLOAT + ANYWHERE
+.It MPlayer:xv
+FLOAT + FULLSCREEN
+.It OpenOffice.org 2.4:VCLSalFrame
+FLOAT
+.It OpenOffice.org 3.1:VCLSalFrame
+FLOAT
+.It pcb:pcb
+FLOAT
+.It xine:Xine Window
+FLOAT + ANYWHERE
+.It xine:xine Panel
+FLOAT + ANYWHERE
+.It xine:xine Video Fullscreen Window
+FULLSCREEN + FLOAT
+.It Xitk:Xitk Combo
+FLOAT + ANYWHERE
+.It Xitk:Xine Window
+FLOAT + ANYWHERE
+.It XTerm:xterm
+XTERM_FONTADJ
+.El
+.Pp
+Os quirks em si est\(~ao descritos abaixo:
+.Pp
+.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
+.It FLOAT
+Esta janela n\(~ao deve ser "tiled", mas permitida a flutuar livremente.
+.It TRANSSZ
+Ajusta o tamanho das janelas transit\('orias que sejam muito pequenas
+usando dialog_ratio 
+(veja a se\(,c\(~ao
+.Sx ARQUIVOS DE CONFIGURA\(,C\(~AO ) .
+.It ANYWHERE
+Permite que a janela posicione a si mesma, n\(~ao-centrada.
+.It XTERM_FONTADJ
+Ajusta as fontes do xterm quando redimencionando.
+.It FULLSCREEN
+Remove a borda para permitir a janela usar todo o tamanho da tela.
+.El
+.Pp
+Quirks personalizados no arquivo de configura\(,c\(~ao s\(~ao especificados da seguinte maneira:
+.Pp
+.Dl quirk[<class>:<name>] = <quirk> [ + <quirk> ... ]
+.Pp
+.Aq class
+e
+.Aq name
+especificam a janela ao qual o quirk se aplica, e
+.Aq quirk
+\('e um dos quirks da lista acima.
+Por exemplo:
+.Bd -literal -offset indent
+quirk[MPlayer:xv] = FLOAT + FULLSCREEN # faz o mplayer tocar livremente
+quirk[pcb:pcb] = NONE  # remove quirk existente
+.Ed
+.Pp
+Voc\(^e pode obter
+.Aq class
+e
+.Aq name
+executando o xprop(1) e ent\(~ao clicando na janela desejada.
+No seguinte exemplo a jenela principal do Firefox foi clicada:
+.Bd -literal -offset indent
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "Navigator", "Firefox"
+.Ed
+.Pp
+Note que usando o grep(1) para WM_CLASS voc\(^e obt\('em class e name. 
+No exemplo acima a configura\(,c\(~ao do quirk poderia ser:
+.Bd -literal -offset indent
+quirk[Firefox:Navigator] = FLOAT
+.Ed
+.Sh SINAIS
+Enviar ao
+.Nm
+um sinal HUP far\('a com que o mesmo seja reiniciado.
+.Sh ARQUIVOS
+.Bl -tag -width "/etc/spectrwm.confXXX" -compact
+.It Pa ~/.spectrwm.conf
+Configura\(,c\(~oes espec\('ificas do usu\('ario.
+.It Pa /etc/spectrwm.conf
+Configura\(,c\(~oes globais.
+.El
+.Sh HIST\('ORIA
+.Nm
+foi inspirado pelo xmonad & dwm.
+.Sh AUTORES
+.An -nosplit
+.Pp
+.Nm
+foi escrito por
+.An Marco Peereboom Aq marco@peereboom.us ,
+.An Ryan Thomas McBride Aq mcbride@countersiege.com
+e
+.An Darrin Chandler Aq dwchandler@stilyagin.com .
+.Sh BUGS
+Atualmente o menu, invocado com
+.Cm M-p ,
+depende do dmenu.
diff --git a/spectrwm_ru.1 b/spectrwm_ru.1
new file mode 100644 (file)
index 0000000..c65a21b
--- /dev/null
@@ -0,0 +1,557 @@
+.\" Copyright (c) 2009 Marco Peereboom <marco@peereboom.us>
+.\" Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate$
+.Dt SPECTRWM 1
+.Os
+.Sh НАЗВАНИЕ
+.Nm spectrwm
+.Nd Оконный менеджер для X11
+.Sh ИСПОЛЬЗОВАНИЕ
+.Nm spectrwm
+.Sh ОПИСАНИЕ
+.Nm
+это минималистичный менеджер окон, ставящий своей целью не мешать вам и не
+занимать ценное пространство экрана. Его настройки по-умолчанию разумны и,
+кроме того, он не требует знания языков программирования для работы с
+конфигурационным файлом. Он написан хакерами для хакеров и старается быть
+легким, компактным и быстрым.
+.Pp
+Когда
+.Nm
+запускается, он читает настройки из своего конфигурационного файла,
+.Pa spectrwm.conf .
+Смотрите секцию
+.Sx КОНФИГУРАЦИОННЫЕ ФАЙЛЫ
+ниже.
+.Pp
+На этой странице используются следующие обозначения:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Cm M
+Мета-клавиша
+.It Cm S
+Shift
+.It Aq Cm Name
+Имя клавиши
+.It Cm M1
+Кнопка мыши 1
+.It Cm M3
+Кнопка мыши 3
+.El
+.Pp
+.Nm
+должен быть понятным и очевидным.
+Большинство действий выполняется комбинациями клавиш.
+Смотрите секцию
+.Sx ПРИВЯЗКИ
+ниже, чтобы узнать о стандартных настройках.
+.Sh КОНФИГУРАЦИОННЫЕ ФАЙЛЫ
+.Nm
+пытается прочитать файл в домашнем каталоге,
+.Pa ~/.spectrwm.conf .
+В случае, если он недоступен,
+происходит обращение к глобальному файлу настроек,
+.Pa /etc/spectrwm.conf .
+.Pp
+Формат файла следующий: \*(Ltключ\*(Gt = \*(Ltзначение\*(Gt.
+Например:
+.Pp
+.Dl color_focus = red
+.Pp
+Однозначное включение и выключение задается значениями 1 и 0.
+.Pp
+Поддерживаются следующие ключевые слова:
+.Pp
+.Bl -tag -width "title_class_enabledXXX" -offset indent -compact
+.It Cm color_focus
+Цвет рамки окна в фокусе.
+.It Cm color_unfocus
+Цвет рамки окон не в фокусе.
+.It Cm bar_enabled
+Включение статусной строки.
+.It Cm bar_border Ns Bq Ar x
+Цвет рамки статусной строки
+.Ar x .
+.It Cm bar_color Ns Bq Ar x
+Цвет статусной строки
+.Ar x .
+.It Cm bar_font_color Ns Bq Ar x
+Цвет шрифта статусной строки
+.Ar x .
+.It Cm bar_font
+Тип шрифта статусной строки.
+.It Cm bar_action
+Внешний файл скрипта для статусной строки, выводящий туда информацию,
+например, уровень заряда батарей.
+.It Cm bar_delay
+Частота выполнения внешнего скрипта статусной строки, секунды.
+.It Cm stack_enabled
+Включить отображение способа укладки окон в статусной строке.
+.It Cm clock_enabled
+Включить часы в статусной строке.
+Можно отключить, установив 0, и Вы сможете использовать
+собственные часы из внешнего скрипта.
+.It Cm dialog_ratio
+Ряд приложений имеет слишком маленькие диалоговые окна.
+Это значение - доля размера экрана, к которой они будут приведены.
+Например, значение 0.6 будет соответствовать 60% от реального размера экрана.
+.It Cm region
+Выделяет область экрана на Ваше усмотрение, уничтожает все перекрытые области
+экрана, определенные автоматически.
+Формат: screen[<idx>]:WIDTHxHEIGHT+X+Y,
+например\& screen[1]:1280x800+0+0.
+.It Cm term_width
+Установить минимальную допустимую ширину эмулятора терминала.
+Если это значение больше 0,
+.Nm
+попытается отмасштабировать шрифты в терминале, чтобы ширина
+была больше этого значения
+.
+Поодерживается только
+.Xr xterm 1
+.
+Также
+.Xr xterm 1
+не может быть с setuid или setgid, хотя это так на многих системах.
+Возможно необходимо задать program[term] (Смотрите секцию
+.Sx ПРОГРАММЫ
+) чтобы использовалась другая копия
+.Xr xterm 1
+без заданного бита setgid.
+.It Cm title_class_enabled
+Отображать класс окна в статусной строке.
+Обычно выключено
+.It Cm title_name_enabled
+Отображать заголовок окна в статусной строке.
+Обычно выключено
+.It Cm modkey
+Назначить Мета-клавишу, клавишу-модификатор.
+Mod1 соответствует клавише ALT, а Mod4 соответствует клавише WIN на PC.
+.It Cm program Ns Bq Ar p
+Добавить пользовательскую программу для назначения привязки
+.Ar p .
+Смотрите секцию
+.Sx ПРОГРАММЫ
+ниже.
+.It Cm bind Ns Bq Ar x
+Назначить привязку на действие
+.Ar x .
+Смотрите секцию
+.Sx ПРИВЯЗКИ
+ниже.
+.It Cm quirk Ns Bq Ar c:n
+Добавить костыль для окон с классом
+.Ar c
+и именем
+.Ar n .
+Смотрите секцию
+.Sx КОСТЫЛИ
+ниже.
+.El
+.Pp
+Цвета задаются с помощью
+.Xr XQueryColor 3
+А шрифты задаются с использованием
+.Xr XQueryFont 3
+.
+.Sh ПРОГРАММЫ
+.Nm
+позволяет Вам добавлять Ваши собственные действия для запуска
+программ и делать к ним привязки как ко всем остальным действиям
+Смотрите секцию
+.Sx ПРИВЯЗКИ
+ниже.
+.Pp
+Стандартные программы:
+.Pp
+.Bl -tag -width "screenshot_wind" -offset indent -compact
+.It Cm term
+xterm
+.It Cm screenshot_all
+screenshot.sh full
+.It Cm screenshot_wind
+screenshot.sh window
+.It Cm lock
+xlock
+.It Cm initscr
+initscreen.sh
+.It Cm menu
+dmenu_run \-fn $bar_font \-nb $bar_color \-nf $bar_font_color \-sb $bar_border \-sf $bar_color
+.El
+.Pp
+Ваши собственные программы задаются следующим образом:
+.Pp
+.Dl program[<name>] = <progpath> [<arg> [... <arg>]]
+.Pp
+.Aq name
+это любой идентификатор, не мешающийся с уже существующими,
+.Aq progpath
+это собственно путь к программе,
+.Aq arg
+это список передаваемых аргументов или оставьте пустым.
+.Pp
+Следующие переменные можно получать из
+.Nm
+(Смотрите секцию
+.Sx КОНФИГУРАЦИОННЫЕ ФАЙЛЫ
+выше),
+и их можно использовать как
+.Aq arg
+(в момент запуска программы будет выполнена подстановка значений):
+.Pp
+.Bl -tag -width "$bar_font_color" -offset indent -compact
+.It Cm $bar_border
+.It Cm $bar_color
+.It Cm $bar_font
+.It Cm $bar_font_color
+.It Cm $color_focus
+.It Cm $color_unfocus
+.El
+.Pp
+Например:
+.Bd -literal -offset indent
+program[ff] = /usr/local/bin/firefox http://spectrwm.org/
+bind[ff] = Mod+f # Значит Mod+F запускает firefox
+.Ed
+.Pp
+Чтобы отменить назначение:
+.Bd -literal -offset indent
+bind[] = Mod+f
+program[ff] =
+.Ed
+.Pp
+.Sh ПРИВЯЗКИ
+.Nm
+предоставляет доступ к действиям с помощью клавиатурных комбинаций.
+.Pp
+Установленные привязки для мыши:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M1
+Сфокусироваться на окне
+.It Cm M-M1
+Переместить окно
+.It Cm M-M3
+Изменить размер окна
+.It Cm M-S-M3
+Изменить размер окна, удерживая его в центре
+.El
+.Pp
+Стандартные клавиатурные привязки:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm M-S- Ns Aq Cm Return
+term
+.It Cm M-p
+menu
+.It Cm M-S-q
+quit
+.It Cm M-q
+restart
+.Nm
+.It Cm M- Ns Aq Cm Space
+cycle_layout
+.It Cm M-S- Ns Aq Cm Space
+reset_layout
+.It Cm M-h
+master_shrink
+.It Cm M-l
+master_grow
+.It Cm M-,
+master_add
+.It Cm M-.
+master_del
+.It Cm M-S-,
+stack_inc
+.It Cm M-S-.
+stack_del
+.It Cm M- Ns Aq Cm Return
+swap_main
+.It Xo
+.Cm M-j ,
+.Cm M- Ns Aq Cm TAB
+.Xc
+focus_next
+.It Xo
+.Cm M-k ,
+.Cm M-S- Ns Aq Cm TAB
+.Xc
+focus_prev
+.It Cm M-m
+focus_main
+.It Cm M-S-j
+swap_next
+.It Cm M-S-k
+swap_prev
+.It Cm M-b
+bar_toggle
+.It Cm M-x
+wind_del
+.It Cm M-S-x
+wind_kill
+.It Cm M- Ns Aq Ar n
+.Ns ws_ Ns Ar n
+.It Cm M-S- Ns Aq Ar n
+.Ns mvws_ Ns Ar n
+.It Cm M- Ns Aq Cm Right
+ws_next
+.It Cm M- Ns Aq Cm Left
+ws_prev
+.It Cm M-S- Ns Aq Cm Right
+screen_next
+.It Cm M-S- Ns Aq Cm Left
+screen_prev
+.It Cm M-s
+screenshot_all
+.It Cm M-S-s
+screenshot_wind
+.It Cm M-S-v
+version
+.It Cm M-t
+float_toggle
+.It Cm M-S Aq Cm Delete
+lock
+.It Cm M-S-i
+initscr
+.El
+.Pp
+Описания действий перечислены ниже:
+.Pp
+.Bl -tag -width "M-j, M-<TAB>XXX" -offset indent -compact
+.It Cm term
+Запустить эмулятор терминала
+(Смотрите секцию
+.Sx ПРОГРАММЫ
+выше)
+.It Cm menu
+Меню
+(Смотрите секцию
+.Sx ПРОГРАММЫ
+выше)
+.It Cm quit
+Выйти
+.Nm
+.It Cm restart
+Перезапустить
+.Nm
+.It Cm cycle_layout
+Менять укладку окон
+.It Cm reset_layout
+Стандартная укладка
+.It Cm master_shrink
+Сжать область главного окна
+.It Cm master_grow
+Расширить область главного окна
+.It Cm master_add
+Добавить окна в главную область
+.It Cm master_del
+Убрать окна из главной области
+.It Cm stack_inc
+Увеличить число столбцов или рядов в текущей укладке
+.It Cm stack_del
+Уменьшить число столбцов или рядов в текущей укладке
+.It Cm swap_main
+Отправить текущее окно в главную область, сделать главным
+.It Cm focus_next
+Фокусироваться на следующем окне
+.It Cm focus_prev
+Фокусироваться на предыдущем окне
+.It Cm focus_main
+Фокусироваться на главном окне
+.It Cm swap_next
+Поменять со следующим окном
+.It Cm swap_prev
+Поменять со предыдущим окном
+.It Cm bar_toggle
+Выключить статусную строку на всех рабочих столах
+.It Cm wind_del
+Закрыть фокусированное окно
+.It Cm wind_kill
+Грохнуть фокусированное окно
+.It Cm ws_ Ns Ar n
+Переключиться на рабочий стол
+.Ar n ,
+где
+.Ar n
+от 1 до 10
+.It Cm mvws_ Ns Ar n
+Переместить фокусированное окно в рабочий стол
+.Ar n ,
+где
+.Ar n
+от 1 до 10
+.It Cm ws_next
+Перейти к следующему не пустому рабочему столу
+.It Cm ws_prev
+Перейти к следующему не пустому рабочему столу
+.It Cm screen_next
+Переместить указатель в следующую область
+.It Cm screen_prev
+Переместить указатель в следующую область
+.It Cm screenshot_all
+Сделать снимок всего экрана (если возможно)
+(Смотрите секцию
+.Sx ПРОГРАММЫ
+выше)
+.It Cm screenshot_wind
+Сделать снимок окна (если возможно)
+(Смотрите секцию
+.Sx ПРОГРАММЫ
+выше)
+.It Cm version
+Показать версию в статусной строке
+.It Cm float_toggle
+Переключить окно в фокусе в плавающий режим, float
+.It Cm lock
+Заблокировать экран
+(Смотрите секцию
+.Sx ПРОГРАММЫ
+выше)
+.It Cm initscr
+Инициализировать экран еще раз
+(Смотрите секцию
+.Sx ПРОГРАММЫ
+выше)
+.El
+.Pp
+Собственные привязки назначаются следующим образом:
+.Pp
+.Dl bind[<action>] = <keys>
+.Pp
+.Aq action
+это действие из списка программ
+.Aq keys
+это не более одной клавиши-модификатора
+(MOD, Mod1, Shift, и.т.п.) и обычные клавиши
+(b, space, и.т.п.), разделенные "+".
+Например:
+.Bd -literal -offset indent
+bind[reset] = Mod4+q # назначить WIN + q на действие reset
+bind[] = Mod1+q # снять все действия с Alt + q
+.Ed
+.Pp
+На одно действие можно назначить несколько комбинаций.
+.Sh КОСТЫЛИ
+.Nm
+позволяет настроить костыли, нужные для специальной работы spectrwm
+с рядом приложений, который вы определяете сами. То есть, Вы можете
+принудительно установить способ тайлинга для какого-нибудь приложения
+.Pp
+Список стандартных костылей:
+.Pp
+.Bl -tag -width "OpenOffice.org N.M:VCLSalFrame<TAB>XXX" -offset indent -compact
+.It Firefox\-bin:firefox\-bin
+TRANSSZ
+.It Firefox:Dialog
+FLOAT
+.It Gimp:gimp
+FLOAT + ANYWHERE
+.It MPlayer:xv
+FLOAT + FULLSCREEN
+.It OpenOffice.org 2.4:VCLSalFrame
+FLOAT
+.It OpenOffice.org 3.1:VCLSalFrame
+FLOAT
+.It pcb:pcb
+FLOAT
+.It xine:Xine Window
+FLOAT + ANYWHERE
+.It xine:xine Panel
+FLOAT + ANYWHERE
+.It xine:xine Video Fullscreen Window
+FULLSCREEN + FLOAT
+.It Xitk:Xitk Combo
+FLOAT + ANYWHERE
+.It Xitk:Xine Window
+FLOAT + ANYWHERE
+.It XTerm:xterm
+XTERM_FONTADJ
+.El
+.Pp
+Описание:
+.Pp
+.Bl -tag -width "XTERM_FONTADJ<TAB>XXX" -offset indent -compact
+.It FLOAT
+Такое окно не нужно тайлить вообще, разрешить ему float
+.It TRANSSZ
+Тразиентое окно
+(Смотрите секцию
+.Sx КОНФИГУРАЦИОННЫЕ ФАЙЛЫ) .
+.It ANYWHERE
+Позволить окну самостоятельно выбрать местоположение
+.It XTERM_FONTADJ
+Изменять шрифты xterm при изменении размеров окна
+.It FULLSCREEN
+Позволить окну запускаться в полноэкранном режиме
+.El
+.Pp
+Назначать костыли можно следующим образом:
+.Pp
+.Dl quirk[<class>:<name>] = <quirk> [ + <quirk> ... ]
+.Pp
+.Aq class
+.Aq name
+определяют к какому окну будет применяться костыль, а
+.Aq quirk
+один из вышеперечисленных способов.
+Например:
+.Bd -literal -offset indent
+quirk[MPlayer:xv] = FLOAT + FULLSCREEN # mplayer настроен
+quirk[pcb:pcb] = NONE  # убрать существующий костыль
+.Ed
+.Pp
+Вы можете узнать
+.Aq class
+.Aq name
+запустив xprop и нажав в интересующее окно.
+Вот как будет выглядеть вывод для Firefox:
+.Bd -literal -offset indent
+$ xprop | grep WM_CLASS
+WM_CLASS(STRING) = "Navigator", "Firefox"
+.Ed
+.Pp
+Обратите внимание, класс и имя меняются местами,
+правильный костыль будет выглядеть так:
+.Bd -literal -offset indent
+quirk[Firefox:Navigator] = FLOAT
+.Ed
+.Sh ФАЙЛЫ
+.Bl -tag -width "/etc/spectrwm.confXXX" -compact
+.It Pa ~/.spectrwm.conf
+.Nm
+Личные настройки пользователя.
+.It Pa /etc/spectrwm.conf
+.Nm
+Глобавльные настройки.
+.El
+.Sh ИСТОРИЯ
+.Nm
+идейно основан на dwm и xmonad
+.Sh АВТОРЫ
+.An -nosplit
+.Pp
+.Nm
+написан:
+.An Marco Peereboom Aq marco@peereboom.us ,
+.An Ryan Thomas McBride Aq mcbride@countersiege.com
+and
+.An Darrin Chandler Aq dwchandler@stilyagin.com .
+.Sh БАГИ
+При вызове меню с помощью
+.Cm M-p ,
+необходима корректная работа dmenu.
diff --git a/spectrwm_se.conf b/spectrwm_se.conf
new file mode 100644 (file)
index 0000000..68dba05
--- /dev/null
@@ -0,0 +1,74 @@
+# Key bindings for Swedish (se) keyboards
+# unbind with: bind[] = <keys>
+bind[cycle_layout]     = MOD+space
+bind[flip_layout]      = MOD+Shift+apostrophe
+bind[stack_reset]      = MOD+Shift+space
+bind[master_shrink]    = MOD+h
+bind[master_grow]      = MOD+l
+bind[master_add]       = MOD+comma
+bind[master_del]       = MOD+period
+bind[stack_inc]                = MOD+Shift+comma
+bind[stack_dec]                = MOD+Shift+period
+bind[swap_main]                = MOD+Return
+bind[focus_next]       = MOD+j
+bind[focus_prev]       = MOD+k
+bind[swap_next]                = MOD+Shift+j
+bind[swap_prev]                = MOD+Shift+k
+bind[spawn_term]       = MOD+Shift+Return
+bind[menu]             = MOD+p
+bind[quit]             = MOD+Shift+q
+bind[restart]          = MOD+q
+bind[focus_main]       = MOD+m
+bind[ws_1]             = MOD+1
+bind[ws_2]             = MOD+2
+bind[ws_3]             = MOD+3
+bind[ws_4]             = MOD+4
+bind[ws_5]             = MOD+5
+bind[ws_6]             = MOD+6
+bind[ws_7]             = MOD+7
+bind[ws_8]             = MOD+8
+bind[ws_9]             = MOD+9
+bind[ws_10]            = MOD+0
+bind[ws_next]          = MOD+Right
+bind[ws_prev]          = MOD+Left
+bind[ws_next_all]      = MOD+Up
+bind[ws_prev_all]      = MOD+Down
+bind[ws_prior]         = MOD+a
+bind[screen_next]      = MOD+Shift+Right
+bind[screen_prev]      = MOD+Shift+Left
+bind[mvws_1]           = MOD+Shift+1
+bind[mvws_2]           = MOD+Shift+2
+bind[mvws_3]           = MOD+Shift+3
+bind[mvws_4]           = MOD+Shift+4
+bind[mvws_5]           = MOD+Shift+5
+bind[mvws_6]           = MOD+Shift+6
+bind[mvws_7]           = MOD+Shift+7
+bind[mvws_8]           = MOD+Shift+8
+bind[mvws_9]           = MOD+Shift+9
+bind[mvws_10]          = MOD+Shift+0
+bind[bar_toggle]       = MOD+b
+bind[focus_next]       = MOD+Tab
+bind[focus_prev]       = MOD+Shift+Tab
+bind[wind_kill]                = MOD+Shift+x
+bind[wind_del]         = MOD+x
+bind[screenshot_all]   = MOD+s
+bind[screenshot_wind]  = MOD+Shift+s
+bind[float_toggle]     = MOD+t
+bind[version]          = MOD+Shift+v
+bind[lock]             = MOD+Shift+Delete
+bind[initscr]          = MOD+Shift+i
+bind[iconify]          = MOD+w
+bind[uniconify]                = MOD+Shift+w
+bind[raise_toggle]     = MOD+Shift+r
+bind[button2]          = MOD+v
+bind[width_shrink]     = MOD+plus
+bind[width_grow]       = MOD+dead_acute
+bind[height_shrink]    = MOD+Shift+plus
+bind[height_grow]      = MOD+Shift+dead_acute
+bind[move_left]                = MOD+aring
+bind[move_right]       = MOD+dead_diaeresis
+bind[move_up]          = MOD+Shift+aring
+bind[move_down]                = MOD+Shift+dead_diaeresis
+bind[name_workspace]   = MOD+Shift+minus
+bind[search_workspace] = MOD+minus
+bind[search_win]       = MOD+f
diff --git a/spectrwm_us.conf b/spectrwm_us.conf
new file mode 100644 (file)
index 0000000..f2ce392
--- /dev/null
@@ -0,0 +1,74 @@
+# Key bindings for United States (us) keyboards
+# unbind with: bind[] = <keys>
+bind[cycle_layout]     = MOD+space
+bind[flip_layout]      = MOD+Shift+backslash
+bind[stack_reset]      = MOD+Shift+space
+bind[master_shrink]    = MOD+h
+bind[master_grow]      = MOD+l
+bind[master_add]       = MOD+comma
+bind[master_del]       = MOD+period
+bind[stack_inc]                = MOD+Shift+comma
+bind[stack_dec]                = MOD+Shift+period
+bind[swap_main]                = MOD+Return
+bind[focus_next]       = MOD+j
+bind[focus_prev]       = MOD+k
+bind[swap_next]                = MOD+Shift+j
+bind[swap_prev]                = MOD+Shift+k
+bind[spawn_term]       = MOD+Shift+Return
+bind[menu]             = MOD+p
+bind[quit]             = MOD+Shift+q
+bind[restart]          = MOD+q
+bind[focus_main]       = MOD+m
+bind[ws_1]             = MOD+1
+bind[ws_2]             = MOD+2
+bind[ws_3]             = MOD+3
+bind[ws_4]             = MOD+4
+bind[ws_5]             = MOD+5
+bind[ws_6]             = MOD+6
+bind[ws_7]             = MOD+7
+bind[ws_8]             = MOD+8
+bind[ws_9]             = MOD+9
+bind[ws_10]            = MOD+0
+bind[ws_next]          = MOD+Right
+bind[ws_prev]          = MOD+Left
+bind[ws_next_all]      = MOD+Up
+bind[ws_prev_all]      = MOD+Down
+bind[ws_prior]         = MOD+a
+bind[screen_next]      = MOD+Shift+Right
+bind[screen_prev]      = MOD+Shift+Left
+bind[mvws_1]           = MOD+Shift+1
+bind[mvws_2]           = MOD+Shift+2
+bind[mvws_3]           = MOD+Shift+3
+bind[mvws_4]           = MOD+Shift+4
+bind[mvws_5]           = MOD+Shift+5
+bind[mvws_6]           = MOD+Shift+6
+bind[mvws_7]           = MOD+Shift+7
+bind[mvws_8]           = MOD+Shift+8
+bind[mvws_9]           = MOD+Shift+9
+bind[mvws_10]          = MOD+Shift+0
+bind[bar_toggle]       = MOD+b
+bind[focus_next]       = MOD+Tab
+bind[focus_prev]       = MOD+Shift+Tab
+bind[wind_kill]                = MOD+Shift+x
+bind[wind_del]         = MOD+x
+bind[screenshot_all]   = MOD+s
+bind[screenshot_wind]  = MOD+Shift+s
+bind[float_toggle]     = MOD+t
+bind[version]          = MOD+Shift+v
+bind[lock]             = MOD+Shift+Delete
+bind[initscr]          = MOD+Shift+i
+bind[iconify]          = MOD+w
+bind[uniconify]                = MOD+Shift+w
+bind[raise_toggle]     = MOD+Shift+r
+bind[button2]          = MOD+v
+bind[width_shrink]     = MOD+minus
+bind[width_grow]       = MOD+equal
+bind[height_shrink]    = MOD+Shift+minus
+bind[height_grow]      = MOD+Shift+equal
+bind[move_left]                = MOD+bracketleft
+bind[move_right]       = MOD+bracketright
+bind[move_up]          = MOD+Shift+bracketleft
+bind[move_down]                = MOD+Shift+bracketright
+bind[name_workspace]   = MOD+Shift+slash
+bind[search_workspace] = MOD+slash
+bind[search_win]       = MOD+f
index 83efea9..3cf35e5 100644 (file)
--- a/version.h
+++ b/version.h
  */
 
 
-#ifndef SCROTWM_VERSION_H
-#define SCROTWM_VERSION_H
+#ifndef SPECTRWM_VERSION_H
+#define SPECTRWM_VERSION_H
 
-#define SCROTWM_STR(x)         #x
-#define SCROTWM_STRINGIZE(x)   SCROTWM_STR(x)
+#define SPECTRWM_STR(x)                #x
+#define SPECTRWM_STRINGIZE(x)  SPECTRWM_STR(x)
 
-#define SCROTWM_MAJOR          0
-#define SCROTWM_MINOR          11
-#define SCROTWM_PATCH          0
-#define SCROTWM_VERSION                SCROTWM_STRINGIZE(SCROTWM_MAJOR) "." \
-                               SCROTWM_STRINGIZE(SCROTWM_MINOR) "." \
-                               SCROTWM_STRINGIZE(SCROTWM_PATCH)
+#define SPECTRWM_MAJOR         0
+#define SPECTRWM_MINOR         11
+#define SPECTRWM_PATCH         0
+#define SPECTRWM_VERSION               SPECTRWM_STRINGIZE(SPECTRWM_MAJOR) "." \
+                               SPECTRWM_STRINGIZE(SPECTRWM_MINOR) "." \
+                               SPECTRWM_STRINGIZE(SPECTRWM_PATCH)
 
-#endif /* SCROTWM_VERSION_H */
+#endif /* SPECTRWM_VERSION_H */