Compare commits

..

No commits in common. "master" and "linkdd" have entirely different histories.

50 changed files with 800 additions and 4358 deletions

View File

@ -11,14 +11,13 @@ SRCS= \
src/ewmh.c \
src/infobar.c \
src/layout.c \
src/launcher.c \
src/parse_api.c \
src/parse.c \
src/screen.c \
src/tag.c \
src/util.c \
src/fifo.c \
src/status.c \
src/systray.c \
src/mouse.c \
src/log.c \
src/wmfs.c
@ -53,13 +52,9 @@ install: all
install ${PROG} ${DESTDIR}${PREFIX}/bin
@echo installing xsession file to ${DESTDIR}${PREFIX}/share/xsessions
mkdir -p ${DESTDIR}${PREFIX}/share/xsessions
install -m 444 wmfs.desktop ${DESTDIR}${PREFIX}/share/xsessions
@echo installing default config file to ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
mkdir -p ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
install -m 444 wmfsrc ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
@echo installing manual pages to ${DESTDIR}${MANPREFIX}/man1/
mkdir -p ${DESTDIR}${MANPREFIX}/man1/
install -m 644 wmfs.1 ${DESTDIR}${MANPREFIX}/man1/wmfs.1
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@ -68,8 +63,6 @@ uninstall:
@echo removing config file from ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
rm -f ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/wmfsrc
rmdir ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
@echo removing manual pages from ${DESTDIR}${MANPREFIX}/man1
rm -f ${DESTDIR}${MANPREFIX}/man1/wmfs.1
dist:
@echo "Generate wmfs-`date +%Y%m`.tar.gz"

92
configure vendored
View File

@ -11,77 +11,61 @@ MANPREFIX="$PREFIX/man"
XDG_CONFIG_DIR="$PREFIX/etc/xdg"
while true; do
case "$1" in
--without-xinerama)
USE_XINERAMA=""; shift;;
--without-imlib2)
USE_IMLIB2=""; shift;;
--prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
PREFIX=$2; shift 2;;
--man-prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
MANPREFIX=$2; shift 2;;
--xdg-config-dir)
[ -z "$2" ] && echo "Missing argument" && exit 1
XDG_CONFIG_DIR=$2; shift 2;;
--help|-h)
echo "Usage: ./configure [options]
case "$1" in
--without-xinerama)
USE_XINERAMA=""; shift;;
--prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
PREFIX=$2; shift 2;;
--xdg-config-dir)
[ -z "$2" ] && echo "Missing argument" && exit 1
XDG_CONFIG_DIR=$2; shift 2;;
--help|-h)
echo "Usage: ./configure [options]
--without-xinerama : compile without xinerama support
--without-imlib2 : compile without imlib2 support
--prefix DIRECTORY : install binary with specified prefix (default $PREFIX)
--man-prefix DIRECTORY : install binary with specified prefix (default $PREFIX)
--xdg-config-dir DIRECTORY : install configuration to specified directory (default $XDG_CONFIG_DIR)"
exit 0;;
*) break;;
esac
exit 0;;
*) break;;
esac
done
LIBS="$LIBS $USE_XINERAMA $USE_IMLIB2"
LIBS="$LIBS $USE_XINERAMA"
which pkg-config > /dev/null 2>&1
if [ $? -eq 0 ];
then
CFLAGS=`pkg-config --cflags-only-I $LIBS`
LDFLAGS=`pkg-config --libs $LIBS`
CFLAGS=`pkg-config --cflags-only-I $LIBS`
LDFLAGS=`pkg-config --libs $LIBS`
else
# Try to use some known paths
case $OS in
FreeBSD)
CFLAGS="-I/usr/local/include"
LDFLAGS="-L/usr/local/lib";;
OpenBSD)
CFLAGS="-I/usr/X11R6/include -I/usr/local/include"
LDFLAGS="-L/usr/X11R6/lib -L/usr/local/lib";;
NetBSD)
CFLAGS="-I/usr/X11R7/include -I/usr/pkg/include"
LDFLAGS="-L/usr/X11R7/lib -L/usr/pkg/lib";;
Linux)
CFLAGS=""
LDFLAGS=""
;;
*)
echo "No default CFLAGS and LDFLAGS found for your OS, feel free to contribute or install pkg-config :)"
exit 1;;
esac
case $OS in
FreeBSD)
CFLAGS="-I/usr/local/include"
LDFLAGS="-L/usr/local/lib";;
OpenBSD)
CFLAGS="-I/usr/X11R6/include -I/usr/local/include"
LDFLAGS="-L/usr/X11R6/lib -L/usr/local/lib";;
NetBSD)
CFLAGS="-I/usr/X11R7/include -I/usr/local/include"
LDFLAGS="-L/usr/X11R7/lib -L/usr/local/lib";;
Linux)
CFLAGS=""
LDFLAGS=""
;;
*)
echo "No default CFLAGS and LDFLAGS found for your OS, feel free to contribute or install pkg-config :)"
exit 1;;
esac
LDFLAGS="$LDFLAGS -lX11"
LDFLAGS="$LDFLAGS -lX11"
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
[ -n "$USE_IMLIB2" ] && LDFLAGS="$LDFLAGS -lImlib2"
fi
[ -n "$USE_XINERAMA" ] && CFLAGS="$CFLAGS -DHAVE_XINERAMA"
[ -n "$USE_IMLIB2" ] && CFLAGS="$CFLAGS -DHAVE_IMLIB2"
# Debian hardening options http://wiki.debian.org/Hardening
which dpkg-buildflags > /dev/null 2>&1
if [ $? -eq 0 ];
then
CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 `dpkg-buildflags --get CFLAGS`"
LDFLAGS="$LDFLAGS `dpkg-buildflags --get LDFLAGS`"
fi
cat > Makefile << EOF
PREFIX=$PREFIX

45
debian/changelog vendored
View File

@ -1,45 +0,0 @@
wmfs (2~beta201206-3) unstable; urgency=low
* No hardening-related Lintiant warnings
-- Mickaël Raybaud-Roig <raybaudroigm@gmail.com> Sun, 24 Jun 2012 16:40:54 +0200
wmfs (2~beta201206-2) unstable; urgency=low
* Fixed some Lintian warnings
* New standards version
-- Mickaël Raybaud-Roig <raybaudroigm@gmail.com> Sun, 24 Jun 2012 15:19:38 +0200
wmfs (2~beta201206-1) unstable; urgency=low
* Updated changelog version
* Added build-depends to the control file
* Updated Vcs-* fields in the control file
-- Mickaël Raybaud-Roig <raybaudroigm@gmail.com> Sun, 24 Jun 2012 13:12:26 +0200
wmfs (2~beta-3) unstable; urgency=low
* Modified build script (debian/rules)
* Modified versions in changelog
* Removed the old manpage
* The configuration is done in override_dh_auto_configure (in debian/rules)
* The .desktop file is installed by dh_install
-- Mickaël Raybaud-Roig <raybaudroigm@gmail.com> Sat, 18 Feb 2012 19:40:09 +0100
wmfs (2~beta-2) unstable; urgency=low
* Added a manpage
* Modified the debian/rules script
* Filled debian/copying
* Added dependencies
-- Mickaël Raybaud-Roig <raybaudroigm@gmail.com> Sat, 28 Jan 2012 12:44:18 +0100
wmfs (2~beta-1) unstable; urgency=low
* Initial release
-- Mickaël Raybaud-Roig <raybaudroigm@gmail.com> Sat, 21 Jan 2012 13:22:37 +0100

1
debian/compat vendored
View File

@ -1 +0,0 @@
8

16
debian/control vendored
View File

@ -1,16 +0,0 @@
Source: wmfs
Section: x11
Priority: extra
Maintainer: Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
Build-Depends: debhelper (>= 8.0.0), libimlib2-dev, libxinerama-dev, libx11-dev
Standards-Version: 3.9.3
Homepage: http://wmfs.info
Vcs-Git: git://github.com/xorg62/wmfs.git
Vcs-Browser: https://github.com/xorg62/wmfs
Package: wmfs
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, libxinerama1, libimlib2, libxcb1, libfreetype6
Description: Window Manager From Scratch
WMFS (Window Manager From Scratch) is a lightweight and highly configurable
tiling window manager for X.

54
debian/copyright vendored
View File

@ -1,54 +0,0 @@
Format: http://dep.debian.net/deps/dep5
Upstream-Name: wmfs
Source: http://wmfs.info
Files: *
Copyright: 2011-2012 Martin Duquesnoy <xorg62@gmail.com>
License: BSD-3-Clauses
Files: debian/*
Copyright: 2012 Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
License: WTFPL-2
License: BSD-3-Clauses
Copyright (c) 1983 The Regents of the University of California.
All rights reserved.
.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
License: WTFPL-2
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
.
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
.
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
.
0. You just DO WHAT THE FUCK YOU WANT TO.

1
debian/docs vendored
View File

@ -1 +0,0 @@
README

16
debian/rules vendored
View File

@ -1,16 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
override_dh_auto_configure:
./configure --prefix /usr --xdg-config-dir /etc/xdg --man-prefix /usr/share/man/
%:
dh $@

View File

@ -1 +0,0 @@
3.0 (quilt)

1
debian/wmfs.install vendored
View File

@ -1 +0,0 @@
wmfs.desktop /usr/share/xsessions

View File

@ -1 +0,0 @@
wmfs.1

1
debian/wmfs.wm vendored
View File

@ -1 +0,0 @@
/usr/bin/wmfs

View File

@ -1,64 +0,0 @@
#! /bin/sh
# simple help script for WMFS2 by arpinux
# default keybinds list
xpos="5"
ypos="5"
width="350"
height="730"
bg="#222222"
fg="#7D7D7D"
l01="^s[80;12;$bg;WMFS² Keybinds Help]"
l03="^s[15;35;$fg;launch terminal:]^s[190;35;$fg;Super + Return]"
l04="^s[15;50;$fg;launch prompt:]^s[190;50;$fg;Super + p]"
l05="^s[15;65;$fg;close client:]^s[190;65;$fg;Super + q]"
l06="^s[15;80;$fg;reload wmfs:]^s[190;80;$fg;Control + Alt + r]"
l07="^s[15;95;$fg;quit wmfs:]^s[190;95;$fg;Control + Alt + q]"
l08="^s[15;115;$fg;next client:]^s[190;115;$fg;Alt + Tab]"
l09="^s[15;130;$fg;prev client:]^s[190;130;$fg;Alt + Shift + Tab]"
l10="^s[15;145;$fg;next tabbed client:]^s[190;145;$fg;Super + Tab]"
l11="^s[15;160;$fg;prev tabbed client:]^s[190;160;$fg;Super + Shift + Tab]"
l12="^s[15;175;$fg;left client:]^s[190;175;$fg;Alt + h]"
l13="^s[15;190;$fg;right client:]^s[190;190;$fg;Alt + l]"
l14="^s[15;205;$fg;top client:]^s[190;205;$fg;Alt + k]"
l15="^s[15;220;$fg;bottom client:]^s[190;220;$fg;Alt + j]"
l16="^s[15;235;$fg;swap client left:]^s[190;235;$fg;Control + Shift + h]"
l17="^s[15;250;$fg;swap client right:]^s[190;250;$fg;Control + Shift + l]"
l18="^s[15;265;$fg;swap client top:]^s[190;265;$fg;Control + Shift + k]"
l19="^s[15;280;$fg;swap client bottom:]^s[190;280;$fg;Control + Shift + j]"
l20="^s[15;295;$fg;tab client left:]^s[190;295;$fg;Alt + Shift + h]"
l21="^s[15;310;$fg;tab client right:]^s[190;310;$fg;Alt + Shift + l]"
l22="^s[15;325;$fg;tab client top:]^s[190;325;$fg;Alt + Shift + k]"
l23="^s[15;340;$fg;tab client bottom:]^s[190;340;$fg;Alt + Shift + j]"
l24="^s[15;355;$fg;untab client:]^s[190;355;$fg;Alt + Shift + u]"
l25="^s[15;375;$fg;increase client on left:]^s[190;375;$fg;Super + h]"
l26="^s[15;390;$fg;decrease client from left:]^s[190;390;$fg;Super + l]"
l27="^s[15;405;$fg;increase client on top:]^s[190;405;$fg;Super + k]"
l28="^s[15;420;$fg;decrease client from top:]^s[190;420;$fg;Super + j]"
l29="^s[15;435;$fg;decrease client from right:]^s[190;435;$fg;Super + Control + h]"
l30="^s[15;450;$fg;increase client on right:]^s[190;450;$fg;Super + Control + l]"
l31="^s[15;465;$fg;decrease client from bottom:]^s[190;465;$fg;Super + Control + k]"
l32="^s[15;480;$fg;increase client to bottom:]^s[190;480;$fg;Super + Control + j]"
l33="^s[15;495;$fg;integrate client to left:]^s[190;495;$fg;Super + Control + Alt + h]"
l34="^s[15;510;$fg;integrate client to right:]^s[190;510;$fg;Super + Control + Alt + l]"
l35="^s[15;525;$fg;integrate client to top:]^s[190;525;$fg;Super + Control + Alt + k]"
l36="^s[15;540;$fg;integrate client to bottom:]^s[190;540;$fg;Super + Control + Alt + j]"
l37="^s[15;560;$fg;horizontal layout:]^s[190;560;$fg;Super + Shift + m]"
l38="^s[15;575;$fg;vertical layout:]^s[190;575;$fg;Super + m]"
l39="^s[15;590;$fg;layout rotate right:]^s[190;590;$fg;Super + r]"
l40="^s[15;605;$fg;layout rotate left:]^s[190;605;$fg;Super + Shift + r]"
l41="^s[15;620;$fg;toggle client free:]^s[190;620;$fg;Super + f]"
l42="^s[15;640;$fg;prev/next tag:]^s[190;640;$fg;Control + Left/Right]"
l43="^s[15;655;$fg;prev/next screen:]^s[190;655;$fg;Control + Up/Down]"
l44="^s[15;670;$fg;set tag (x):]^s[190;670;$fg;Super + F(x)]"
l45="^s[15;685;$fg;tag client with (x):]^s[190;685;$fg;Super + Shift + F(x)]"
l46="^s[15;700;$fg;add tag:]^s[190;700;$fg;Super + Shift + -]"
l47="^s[15;715;$fg;delete tag:]^s[190;715;$fg;Super + -]"
frame="^R[0;0;350;15;$fg] ^R[0;728;350;2;$fg] ^R[0;0;2;730;$fg] ^R[348;0;2;730;$fg]"
wmfs -c status_surface "$xpos,$ypos,$width,$height,$bg $frame $l01 $l03 $l04 $l05 $l06 $l07 $l08 $l09 $l10 $l11 $l12 $l13 $l14 $l15 $l16 $l17 $l18 $l19 $l20 $l21 $l22 $l23 $l24 $l25 $l26 $l27 $l28 $l29 $l30 $l31 $l32 $l33 $l34 $l35 $l36 $l37 $l38 $l39 $l40 $l41 $l42 $l43 $l44 $l45 $l46 $l47"

View File

@ -5,9 +5,7 @@ TIMING=10
statustext()
{
# Syntax : status <bar name> <data>
# possible sequences as data: \s[] \R[] \i[]
wmfs -c status "default `date`"
echo "status default `date`" > /tmp/wmfs-$DISPLAY.fifo
}
while true;

View File

@ -23,7 +23,7 @@ barwin_new(Window parent, int x, int y, int w, int h, Color fg, Color bg, bool e
struct barwin *b = (struct barwin*)xcalloc(1, sizeof(struct barwin));
XSetWindowAttributes at =
{
.override_redirect = true,
.override_redirect = True,
.background_pixmap = ParentRelative,
.event_mask = BARWIN_MASK
};
@ -51,7 +51,6 @@ barwin_new(Window parent, int x, int y, int w, int h, Color fg, Color bg, bool e
b->fg = fg;
SLIST_INIT(&b->mousebinds);
SLIST_INIT(&b->statusmousebinds);
/* Attach */
SLIST_INSERT_HEAD(&W->h.barwin, b, next);

View File

@ -22,14 +22,9 @@
#define barwin_refresh(b) XCopyArea(W->dpy, b->dr, b->win, W->gc, 0, 0, b->geo.w, b->geo.h, 0, 0)
#define barwin_map(b) XMapWindow(W->dpy, b->win);
#define barwin_unmap(b) XUnmapWindow(W->dpy, b->win);
#define barwin_move(b, x, y) XMoveWindow(W->dpy, b->win, x, y);
#define barwin_reparent(b, w) XReparentWindow(W->dpy, b->win, w, 0, 0);
static inline void
barwin_move(struct barwin *b, int x, int y)
{
XMoveWindow(W->dpy, b->win, (b->geo.x = x), (b->geo.y = y));
}
struct barwin* barwin_new(Window parent, int x, int y, int w, int h, Color fg, Color bg, bool entermask);
void barwin_remove(struct barwin *b);
void barwin_resize(struct barwin *b, int w, int h);

View File

@ -9,42 +9,45 @@
#include "config.h"
#include "event.h"
#include "barwin.h"
#include "barwin.h"
#include "draw.h"
#include "screen.h"
#include "mouse.h"
#define CLIENT_RESIZE_DIR(D) \
void uicb_client_resize_##D(Uicb cmd) \
{ \
if(W->client) \
client_fac_resize(W->client, D, ATOI(cmd)); \
}
#define CLIENT_MOUSE_MOD Mod1Mask
#define CLIENT_ACTION_DIR(A, D) \
void uicb_client_##A##_##D(Uicb cmd) \
{ \
(void)cmd; \
struct client *c; \
if(W->client && (c = client_next_with_pos(W->client, D))) \
client_##A(c); \
}
#define CLIENT_RESIZE_DIR(D) \
void uicb_client_resize_##D(Uicb cmd) \
{ \
if(W->client) \
client_fac_resize(W->client, D, ATOI(cmd)); \
}
#define CLIENT_ACTION_IDIR(A, D) \
void uicb_client_##A##_##D(Uicb cmd) \
{ \
(void)cmd; \
if(W->client) \
client_##A(W->client, D); \
}
#define CLIENT_ACTION_DIR(A, D) \
void uicb_client_##A##_##D(Uicb cmd) \
{ \
(void)cmd; \
struct client *c; \
if(W->client && (c = client_next_with_pos(W->client, D))) \
client_##A(c); \
}
#define CLIENT_ACTION_LIST(A, L) \
void uicb_client_##A##_##L(Uicb cmd) \
{ \
(void)cmd; \
struct client *c; \
if(W->client && (c = client_##L(W->client))) \
client_##A(c); \
}
#define CLIENT_ACTION_IDIR(A, D) \
void uicb_client_##A##_##D(Uicb cmd) \
{ \
(void)cmd; \
if(W->client) \
client_##A(W->client, D); \
}
#define CLIENT_ACTION_LIST(A, L) \
void uicb_client_##A##_##L(Uicb cmd) \
{ \
(void)cmd; \
struct client *c; \
if(W->client && (c = client_##L(W->client))) \
client_##A(c); \
}
/* uicb_client_resize_dir() */
CLIENT_RESIZE_DIR(Right)
@ -87,7 +90,7 @@ CLIENT_ACTION_LIST(focus, prev_tab)
/** Send a ConfigureRequest event to the struct client
* \param c struct client pointer
*/
void
inline void
client_configure(struct client *c)
{
XConfigureEvent ev =
@ -104,8 +107,8 @@ client_configure(struct client *c)
.override_redirect = 0
};
XSendEvent(W->dpy, c->win, false, StructureNotifyMask, (XEvent *)&ev);
XSync(W->dpy, false);
XSendEvent(W->dpy, c->win, False, StructureNotifyMask, (XEvent *)&ev);
XSync(W->dpy, False);
}
struct client*
@ -113,15 +116,10 @@ client_gb_win(Window w)
{
struct client *c = SLIST_FIRST(&W->h.client);
while(c)
{
if(c->win == w)
return c;
while(c && c->win != w)
c = SLIST_NEXT(c, next);
}
return NULL;
return c;
}
struct client*
@ -129,26 +127,25 @@ client_gb_frame(Window w)
{
struct client *c = SLIST_FIRST(&W->h.client);
while(c)
{
if(c->frame == w)
return c;
while(c && c->frame != w)
c = SLIST_NEXT(c, next);
}
return NULL;
return c;
}
struct client*
client_gb_pos(struct tag *t, int x, int y)
{
struct client *c;
struct client *c = SLIST_FIRST(&t->clients);
FOREACH_NFCLIENT(c, &t->clients, tnext)
while(c)
{
if(INAREA(x, y, c->geo))
return c;
c = SLIST_NEXT(c, tnext);
}
return NULL;
}
@ -157,18 +154,10 @@ client_gb_titlebar(Window w)
{
struct client *c = SLIST_FIRST(&W->h.client);
if(!c->titlebar)
return NULL;
while(c)
{
if(c->titlebar->win == w)
return c;
while(c && c->titlebar->win != w)
c = SLIST_NEXT(c, next);
}
return NULL;
return c;
}
/*
@ -198,68 +187,38 @@ client_next_with_pos(struct client *bc, enum position p)
return c;
}
#define FLAG_SWAP2(f1, f2, m1) \
if((f1 & m1) != (f2 & m1)) \
{ \
f1 ^= m1; \
f2 ^= m1; \
}
#define SWAP_ARRANGE_TAB(C) \
SLIST_FOREACH(c, &C->tag->clients, tnext) \
{ \
if(c->tabmaster == C) \
{ \
c->screen = C->screen; \
if((C->flags & CLIENT_FREE) != (c->flags & CLIENT_FREE)) \
{ \
c->flags ^= CLIENT_FREE; \
c->flags ^= CLIENT_TILED; \
} \
} \
}
void
client_swap2(struct client *c1, struct client *c2)
{
struct client *c;
struct tag *t;
struct geo g;
/* Conflict / errors */
if(c1 == c2 || !c1 || !c2)
return;
/* Reverse FREE/TILED flags if there are different */
FLAG_SWAP2(c1->flags, c2->flags, CLIENT_FREE);
FLAG_SWAP2(c1->flags, c2->flags, CLIENT_TILED);
/* are swapped geos compatible? */
if(client_winsize(c1, &c2->geo)
|| client_winsize(c2, &c1->geo))
return;
if(c1->screen != c2->screen)
swap_ptr((void**)&c1->screen, (void**)&c2->screen);
/*
* Arrange flags for all tabbed client of
* possible c1/c2 tabmaster
*/
if(c1->flags & CLIENT_TABMASTER)
SWAP_ARRANGE_TAB(c1);
if(c2->flags & CLIENT_TABMASTER)
SWAP_ARRANGE_TAB(c2);
if(c1->tag != c2->tag)
{
c1->flags |= CLIENT_IGNORE_LAYOUT;
c2->flags |= CLIENT_IGNORE_LAYOUT;
t = c1->tag;
tag_client(c2->tag, c1);
tag_client(t, c2);
}
g = c1->geo;
client_moveresize(c1, &c2->geo);
client_moveresize(c2, &g);
c1->tgeo = c2->geo;
c2->tgeo = c1->geo;
c1->flags |= CLIENT_IGNORE_ENTER;
c2->flags |= CLIENT_IGNORE_ENTER;
client_moveresize(c1, &c1->tgeo);
client_moveresize(c2, &c2->tgeo);
}
static inline struct client*
@ -304,7 +263,7 @@ client_swap(struct client *c, enum position p)
if(ev.type == KeyPress)
{
XKeyPressedEvent *ke = &ev.xkey;
keysym = XkbKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0, 0);
keysym = XKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0);
_REV_SBORDER();
@ -363,13 +322,13 @@ client_grabbuttons(struct client *c, bool focused)
while(i++ != Button5)
{
XGrabButton(W->dpy, i, W->client_mod, c->win, False,
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(W->dpy, i, W->client_mod | LockMask, c->win, False,
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD | LockMask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(W->dpy, i, W->client_mod | W->numlockmask, c->win, False,
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD | W->numlockmask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(W->dpy, i, W->client_mod | LockMask | W->numlockmask, c->win, False,
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD | LockMask | W->numlockmask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
}
@ -387,26 +346,10 @@ client_grabbuttons(struct client *c, bool focused)
#define _REMAINDER() \
if((rm = ((x + f) - (c->rgeo.w - c->border))) > 0) \
f -= rm;
#define _STATUSLINE(C, b) \
do { \
sctx = (b ? &c->theme->client_s_sl : &c->theme->client_n_sl); \
sctx->barwin = C->titlebar; \
status_copy_mousebind(sctx); \
status_render(sctx); \
if(C->flags & CLIENT_FREE) \
{ \
sctx = &c->theme->client_f_sl; \
sctx->barwin = C->titlebar; \
status_copy_mousebind(sctx); \
status_render(sctx); \
} \
} while(/* CONSTCOND */ 0);
void
client_frame_update(struct client *c, struct colpair *cp)
{
struct client *cc;
struct status_ctx *sctx;
int y, f, xt, rm, w, n = 1;
if(c->flags & CLIENT_TABBED)
@ -441,9 +384,6 @@ client_frame_update(struct client *c, struct colpair *cp)
barwin_move(c->titlebar, 0, 0);
barwin_resize(c->titlebar, f, c->tbarw);
barwin_refresh_color(c->titlebar);
_STATUSLINE(c, (cp == &c->scol));
draw_text(c->titlebar->dr, c->theme, xt, y, cp->fg, c->title);
barwin_refresh(c->titlebar);
}
@ -452,12 +392,10 @@ client_frame_update(struct client *c, struct colpair *cp)
{
struct geo g = { f - 1, 0, 1, c->titlebar->geo.h };
int x = c->border;
char *title;
SLIST_FOREACH(cc, &c->tag->clients, tnext)
{
title = (cc->title ? cc->title : "WMFS");
w = draw_textw(c->theme, title);
w = (cc->title ? draw_textw(c->theme, cc->title) : 0);
_XTEXT();
if(cc == c)
@ -469,10 +407,8 @@ client_frame_update(struct client *c, struct colpair *cp)
barwin_resize(c->titlebar, f, c->tbarw);
barwin_refresh_color(c->titlebar);
_STATUSLINE(c, true);
draw_rect(c->titlebar->dr, &g, c->scol.bg);
draw_text(c->titlebar->dr, c->theme, xt, y, cp->fg, title);
draw_rect(cc->titlebar->dr, g, c->scol.bg);
draw_text(c->titlebar->dr, c->theme, xt, y, cp->fg, c->title);
barwin_refresh(c->titlebar);
x += f;
@ -487,10 +423,8 @@ client_frame_update(struct client *c, struct colpair *cp)
barwin_resize(cc->titlebar, f, c->tbarw - 2);
barwin_refresh_color(cc->titlebar);
_STATUSLINE(cc, false);
draw_rect(cc->titlebar->dr, &g, c->scol.bg);
draw_text(cc->titlebar->dr, c->theme, xt, y - 1, c->ncol.fg, title);
draw_rect(cc->titlebar->dr, g, c->scol.bg);
draw_text(cc->titlebar->dr, c->theme, xt, y - 1, c->ncol.fg, cc->title);
barwin_refresh(cc->titlebar);
x += f;
@ -499,6 +433,7 @@ client_frame_update(struct client *c, struct colpair *cp)
}
}
void
client_tab_focus(struct client *c)
{
@ -509,9 +444,7 @@ client_tab_focus(struct client *c)
c->flags |= CLIENT_TABMASTER;
c->flags &= ~CLIENT_TABBED;
client_moveresize(c, &c->tabmaster->geo);
if(c->tag == c->screen->seltag)
client_map(c);
@ -544,12 +477,9 @@ client_tab_focus(struct client *c)
void
_client_tab(struct client *c, struct client *cm)
{
Flags m[2] = { CLIENT_TILED, CLIENT_FREE };
/* Do not tab already tabbed client */
/* Do not tab already tabed client */
if(c->flags & (CLIENT_TABBED | CLIENT_TABMASTER)
|| c->tag != cm->tag || c == cm
|| !COMPCLIENT(c, cm))
|| c->tag != cm->tag || c == cm)
return;
layout_split_arrange_closed(c);
@ -558,12 +488,6 @@ _client_tab(struct client *c, struct client *cm)
c->geo = cm->geo;
cm->tabmaster = c;
if(cm->flags & CLIENT_FREE)
swap_int((int*)&m[0], (int*)&m[1]);
c->flags |= m[0];
c->flags &= ~m[1];
client_focus(cm);
}
@ -588,7 +512,6 @@ client_untab(struct client *c)
{
client_tab_focus(cc);
c->flags &= ~CLIENT_TABBED;
c->flags |= CLIENT_IGNORE_ENTER;
c->tabmaster = NULL;
/* Looking for tabbed client in cc, if there is not
@ -608,8 +531,7 @@ client_untab(struct client *c)
{
c->geo = c->tgeo = og;
c->tag->sel = cc;
layout_client(c);
layout_split_integrate(c, cc);
client_map(c);
client_moveresize(c, &c->geo);
client_update_props(c, CPROP_TAB);
@ -645,17 +567,7 @@ client_focus(struct client *c)
client_grabbuttons(c, true);
client_tab_focus(c);
client_frame_update(c, CCOL(c));
if(c->flags & CLIENT_FREE
&& !(c->flags & (CLIENT_FULLSCREEN | CLIENT_TABBED)))
{
c->tag->flags |= CLIENT_IGNORE_ENTER;
XRaiseWindow(W->dpy, c->frame);
}
XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
XChangeProperty(W->dpy, W->root, W->net_atom[net_active_window], XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&c->win, 1);
}
else
{
@ -688,10 +600,10 @@ client_get_name(struct client *c)
unsigned long ir, il;
/* This one instead XFetchName for utf8 name support */
if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_name], 0, 65536,
False, W->net_atom[utf8_string], &rt, &rf, &ir, &il, (unsigned char**)&c->title) != Success)
XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_name], 0, 65536,
False, W->net_atom[utf8_string], &rt, &rf, &ir, &il, (unsigned char**)&c->title);
if(XGetWindowProperty(W->dpy, c->win, ATOM("_NET_WM_NAME"), 0, 4096,
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, (unsigned char**)&c->title) != Success)
XGetWindowProperty(W->dpy, c->win, ATOM("WM_NAME"), 0, 4096,
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, (unsigned char**)&c->title);
/* Still no title... */
if(!c->title)
@ -742,7 +654,7 @@ uicb_client_close(Uicb cmd)
client_close(W->client);
}
void
static void
client_get_sizeh(struct client *c)
{
long msize;
@ -809,7 +721,6 @@ static void
client_frame_new(struct client *c)
{
struct barwin *frameb;
struct barwin *clientb;
XSetWindowAttributes at =
{
.background_pixel = c->ncol.bg,
@ -820,7 +731,6 @@ client_frame_new(struct client *c)
/* Use a fake barwin only to store mousebinds of frame win */
frameb = barwin_new(W->root, 0, 0, 1, 1, 0, 0, false);
clientb = barwin_new(W->root, 0, 0, 1, 1, 0, 0, false);
frameb->win =
c->frame = XCreateWindow(W->dpy, W->root,
@ -831,10 +741,8 @@ client_frame_new(struct client *c)
CopyFromParent,
(CWOverrideRedirect | CWBackPixmap
| CWBackPixel | CWEventMask), &at);
clientb->win = c->win;
frameb->mousebinds = W->tmp_head.client;
clientb->mousebinds = W->tmp_head.client;
if(c->tbarw > c->border)
{
@ -847,34 +755,6 @@ client_frame_new(struct client *c)
XReparentWindow(W->dpy, c->win, c->frame, c->border, c->tbarw);
}
static void
_apply_rule(struct client *c, struct rule *r)
{
if(r->screen != -1)
c->screen = screen_gb_id(r->screen);
c->tag = c->screen->seltag;
if(r->tag != -1)
c->tag = tag_gb_id(c->screen, r->tag);
c->theme = r->theme;
/* free = false for originally free client */
if(r->flags & RULE_FREE)
c->flags |= CLIENT_FREE;
else
c->flags &= ~CLIENT_FREE;
/* Free rule is not compatible with tab rule */
if(r->flags & RULE_TAB)
W->flags ^= WMFS_TABNOC; /* < can be disable by client_tab_next_opened */
if(r->flags & RULE_IGNORE_TAG)
c->flags |= CLIENT_IGNORE_TAG;
c->flags |= CLIENT_RULED;
}
#define RINSTANCE 0x01
#define RCLASS 0x02
#define RROLE 0x04
@ -883,7 +763,6 @@ static void
client_apply_rule(struct client *c)
{
struct rule *r;
struct rule *defaultr = NULL;
char *wmname = NULL;
char *role = NULL;
int f;
@ -904,30 +783,42 @@ client_apply_rule(struct client *c)
}
/* Get _NET_WM_NAME */
if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_name], 0, 0x77777777, false,
W->net_atom[utf8_string], &rf, &f, &n, &il, &data)
if(XGetWindowProperty(W->dpy, c->win, ATOM("_NET_WM_NAME"), 0, 0x77777777, false,
ATOM("UTF8_STRING"), &rf, &f, &n, &il, &data)
== Success && data)
{
wmname = xstrdup((char*)data);
XFree(data);
}
/* Apply a specific rule */
SLIST_FOREACH(r, &W->h.rule, next)
{
if (r->instance && !strcmp(r->instance, "*"))
defaultr = r;
if(s)
{
FLAGAPPLY(flags, (xch.res_name && r->instance && !strcmp(xch.res_name, r->instance)), RINSTANCE);
FLAGAPPLY(flags, (xch.res_class && r->class && !strcmp(xch.res_class, r->class)), RCLASS);
FLAGAPPLY(flags, (xch.res_name && r->instance && !strcmp(xch.res_name, r->instance)), RINSTANCE);
FLAGAPPLY(flags, (xch.res_class && r->class && !strcmp(xch.res_class, r->class)), RCLASS);
}
FLAGAPPLY(flags, (wmname && r->name && !strcmp(wmname, r->name)), RNAME);
FLAGAPPLY(flags, ((role && r->role && !strcmp(role, r->role)) || !role || !r->role), RROLE);
if(flags & (RINSTANCE | RCLASS | RNAME) && flags & RROLE)
_apply_rule(c, r);
{
c->screen = screen_gb_id(r->screen);
c->tag = tag_gb_id(c->screen, r->tag);
c->theme = r->theme;
if(r->flags & RULE_FREE)
{ /* TODO */ }
if(r->flags & RULE_MAX)
{ /* TODO */ }
if(r->flags & RULE_IGNORE_TAG)
{ /* TODO */ }
c->flags = r->flags | CLIENT_RULED;
}
flags = 0;
}
@ -936,10 +827,6 @@ client_apply_rule(struct client *c)
if(wmname)
free(wmname);
/* Apply default rule */
if (!(c->flags & CLIENT_RULED) && defaultr != NULL)
_apply_rule(c, defaultr);
}
struct client*
@ -951,7 +838,7 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
c->win = w;
c->flags = 0;
c->screen = screen_update_sel();
c->theme = W->ctheme;
c->theme = THEME_DEFAULT;
c->tag = NULL;
c->tabmaster = NULL;
@ -963,14 +850,7 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
c->tgeo = c->wgeo = c->rgeo = c->geo;
c->tbgeo = NULL;
client_get_sizeh(c);
if(!scan)
{
if(c->flags & CLIENT_HINT_FLAG /* && OPTIONKIVABIEN */)
c->flags |= CLIENT_FREE;
client_apply_rule(c);
}
client_apply_rule(c);
/*
* Conf option set per client, for possibility
@ -985,11 +865,11 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
client_frame_new(c);
/* Set tag */
client_get_sizeh(c);
if(!scan)
{
ewmh_manage_window_type(c);
tag_client((c->flags & CLIENT_RULED ? c->tag : c->screen->seltag), c);
}
/* Map, not at reload */
if(c->tag == c->screen->seltag)
@ -1003,16 +883,16 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
/* Attach */
SLIST_INSERT_HEAD(&W->h.client, c, next);
ewmh_set_wm_state(w, NormalState);
if(!scan)
{
client_get_name(c);
if(W->flags & WMFS_AUTOFOCUS)
client_focus(c);
client_focus(c);
client_configure(c);
ewmh_manage_window_type(c);
}
ewmh_get_client_list();
return c;
}
@ -1049,7 +929,7 @@ client_update_props(struct client *c, Flags f)
}
}
void
static void
client_geo_hints(struct geo *g, int *s)
{
/* base */
@ -1085,32 +965,29 @@ client_geo_hints(struct geo *g, int *s)
g->h = s[MAXH];
}
/* Manage window size in frame in tiling mode */
bool
client_winsize(struct client *c, struct geo *g)
{
int ow, oh;
struct geo og = c->wgeo;
struct geo tmp = *g;
tmp.w -= W->padding >> 1;
tmp.h -= W->padding >> 1;
/* Window geo */
c->wgeo.x = c->border;
c->wgeo.y = c->tbarw;
c->wgeo.h = oh = tmp.h - (c->border + c->tbarw);
c->wgeo.w = ow = tmp.w - (c->border << 1);
c->wgeo.h = oh = g->h - (c->border + c->tbarw);
c->wgeo.w = ow = g->w - (c->border << 1);
client_geo_hints(&c->wgeo, (int*)c->sizeh);
/* Check possible problem for tile integration */
if(ow < c->sizeh[MINW] || oh < c->sizeh[MINH])
if(tmp.w < c->geo.w || tmp.h < c->geo.h)
{
if(g->w < c->geo.w || g->h < c->geo.h)
{
c->wgeo = og;
return true;
}
}
/* Balance position with new size */
c->wgeo.x += (ow - c->wgeo.w) >> 1;
@ -1120,68 +997,29 @@ client_winsize(struct client *c, struct geo *g)
return false;
}
void
bool
client_moveresize(struct client *c, struct geo *g)
{
bool r = true;
if(c->flags & CLIENT_TABBED)
return;
return false;
/* Adjust frame regarding window required size */
if(c->flags & CLIENT_FREE)
{
g->w -= c->border + c->border;
g->h -= c->tbarw + c->border;
c->ttgeo = c->tgeo = c->rgeo = c->geo = *g;
client_geo_hints(g, (int*)c->sizeh);
c->wgeo = c->geo = c->rgeo = *g;
c->wgeo.x = c->border;
c->wgeo.y = c->tbarw;
c->geo.w = c->rgeo.w = c->wgeo.w + c->border + c->border;
c->geo.h = c->rgeo.h = c->wgeo.h + c->tbarw + c->border;
c->rgeo.x += c->screen->ugeo.x;
c->rgeo.y += c->screen->ugeo.y;
if(!INAREA(c->rgeo.x, c->rgeo.y, c->screen->ugeo))
if(!(c->flags & CLIENT_DID_WINSIZE))
if(client_winsize(c, g))
{
/* New screen (moved by mouse) */
if(c->flags & CLIENT_MOUSE)
{
c->flags |= CLIENT_IGNORE_LAYOUT;
c->screen = screen_gb_geo(c->rgeo.x, c->rgeo.y);
tag_client(c->screen->seltag, c);
c->geo.x = c->rgeo.x - c->screen->ugeo.x;
c->geo.y = c->rgeo.y - c->screen->ugeo.y;
}
/* Out of the screen case */
else
{
c->geo.x = (c->screen->ugeo.w >> 1) - (c->geo.w >> 1);
c->geo.y = (c->screen->ugeo.h >> 1) - (c->geo.h >> 1);
c->rgeo.x = c->screen->ugeo.x + c->geo.x;
c->rgeo.y = c->screen->ugeo.y + c->geo.y;
}
r = false;
/* TODO
* Window required size not compatible
* with frame window size in tile mode
*/
}
}
/* Adjust window regarding required size for frame (tiling) */
else
{
c->ttgeo = c->tgeo = c->rgeo = c->geo = *g;
if(!(c->flags & CLIENT_DID_WINSIZE))
client_winsize(c, g);
c->rgeo.x += c->screen->ugeo.x;
c->rgeo.y += c->screen->ugeo.y;
c->rgeo.x += W->padding >> 2;
c->rgeo.y += W->padding >> 2;
c->rgeo.w -= W->padding >> 1;
c->rgeo.h -= W->padding >> 1;
}
/* Real geo regarding full root size */
c->rgeo.x += c->screen->ugeo.x;
c->rgeo.y += c->screen->ugeo.y;
XMoveResizeWindow(W->dpy, c->frame,
c->rgeo.x, c->rgeo.y,
@ -1197,25 +1035,8 @@ client_moveresize(struct client *c, struct geo *g)
client_frame_update(c, CCOL(c));
client_update_props(c, CPROP_GEO);
client_configure(c);
}
void
client_place_at_mouse(struct client *c)
{
int x, y;
Window w;
int d, u;
XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (uint *)&u);
if(x < c->screen->ugeo.x)
x = 0;
if(y < c->screen->ugeo.y)
y = 0;
c->geo.x = ((x + c->geo.w) > c->screen->ugeo.w ? c->screen->ugeo.w - c->geo.w : x);
c->geo.y = ((y + c->geo.h) > c->screen->ugeo.h ? c->screen->ugeo.h - c->geo.h : y);
return r;
}
void
@ -1262,7 +1083,7 @@ _fac_arrange_row(struct client *c, enum position p, int fac)
struct client *cc;
/* Travel clients to search row parents and apply fac */
FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
SLIST_FOREACH(cc, &c->tag->clients, tnext)
if(GEO_PARENTROW(g, cc->tgeo, p))
_fac_apply(cc, p, fac);
}
@ -1278,7 +1099,7 @@ _fac_check_to_reverse(struct client *c)
* resize client because of possible error with next
* clients in linked list.
*/
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext)
SLIST_FOREACH(gc, &c->tag->clients, tnext)
if(gc->flags & CLIENT_FAC_APPLIED
&& client_winsize(gc, &gc->tgeo))
{
@ -1286,7 +1107,7 @@ _fac_check_to_reverse(struct client *c)
* Reverse back the flag and the window geo
* in previous affected clients
*/
FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
SLIST_FOREACH(cc, &c->tag->clients, tnext)
{
cc->tgeo = cc->ttgeo;
cc->flags &= ~CLIENT_DID_WINSIZE;
@ -1302,10 +1123,10 @@ _fac_resize(struct client *c, enum position p, int fac)
struct client *cc, *gc = client_next_with_pos(c, p);
enum position rp = RPOS(p);
if(!gc || gc->screen != c->screen || !(c->flags & CLIENT_TILED))
if(!gc || gc->screen != c->screen)
return;
FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
SLIST_FOREACH(cc, &c->tag->clients, tnext)
cc->ttgeo = cc->tgeo;
if(GEO_CHECK2(c->tgeo, gc->tgeo, p))
@ -1327,17 +1148,17 @@ client_apply_tgeo(struct tag *t)
{
struct client *c;
FOREACH_NFCLIENT(c, &t->clients, tnext)
SLIST_FOREACH(c, &t->clients, tnext)
{
client_moveresize(c, &c->tgeo);
c->flags &= ~CLIENT_FAC_APPLIED;
}
}
#define _REV_BORDER() \
do { \
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \
#define _REV_BORDER() \
do { \
SLIST_FOREACH(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \
} while(/* CONSTCOND */ 0);
void
client_fac_resize(struct client *c, enum position p, int fac)
@ -1368,7 +1189,7 @@ client_fac_resize(struct client *c, enum position p, int fac)
if(ev.type == KeyPress)
{
XKeyPressedEvent *ke = &ev.xkey;
keysym = XkbKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0, 0);
keysym = XKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0);
_REV_BORDER();
@ -1419,7 +1240,7 @@ client_fac_resize(struct client *c, enum position p, int fac)
/* Aborted with escape, Set back original geos */
else
{
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext)
SLIST_FOREACH(gc, &c->tag->clients, tnext)
{
gc->tgeo = gc->geo;
gc->flags &= ~CLIENT_DID_WINSIZE;
@ -1430,7 +1251,7 @@ client_fac_resize(struct client *c, enum position p, int fac)
XUngrabKeyboard(W->dpy, CurrentTime);
}
void
inline void
client_fac_hint(struct client *c)
{
int w = c->sizeh[MINW] + c->border + c->border;
@ -1454,76 +1275,31 @@ client_remove(struct client *c)
{
c->flags |= CLIENT_DYING;
client_untab(c);
XGrabServer(W->dpy);
XSetErrorHandler(wmfs_error_handler_dummy);
client_map(c);
XReparentWindow(W->dpy, c->win, W->root, c->rgeo.x, c->rgeo.y);
XUngrabButton(W->dpy, AnyButton, AnyModifier, c->win);
ewmh_set_wm_state(c->win, WithdrawnState);
XSync(W->dpy, false);
XSetErrorHandler(wmfs_error_handler);
XUngrabServer(W->dpy);
SLIST_REMOVE(&W->h.client, c, client, next);
tag_client(NULL, c);
client_untab(c);
/* Remove frame */
if(c->titlebar)
barwin_remove(c->titlebar);
XDestroyWindow(W->dpy, c->frame);
if(c->titlebar)
barwin_remove(c->titlebar);
/* Remove from global client list */
SLIST_REMOVE(&W->h.client, c, client, next);
tag_client(NULL, c);
ewmh_set_wm_state(c->win, WithdrawnState);
XUngrabServer(W->dpy);
XSync(W->dpy, False);
XSetErrorHandler(wmfs_error_handler);
free(c);
ewmh_get_client_list();
}
void
uicb_client_toggle_free(Uicb cmd)
{
struct client *c;
(void)cmd;
if(!(W->client))
return;
W->client->flags ^= CLIENT_FREE;
layout_client(W->client);
/* Set tabbed client of toggled client as free */
if(W->client->flags & CLIENT_TABMASTER)
{
SLIST_FOREACH(c, &W->client->tag->clients, tnext)
if(c->tabmaster == W->client && c != W->client)
c->flags ^= CLIENT_FREE;
}
}
void uicb_client_toggle_ignore_tag(Uicb cmd)
{
struct client *c;
(void)cmd;
if(!(W->client))
return;
W->client->flags ^= CLIENT_IGNORE_TAG;
/* Set tabbed client of toggled client as ignore_tag */
if(W->client->flags & CLIENT_TABMASTER)
{
SLIST_FOREACH(c, &W->client->tag->clients, tnext)
if(c->tabmaster == W->client && c != W->client)
c->flags ^= CLIENT_IGNORE_TAG;
}
}
void
uicb_client_tab_next_opened(Uicb cmd)
{
(void)cmd;
W->flags ^= WMFS_TABNOC;
}
void

View File

@ -6,8 +6,6 @@
#ifndef CLIENT_H
#define CLIENT_H
#include <X11/XKBlib.h>
#include "wmfs.h"
#include "layout.h"
#include "ewmh.h"
@ -15,15 +13,7 @@
#define TCLIENT_CHECK(C) (C->flags & CLIENT_TABBED && !(C->flags & CLIENT_TABMASTER))
/* SLIST_FOREACH for client with no free client */
#define FOREACH_NFCLIENT(V, H, F) \
SLIST_FOREACH(V, H, F) \
if(!(V->flags & CLIENT_FREE))
/* Are two clients compatibles ? (to be tabbed together) */
#define COMPCLIENT(C1, C2) ((C1->flags & CLIENT_IGNORE_TAG) == (C2->flags & CLIENT_IGNORE_TAG))
void client_configure(struct client *c);
inline void client_configure(struct client *c);
struct client *client_gb_win(Window w);
struct client *client_gb_frame(Window w);
struct client *client_gb_pos(struct tag *t, int x, int y);
@ -42,11 +32,8 @@ void client_get_name(struct client *c);
void client_close(struct client *c);
void uicb_client_close(Uicb cmd);
struct client *client_new(Window w, XWindowAttributes *wa, bool scan);
void client_geo_hints(struct geo *g, int *s);
void client_get_sizeh(struct client *c);
bool client_winsize(struct client *c, struct geo *geo);
void client_moveresize(struct client *c, struct geo *g);
void client_place_at_mouse(struct client *c);
bool client_moveresize(struct client *c, struct geo *g);
void client_maximize(struct client *c);
void client_fac_resize(struct client *c, enum position p, int fac);
void client_fac_adjust(struct client *c);
@ -61,11 +48,8 @@ void client_apply_tgeo(struct tag *t);
#define CPROP_TAB 0x08
void client_update_props(struct client *c, Flags f);
void client_fac_hint(struct client *c);
inline void client_fac_hint(struct client *c);
void uicb_client_untab(Uicb cmd);
void uicb_client_toggle_free(Uicb cmd);
void uicb_client_toggle_ignore_tag(Uicb cmd);
void uicb_client_tab_next_opened(Uicb cmd);
/* Generated */
void uicb_client_resize_Right(Uicb);
@ -193,25 +177,5 @@ clients_tag_arrange_map(struct tag *t)
sfunc(c);
}
static inline struct client*
client_get_larger(struct tag *t, bool ignoring_tag)
{
struct client *c, *lc = NULL;
int tmp, l = 0;
FOREACH_NFCLIENT(c, &t->clients, tnext)
{
if((tmp = (c->geo.w + c->geo.h)) > l && (c->flags & CLIENT_IGNORE_TAG) == ignoring_tag)
{
l = tmp;
lc = c;
}
}
if(lc && (lc->flags & CLIENT_TABBED))
lc = lc->tabmaster;
return lc;
}
#endif /* CLIENT_H */

View File

@ -10,13 +10,6 @@
#include "screen.h"
#include "infobar.h"
#include "util.h"
#include "status.h"
#define ISTRDUP(t, s) \
do { \
if((tmp = s)) \
t = xstrdup(tmp); \
} while(/* CONSTCOND */ 0);
static void
config_mouse_section(struct mbhead *mousebinds, struct conf_sec **sec)
@ -50,7 +43,6 @@ config_theme(void)
struct theme *t, *p = NULL;
size_t i, n;
struct conf_sec *sec, **ks;
char *tmp;
/* [themes] */
sec = fetch_section_first(NULL, "themes");
@ -83,33 +75,9 @@ config_theme(void)
t->tags_n.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "tags_normal_bg").str);
t->tags_s.fg = color_atoh(fetch_opt_first(ks[i], "#222222", "tags_sel_fg").str);
t->tags_s.bg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_sel_bg").str);
t->tags_o.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_occupied_fg").str);
t->tags_o.bg = color_atoh(fetch_opt_first(ks[i], "#444444", "tags_occupied_bg").str);
t->tags_u.fg = color_atoh(fetch_opt_first(ks[i], "#444444", "tags_urgent_fg").str);
t->tags_u.bg = color_atoh(fetch_opt_first(ks[i], "#CC4444", "tags_urgent_bg").str);
t->tags_border_col = color_atoh(fetch_opt_first(ks[i], "#888888", "tags_border_color").str);
t->tags_border_width = fetch_opt_first(ks[i], "0", "tags_border_width").num;
/* status line */
t->tags_n_sl = status_new_ctx(NULL, t);
t->tags_s_sl = status_new_ctx(NULL, t);
t->tags_o_sl = status_new_ctx(NULL, t);
t->tags_u_sl = status_new_ctx(NULL, t);
ISTRDUP(t->tags_n_sl.status, fetch_opt_first(ks[i], "", "tags_normal_statusline").str);
ISTRDUP(t->tags_s_sl.status, fetch_opt_first(ks[i], "", "tags_sel_statusline").str);
ISTRDUP(t->tags_o_sl.status, fetch_opt_first(ks[i], "", "tags_occupied_statusline").str);
ISTRDUP(t->tags_u_sl.status, fetch_opt_first(ks[i], "", "tags_urgent_statusline").str);
if(t->tags_n_sl.status)
status_parse(&t->tags_n_sl);
if(t->tags_s_sl.status)
status_parse(&t->tags_s_sl);
if(t->tags_o_sl.status)
status_parse(&t->tags_o_sl);
if(t->tags_u_sl.status)
status_parse(&t->tags_u_sl);
/* Client / frame */
t->client_n.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "client_normal_fg").str);
t->client_n.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "client_normal_bg").str);
@ -119,22 +87,6 @@ config_theme(void)
t->client_titlebar_width = fetch_opt_first(ks[i], "12", "client_titlebar_width").num;
t->client_border_width = fetch_opt_first(ks[i], "1", "client_border_width").num;
/* status line */
t->client_n_sl = status_new_ctx(NULL, t);
t->client_s_sl = status_new_ctx(NULL, t);
t->client_f_sl = status_new_ctx(NULL, t);
ISTRDUP(t->client_n_sl.status, fetch_opt_first(ks[i], "", "client_normal_statusline").str);
ISTRDUP(t->client_s_sl.status, fetch_opt_first(ks[i], "", "client_sel_statusline").str);
ISTRDUP(t->client_f_sl.status, fetch_opt_first(ks[i], "", "client_free_statusline").str);
if(t->client_n_sl.status)
status_parse(&t->client_n_sl);
if(t->client_s_sl.status)
status_parse(&t->client_s_sl);
if(t->client_f_sl.status)
status_parse(&t->client_f_sl);
SLIST_INSERT_TAIL(&W->h.theme, t, next, p);
p = t;
@ -181,10 +133,9 @@ static void
config_tag(void)
{
struct screen *s;
struct tag *t;
size_t i, n;
struct conf_sec *sec, **ks, **mb;
char *name, *tmp;
char *name;
int screenid;
/* [tags] */
@ -192,9 +143,6 @@ config_tag(void)
ks = fetch_section(sec, "tag");
n = fetch_section_count(ks);
if (fetch_opt_first(sec, "1", "circular").boolean)
W->flags |= WMFS_TAGCIRC;
/* [mouse] */
if((mb = fetch_section(sec, "mouse")))
{
@ -210,14 +158,7 @@ config_tag(void)
SLIST_FOREACH(s, &W->h.screen, next)
if(screenid == s->id || screenid == -1)
{
t = tag_new(s, name);
t->statusctx = status_new_ctx(NULL, NULL);
ISTRDUP(t->statusctx.status, fetch_opt_first(ks[i], "", "statusline").str);
if(t->statusctx.status)
status_parse(&t->statusctx);
}
tag_new(s, name);
}
/* If no tag at all on a screen, add one anyway */
@ -232,29 +173,10 @@ static void
config_client(void)
{
struct conf_sec *sec, **mb;
char *tmp;
/* [client] */
sec = fetch_section_first(NULL, "client");
W->padding = fetch_opt_first(sec, "0", "padding").num;
W->client_mod = modkey_keysym(fetch_opt_first(sec, "Super", "key_modifier").str);
if(fetch_opt_first(sec, "0", "autofocus").boolean)
W->flags |= WMFS_AUTOFOCUS;
/* Get theme */
tmp = fetch_opt_first(sec, "default", "theme").str;
W->ctheme = name_to_theme(tmp);
/* Get focus configuration */
W->cfocus = 0;
tmp = fetch_opt_first(sec, "enter", "focus").str;
if(strstr(tmp, "enter"))
W->cfocus |= CFOCUS_ENTER;
if(strstr(tmp, "click"))
W->cfocus |= CFOCUS_CLICK;
/* [mouse] */
/* for client frame AND titlebar */
if((mb = fetch_section(sec, "mouse")))
@ -264,12 +186,18 @@ config_client(void)
}
}
#define ISTRDUP(t, s) \
do { \
if((tmp = s)) \
t = xstrdup(tmp); \
} while(/* CONSTCOND */ 0);
static void
config_rule(void)
{
int i, n;
struct conf_sec *sec, **ks;
struct rule *r;
struct theme *t;
char *tn, *tmp;
/* [rules] */
@ -293,13 +221,20 @@ config_rule(void)
r->tag = fetch_opt_first(ks[i], "-1", "tag").num;
FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "free").boolean, RULE_FREE);
FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "tab").boolean, RULE_TAB);
FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "max").boolean, RULE_MAX);
FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "ignore_tag").boolean, RULE_IGNORE_TAG);
if((tn = fetch_opt_first(ks[i], "", "theme").str))
r->theme = name_to_theme(tn);
{
SLIST_FOREACH(t, &W->h.theme, next)
if(!strcmp(tn, t->name))
{
r->theme = t;
break;
}
}
else
r->theme = W->ctheme;
r->theme = SLIST_FIRST(&W->h.theme);
SLIST_INSERT_HEAD(&W->h.rule, r, next);
}
@ -307,38 +242,6 @@ config_rule(void)
free(ks);
}
static void
config_launcher(void)
{
struct conf_sec *sec, **ks;
struct launcher *l;
int n, i;
/* [launchers] */
sec = fetch_section_first(NULL, "launchers");
ks = fetch_section(sec, "launcher");
n = fetch_section_count(ks);
SLIST_INIT(&W->h.launcher);
/* [launcher] */
for(i = 0; i < n; ++i)
{
l = xcalloc(1, sizeof(struct launcher));
l->name = xstrdup(fetch_opt_first(ks[i], "default", "name").str);
l->prompt = xstrdup(fetch_opt_first(ks[i], ":", "prompt").str);
l->command = xstrdup(fetch_opt_first(ks[i], "spawn", "command").str);
if((l->width = fetch_opt_first(ks[i], "150", "width").num) <= 0)
l->width = 150;
SLIST_INSERT_HEAD(&W->h.launcher, l, next);
}
free(ks);
}
static void
config_keybind(void)
{
@ -401,13 +304,7 @@ config_init(void)
sprintf(W->confpath, "%s/"CONFIG_DEFAULT_PATH, getenv("HOME"));
if(get_conf(W->confpath) == -1)
{
warnxl("parsing default configuration file (%s) failed.", W->confpath);
sprintf(W->confpath, "%s/wmfs/wmfsrc", XDG_CONFIG_DIR);
if(get_conf(W->confpath) == -1)
errxl(1, "parsing system configuration file (%s) failed.", W->confpath);
}
errxl(1, "parsing default configuration file (%s) failed.", W->confpath);
}
config_theme();
@ -416,7 +313,6 @@ config_init(void)
config_client();
config_bars();
config_rule();
config_launcher();
free_conf();
}

View File

@ -17,8 +17,6 @@
#include "status.h"
#include "mouse.h"
#include "screen.h"
#include "infobar.h"
#include "launcher.h"
#define THEME_DEFAULT (SLIST_FIRST(&W->h.theme))
@ -35,61 +33,47 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
{ "tag_next", uicb_tag_next },
{ "tag_prev", uicb_tag_prev },
{ "tag_client", uicb_tag_client },
{ "tag_client_and_set", uicb_tag_client_and_set },
{ "tag_move_client_next", uicb_tag_move_client_next },
{ "tag_move_client_prev", uicb_tag_move_client_prev },
{ "tag_click", uicb_tag_click },
{ "tag_new", uicb_tag_new },
{ "tag_del", uicb_tag_del },
/* Layout */
{ "layout_vmirror", uicb_layout_vmirror },
{ "layout_hmirror", uicb_layout_hmirror },
{ "layout_rotate_left", uicb_layout_rotate_left },
{ "layout_rotate_right", uicb_layout_rotate_right },
{ "layout_prev_set", uicb_layout_prev_set },
{ "layout_next_set", uicb_layout_next_set },
{ "layout_integrate_left", uicb_layout_integrate_Left },
{ "layout_integrate_right", uicb_layout_integrate_Right },
{ "layout_integrate_top", uicb_layout_integrate_Top },
{ "layout_integrate_bottom", uicb_layout_integrate_Bottom },
{ "layout_vmirror", uicb_layout_vmirror },
{ "layout_hmirror", uicb_layout_hmirror },
{ "layout_rotate_left", uicb_layout_rotate_left },
{ "layout_rotate_right", uicb_layout_rotate_right },
{ "layout_prev_set", uicb_layout_prev_set },
{ "layout_next_set", uicb_layout_next_set },
/* Client */
{ "client_close", uicb_client_close },
{ "client_resize_right", uicb_client_resize_Right },
{ "client_resize_left", uicb_client_resize_Left },
{ "client_resize_top", uicb_client_resize_Top },
{ "client_resize_bottom", uicb_client_resize_Bottom },
{ "client_focus_right", uicb_client_focus_Right },
{ "client_focus_left", uicb_client_focus_Left },
{ "client_focus_top", uicb_client_focus_Top },
{ "client_focus_bottom", uicb_client_focus_Bottom },
{ "client_tab_right", uicb_client_tab_Right },
{ "client_tab_left", uicb_client_tab_Left },
{ "client_tab_top", uicb_client_tab_Top },
{ "client_tab_bottom", uicb_client_tab_Bottom },
{ "client_swap_right", uicb_client_swap_Right },
{ "client_swap_left", uicb_client_swap_Left },
{ "client_swap_top", uicb_client_swap_Top },
{ "client_swap_bottom", uicb_client_swap_Bottom },
{ "client_focus_next", uicb_client_focus_next },
{ "client_focus_prev", uicb_client_focus_prev },
{ "client_swap_next", uicb_client_swapsel_next },
{ "client_swap_prev", uicb_client_swapsel_prev },
{ "client_untab", uicb_client_untab },
{ "client_focus_next_tab", uicb_client_focus_next_tab },
{ "client_focus_prev_tab", uicb_client_focus_prev_tab },
{ "client_focus_click", uicb_client_focus_click },
{ "client_toggle_free", uicb_client_toggle_free },
{ "client_toggle_ignore_tag", uicb_client_toggle_ignore_tag },
{ "client_tab_next_opened", uicb_client_tab_next_opened },
{ "client_close", uicb_client_close },
{ "client_resize_right", uicb_client_resize_Right },
{ "client_resize_left", uicb_client_resize_Left },
{ "client_resize_top", uicb_client_resize_Top },
{ "client_resize_bottom", uicb_client_resize_Bottom },
{ "client_focus_right", uicb_client_focus_Right },
{ "client_focus_left", uicb_client_focus_Left },
{ "client_focus_top", uicb_client_focus_Top },
{ "client_focus_bottom", uicb_client_focus_Bottom },
{ "client_tab_right", uicb_client_tab_Right },
{ "client_tab_left", uicb_client_tab_Left },
{ "client_tab_top", uicb_client_tab_Top },
{ "client_tab_bottom", uicb_client_tab_Bottom },
{ "client_swap_right", uicb_client_swap_Right },
{ "client_swap_left", uicb_client_swap_Left },
{ "client_swap_top", uicb_client_swap_Top },
{ "client_swap_bottom", uicb_client_swap_Bottom },
{ "client_focus_next", uicb_client_focus_next },
{ "client_focus_prev", uicb_client_focus_prev },
{ "client_swap_next", uicb_client_swapsel_next },
{ "client_swap_prev", uicb_client_swapsel_prev },
{ "client_untab", uicb_client_untab },
{ "client_focus_next_tab", uicb_client_focus_next_tab },
{ "client_focus_prev_tab", uicb_client_focus_prev_tab },
{ "client_focus_click", uicb_client_focus_click },
/* Status */
{ "status" , uicb_status },
{ "status_surface", uicb_status_surface },
/* Infobar */
{ "infobar_toggle_hide", uicb_infobar_toggle_hide },
{ "status" , uicb_status },
/* Mouse */
{ "mouse_resize", uicb_mouse_resize },
@ -103,9 +87,6 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
{ "screen_move_client_next", uicb_screen_move_client_next },
{ "screen_move_client_prev", uicb_screen_move_client_prev },
/* Launcher */
{ "launcher", uicb_launcher },
{ NULL, NULL }
};

View File

@ -10,10 +10,6 @@
#include <string.h>
#include <X11/Xlib.h>
#ifdef HAVE_IMLIB2
#include <Imlib2.h>
#endif /* HAVE_IMLIB2 */
#include "wmfs.h"
#include "config.h"
#include "screen.h"
@ -29,43 +25,12 @@ draw_text(Drawable d, struct theme *t, int x, int y, Color fg, const char *str)
}
static inline void
draw_rect(Drawable d, struct geo *g, Color bg)
draw_rect(Drawable d, struct geo g, Color bg)
{
XSetForeground(W->dpy, W->gc, bg);
XFillRectangle(W->dpy, d, W->gc, g->x, g->y, g->w, g->h);
XFillRectangle(W->dpy, d, W->gc, g.x, g.y, g.w, g.h);
}
#ifdef HAVE_IMLIB2
/*
* Draw image on drawable with g geo
* Require that the image was loaded with draw_image_load()
*/
static inline void
draw_image(Drawable d, struct geo *g)
{
imlib_context_set_drawable(d);
imlib_render_image_on_drawable_at_size(g->x, g->y, g->w, g->h);
imlib_free_image();
}
/*
* Load image, set it in imlib context, and return
* width & height as argument 2 & 3
*/
static inline void
draw_image_load(char *path, int *w, int *h)
{
Imlib_Image image = imlib_load_image(path);
imlib_context_set_image(image);
*w = imlib_image_get_width();
*h = imlib_image_get_height();
}
#endif /* HAVE_IMLIB2 */
/*
* For client use
*/
@ -76,28 +41,24 @@ draw_reversed_rect(Drawable dr, struct client *c, bool t)
struct geo *ug = &c->screen->ugeo;
int i = c->theme->client_border_width;
if(c->flags & CLIENT_FREE)
{
XDrawRectangle(W->dpy, dr, W->rgc,
ug->x + g->x + i,
ug->y + g->y + i,
g->w - (i << 1),
g->h - (i << 1));
}
else
{
XDrawRectangle(W->dpy, dr, W->rgc,
ug->x + g->x + i + (W->padding >> 2),
ug->y + g->y + i + (W->padding >> 2),
g->w - (i << 1) - (W->padding >> 1),
g->h - (i << 1) - (W->padding >> 1));
}
XDrawRectangle(W->dpy, dr, W->rgc,
ug->x + g->x + i,
ug->y + g->y + i,
g->w - (i << 1),
g->h - (i << 1));
}
static inline void
draw_line(Drawable d, int x1, int y1, int x2, int y2)
draw_reversed_cross(Drawable dr, struct geo *g)
{
XDrawLine(W->dpy, d, W->gc, x1, y1, x2, y2);
int x = g->x + W->screen->ugeo.x;
int y = g->y + W->screen->ugeo.y;
XDrawLine(W->dpy, dr, W->rgc,
x, y, x + g->w, y + g->h);
XDrawLine(W->dpy, dr, W->rgc,
x + g->w, y, x, y + g->h);
}
static inline unsigned short

View File

@ -5,32 +5,22 @@
#include "event.h"
#include "ewmh.h"
#include "config.h"
#include "util.h"
#include "wmfs.h"
#include "client.h"
#include "barwin.h"
#include "screen.h"
#include "systray.h"
#include "infobar.h"
#define EVDPY(e) (e)->xany.display
#define MOUSE_DO_BIND(m) \
if(m->button == ev->button) \
if(!m->use_area || (m->use_area && INAREA(ev->x, ev->y, m->area))) \
if(m->func) \
m->func(m->cmd);
static void
event_buttonpress(XEvent *e)
{
XButtonEvent *ev = &e->xbutton;
struct mousebind *m;
struct barwin *b;
struct client *c;
screen_update_sel();
status_flush_surface();
SLIST_FOREACH(b, &W->h.barwin, next)
if(b->win == ev->window)
@ -38,16 +28,13 @@ event_buttonpress(XEvent *e)
W->last_clicked_barwin = b;
SLIST_FOREACH(m, &b->mousebinds, next)
MOUSE_DO_BIND(m);
SLIST_FOREACH(m, &b->statusmousebinds, next)
MOUSE_DO_BIND(m);
if(m->button == ev->button)
if(!m->use_area || (m->use_area && INAREA(ev->x, ev->y, m->area)))
if(m->func)
m->func(m->cmd);
break;
}
if((c = client_gb_win(ev->window)) && c != W->client
&& ev->button == 1 && W->cfocus & CFOCUS_CLICK)
client_focus(c);
}
static void
@ -61,18 +48,12 @@ event_enternotify(XEvent *e)
&& ev->window != W->root)
return;
if(ev->window == W->systray.win || systray_find(ev->window))
return;
if((c = client_gb_win(ev->window))
|| (c = client_gb_frame(ev->window)))
{
if(c->flags & CLIENT_IGNORE_ENTER)
c->flags ^= CLIENT_IGNORE_ENTER;
else if(c->tag->flags & TAG_IGNORE_ENTER)
c->tag->flags ^= TAG_IGNORE_ENTER;
else if(c != W->client && !(c->flags & CLIENT_TABBED)
&& W->cfocus & CFOCUS_ENTER)
else if(c != W->client && !(c->flags & CLIENT_TABBED))
client_focus(c);
}
}
@ -82,70 +63,11 @@ event_clientmessageevent(XEvent *e)
{
XClientMessageEvent *ev = &e->xclient;
struct client *c;
struct _systray *sy;
int type = 0;
while(type < net_last && W->net_atom[type] != ev->message_type)
++type;
/*
* Systray message
* _NET_WM_SYSTRAY_TRAY_OPCODE
*/
if(ev->window == W->systray.win && type == net_system_tray_opcode)
{
if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY)
{
systray_add(ev->data.l[2]);
systray_update();
}
else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS)
{
if((sy = systray_find(ev->data.l[2])))
ewmh_send_message(sy->win, sy->win, "_XEMBED", XEMBED_FOCUS_IN,
XEMBED_FOCUS_CURRENT, 0, 0, 0);
}
}
else if(ev->window == W->root)
{
/* WMFS message */
if(ev->data.l[4])
{
/* Manage _WMFS_FUNCTION && _WMFS_CMD */
if(type == wmfs_function || type == wmfs_cmd)
{
Atom rt;
int d;
long unsigned int len, il;
unsigned char *ret = NULL, *ret_cmd = NULL;
void (*func)(Uicb);
if(XGetWindowProperty(EVDPY(e), W->root, W->net_atom[wmfs_function], 0, 65536,
False, W->net_atom[utf8_string], &rt, &d,
&len, &il, &ret) == Success
&& ret && ((func = uicb_name_func((char*)ret))))
{
if(XGetWindowProperty(EVDPY(e), W->root, W->net_atom[wmfs_cmd], 0, 65536,
False, W->net_atom[utf8_string], &rt, &d,
&len, &il, &ret_cmd) == Success
&& len && ret_cmd)
{
func((Uicb)ret_cmd);
XFree(ret_cmd);
}
else
func(NULL);
XFree(ret);
}
}
}
if(type == net_active_window)
if((sy = systray_find(ev->data.l[0])))
XSetInputFocus(W->dpy, sy->win, RevertToNone, CurrentTime);
}
switch(type)
{
/* _NET_WM_STATE */
@ -173,28 +95,12 @@ event_configureevent(XEvent *e)
if((c = client_gb_win(ev->window)))
{
if(c->flags & CLIENT_FREE)
{
if(ev->value_mask & CWX)
c->geo.x = ev->x;
if(ev->value_mask & CWY)
c->geo.y = ev->y - c->tbarw - c->border - c->border;
if(ev->value_mask & CWWidth)
c->geo.w = ev->width + c->border + c->border;
if(ev->value_mask & CWHeight)
c->geo.h = ev->height + c->tbarw + c->border;
if(ev->value_mask & CWWidth)
_fac_resize(c, Right, ev->width - c->wgeo.w);
if(ev->value_mask & CWHeight)
_fac_resize(c, Bottom, ev->height - c->wgeo.h);
client_moveresize(c, &c->geo);
}
else
{
if(ev->value_mask & CWWidth)
_fac_resize(c, Right, ev->width - c->wgeo.w);
if(ev->value_mask & CWHeight)
_fac_resize(c, Bottom, ev->height - c->wgeo.h);
client_apply_tgeo(c->tag);
}
client_apply_tgeo(c->tag);
}
else
{
@ -215,16 +121,9 @@ event_destroynotify(XEvent *e)
{
XDestroyWindowEvent *ev = &e->xdestroywindow;
struct client *c;
struct _systray *s;
if((c = client_gb_win(ev->window)))
client_remove(c);
else if((s = systray_find(ev->window)))
{
ewmh_set_wm_state(s->win, WithdrawnState);
systray_del(s);
systray_update();
}
}
static void
@ -241,23 +140,14 @@ event_maprequest(XEvent *e)
{
XMapRequestEvent *ev = &e->xmaprequest;
XWindowAttributes at;
struct _systray *s;
/* Which windows to manage */
if(!XGetWindowAttributes(EVDPY(e), ev->window, &at)
|| at.override_redirect
|| ewmh_manage_window_type_desktop(ev->window)
|| ewmh_manage_state_sticky(ev->window))
|| at.override_redirect)
return;
if(!client_gb_win(ev->window))
client_new(ev->window, &at, false);
else if((s = systray_find(ev->window)))
{
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
systray_update();
}
}
static void
@ -274,9 +164,7 @@ static void
event_propertynotify(XEvent *e)
{
XPropertyEvent *ev = &e->xproperty;
XWMHints *h;
struct client *c;
struct _systray *s;
if(ev->state == PropertyDelete)
return;
@ -287,34 +175,26 @@ event_propertynotify(XEvent *e)
{
case XA_WM_TRANSIENT_FOR:
break;
case XA_WM_NORMAL_HINTS:
client_get_sizeh(c);
/* client_get_size_hints(c); */
break;
case XA_WM_HINTS:
if((h = XGetWMHints(EVDPY(e), c->win))
&& (h->flags & XUrgencyHint)
&& c->tag != W->screen->seltag)
/*
XWMHints *h;
if((h = XGetWMHints(EVDPY, c->win)) && (h->flags & XUrgencyHint) && c != sel)
{
c->tag->flags |= TAG_URGENT;
infobar_elem_screen_update(c->screen, ElemTag);
client_urgent(c, True);
XFree(h);
}
*/
break;
default:
if(ev->atom == XA_WM_NAME || ev->atom == W->net_atom[net_wm_name])
client_get_name(c);
break;
}
}
else if((s = systray_find(ev->window)))
{
systray_state(s);
systray_update();
}
}
static void
@ -322,39 +202,19 @@ event_unmapnotify(XEvent *e)
{
XUnmapEvent *ev = &e->xunmap;
struct client *c;
struct _systray *s;
if((c = client_gb_win(ev->window))
&& ev->send_event
&& ev->event == W->root)
{
Atom rt;
unsigned long n, il;
int d;
unsigned char *ret = NULL;
if(XGetWindowProperty(EVDPY(e), c->win, W->net_atom[wm_state], 0, 2,
False, W->net_atom[wm_state], &rt, &d,
&n, &il, &ret) == Success)
if(*ret == NormalState)
client_remove(c);
}
else if((s = systray_find(ev->window)))
{
systray_del(s);
systray_update();
}
if((c = client_gb_win(ev->window)) && ev->send_event)
client_remove(c);
}
static void
event_keypress(XEvent *e)
{
XKeyPressedEvent *ev = &e->xkey;
KeySym keysym = XkbKeycodeToKeysym(EVDPY(e), (KeyCode)ev->keycode, 0, 0);
KeySym keysym = XKeycodeToKeysym(EVDPY(e), (KeyCode)ev->keycode, 0);
struct keybind *k;
screen_update_sel();
status_flush_surface();
SLIST_FOREACH(k, &W->h.keybind, next)
if(k->keysym == keysym && KEYPRESS_MASK(k->mod) == KEYPRESS_MASK(ev->state))
@ -376,36 +236,6 @@ event_expose(XEvent *e)
}
}
static void
event_mapnotify(XEvent *e)
{
XMapEvent *ev = &e->xmap;
struct client *c;
struct _systray *s;
if(ev->window != ev->event && !ev->send_event)
return;
if((c = client_gb_win(ev->window)))
client_map(c);
else if((s = systray_find(ev->window)))
{
ewmh_set_wm_state(s->win, NormalState);
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
}
}
static void
event_selectionclearevent(XEvent *ev)
{
/* Getting selection if lost it */
if(ev->xselectionclear.window == W->systray.win)
systray_acquire();
systray_update();
}
static void
event_dummy(XEvent *e)
{
@ -429,11 +259,12 @@ event_init(void)
event_handle[Expose] = event_expose;
event_handle[FocusIn] = event_focusin;
event_handle[KeyPress] = event_keypress;
event_handle[MapNotify] = event_mapnotify;
/*event_handle[MapNotify] = event_mapnotify;*/
event_handle[MapRequest] = event_maprequest;
event_handle[MappingNotify] = event_mappingnotify;
event_handle[PropertyNotify] = event_propertynotify;
/*event_handle[ReparentNotify] = event_reparentnotify;*/
event_handle[SelectionClear] = event_selectionclearevent;
/*event_handle[SelectionClear] = event_selectionclearevent;*/
event_handle[UnmapNotify] = event_unmapnotify;
}

View File

@ -6,8 +6,6 @@
#ifndef EVENT_H
#define EVENT_H
#include <X11/XKBlib.h>
#include "wmfs.h"
#define MAX_EV 256

View File

@ -22,8 +22,6 @@ ewmh_init(void)
/* EWMH hints */
W->net_atom[wm_state] = ATOM("WM_STATE");
W->net_atom[wm_class] = ATOM("WM_CLASS");
W->net_atom[wm_name] = ATOM("WM_NAME");
W->net_atom[net_supported] = ATOM("_NET_SUPPORTED");
W->net_atom[net_client_list] = ATOM("_NET_CLIENT_LIST");
W->net_atom[net_frame_extents] = ATOM("_NET_FRAME_EXTENTS");
@ -42,7 +40,6 @@ ewmh_init(void)
W->net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK");
W->net_atom[net_wm_window_opacity] = ATOM("_NET_WM_WINDOW_OPACITY");
W->net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
W->net_atom[net_wm_window_type_desktop] = ATOM("_NET_WM_WINDOW_TYPE_DESKTOP");
W->net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
W->net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
W->net_atom[net_wm_window_type_dialog] = ATOM("_NET_WM_WINDOW_TYPE_DIALOG");
@ -51,9 +48,7 @@ ewmh_init(void)
W->net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
W->net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
W->net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
W->net_atom[net_wm_state_hidden] = ATOM("_NET_WM_STATE_HIDDEN");
W->net_atom[net_system_tray_s] = ATOM("_NET_SYSTEM_TRAY_S0");
W->net_atom[net_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
W->net_atom[net_wm_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
W->net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
W->net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
W->net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
@ -84,14 +79,12 @@ ewmh_init(void)
/* Set _NET_SUPPORTING_WM_CHECK */
XChangeProperty(W->dpy, W->root, W->net_atom[net_supporting_wm_check], XA_WINDOW, 32,
PropModeReplace, (unsigned char*)&W->root, 1);
/*
XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
PropModeReplace, (unsigned char*)&rootn, strlen(rootn));
XChangeProperty(W->dpy, W->root, ATOM("WM_CLASS"), XA_STRING, 8,
PropModeReplace, (unsigned char*)&"wmfs", 4);
XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
PropModeReplace, (unsigned char*)&"wmfs2", 5);
/*
PropModeReplace, (unsigned char*)&class, strlen(class));
* Set _NET_WM_PID
XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_pid], XA_CARDINAL, 32,
@ -113,56 +106,6 @@ ewmh_set_wm_state(Window w, int state)
W->net_atom[wm_state], 32, PropModeReplace, d, 2);
}
/*
* _NET_CLIENT_LIST
*/
void
ewmh_get_client_list(void)
{
Window *list;
struct client *c;
int win_n = 0;
SLIST_FOREACH(c, &W->h.client, next)
++win_n;
list = xcalloc(win_n, sizeof(Window));
win_n = 0;
SLIST_FOREACH(c, &W->h.client, next)
list[win_n++] = c->win;
XChangeProperty(W->dpy, W->root, W->net_atom[net_client_list], XA_WINDOW, 32,
PropModeReplace, (unsigned char *)list, win_n);
XFree(list);
}
/*
* Get xembed state
*/
long
ewmh_get_xembed_state(Window win)
{
Atom rf;
int f;
long ret = 0;
unsigned long n, il;
unsigned char *data = NULL;
if(XGetWindowProperty(W->dpy, win, W->net_atom[xembedinfo], 0L, 2, False,
W->net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
return 0;
if(rf == W->net_atom[xembedinfo] && n == 2)
ret = (long)data[1];
if(n && data)
XFree(data);
return ret;
}
void
ewmh_update_wmfs_props(void)
{
@ -175,6 +118,7 @@ ewmh_update_wmfs_props(void)
cts = xcalloc(ns, sizeof(long));
for(i = 0; i < ns; ++i)
{
s = screen_gb_id(i);
@ -195,113 +139,34 @@ void
ewmh_manage_state(long data[], struct client *c)
{
/* _NET_WM_STATE_FULLSCREEN */
if(data[1] == (long)W->net_atom[net_wm_state_fullscreen]
|| data[2] == (long)W->net_atom[net_wm_state_fullscreen])
if(data[1] == (long)W->net_atom[net_wm_state_fullscreen])
{
if(data[0] == _NET_WM_STATE_ADD
|| (data[0] == _NET_WM_STATE_TOGGLE && !(c->flags & CLIENT_FULLSCREEN)))
{
c->flags |= CLIENT_FULLSCREEN;
XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
(unsigned char*)&W->net_atom[net_wm_state_fullscreen], 1);
XReparentWindow(W->dpy, c->win, W->root, c->screen->geo.x, c->screen->geo.y);
XResizeWindow(W->dpy, c->win, c->screen->geo.w, c->screen->geo.h);
XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
(unsigned char*)&W->net_atom[net_wm_state_fullscreen], true);
if(c->tag)
client_focus(c);
client_focus(c);
XRaiseWindow(W->dpy, c->win);
}
else
else if(data[0] == _NET_WM_STATE_REMOVE
|| (data[0] == _NET_WM_STATE_TOGGLE && c->flags & CLIENT_FULLSCREEN))
{
c->flags &= ~CLIENT_FULLSCREEN;
XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
(unsigned char*)0, 0);
XReparentWindow(W->dpy, c->win, c->frame, c->wgeo.x, c->wgeo.y);
XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace,
(unsigned char*)&W->net_atom[net_wm_state_fullscreen], false);
if(c->flags & CLIENT_FREE)
client_moveresize(c, &c->geo);
else
layout_fix_hole(c);
client_moveresize(c, &c->geo);
}
}
}
bool
ewmh_manage_state_sticky(Window win)
{
Atom *atom, rf;
int f;
unsigned long n, il, i;
unsigned char *data = NULL;
bool is_sticky = false;
if(XGetWindowProperty(W->dpy, win, W->net_atom[net_wm_state], 0L, 0x7FFFFFFFL, false,
XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
{
atom = (Atom*)data;
for(i = 0; i < n; ++i)
{
/* manage _NET_WM_STATE_STICKY */
if(atom[i] == W->net_atom[net_wm_state_sticky])
{
XWindowAttributes at;
XMapWindow(W->dpy, win);
XMapSubwindows(W->dpy, win);
if(XGetWindowAttributes(W->dpy, win, &at))
{
struct geo g;
if(at.x < W->screen->ugeo.x)
g.x = W->screen->ugeo.x;
else if((at.x + at.width) > W->screen->ugeo.w)
g.x = W->screen->ugeo.w - at.width;
else
g.x = at.x;
if(at.y < W->screen->ugeo.y)
g.y = W->screen->ugeo.y;
else if((at.y + at.height) > W->screen->ugeo.h)
g.y = W->screen->ugeo.h - at.height;
else
g.y = at.y;
XMoveWindow(W->dpy, win, g.x, g.y);
}
if(W->client)
{
XUngrabButton(W->dpy, AnyButton, AnyModifier, W->client->win);
XGrabButton(W->dpy, AnyButton, AnyModifier, W->client->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
client_frame_update(W->client, &W->client->ncol);
W->client = NULL;
}
XRaiseWindow(W->dpy, win);
XSetInputFocus(W->dpy, win, RevertToPointerRoot, CurrentTime);
XChangeProperty(W->dpy, W->root, W->net_atom[net_active_window], XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&win, 1);
is_sticky = true;
break;
}
}
XFree(data);
}
return is_sticky;
}
void
@ -313,20 +178,6 @@ ewmh_manage_window_type(struct client *c)
unsigned char *data = NULL;
long ldata[5] = { _NET_WM_STATE_ADD };
if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL,
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
{
atom = (Atom*)data;
for(i = 0; i < n; ++i)
{
/* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */
if(atom[i] == W->net_atom[net_wm_window_type_dialog])
c->flags |= CLIENT_FREE;
}
XFree(data);
}
/* _NET_WM_STATE at window mangement */
if(XGetWindowProperty(W->dpy, c->win, W->net_atom[net_wm_state], 0L, 0x7FFFFFFFL, false,
XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
@ -343,36 +194,3 @@ ewmh_manage_window_type(struct client *c)
}
}
bool
ewmh_manage_window_type_desktop(Window win)
{
Atom *atom, rf;
int f;
unsigned long n, il, i;
unsigned char *data = NULL;
bool is_desktop = false;
if(XGetWindowProperty(W->dpy, win, W->net_atom[net_wm_window_type], 0L, 0x7FFFFFFF,
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
{
atom = (Atom*)data;
for(i = 0; i < n; ++i)
{
/* If it is a _NET_WM_WINDOW_TYPE_DESKTOP window */
if(atom[i] == W->net_atom[net_wm_window_type_desktop])
{
/* map it, but don't manage it */
XMapWindow(W->dpy, win);
XMapSubwindows(W->dpy, win);
is_desktop = true;
break;
}
}
XFree(data);
}
return is_desktop;
}

View File

@ -11,37 +11,12 @@
#include <X11/Xutil.h>
#include "wmfs.h"
#include "util.h"
/* EWMH/Xembed const from freedesktop */
#define XEMBED_MAPPED (1 << 0)
#define XEMBED_EMBEDDED_NOTIFY 0
#define XEMBED_WINDOW_ACTIVATE 1
#define XEMBED_WINDOW_DEACTIVATE 2
#define XEMBED_REQUEST_FOCUS 3
#define XEMBED_FOCUS_IN 4
#define XEMBED_FOCUS_OUT 5
#define XEMBED_FOCUS_NEXT 6
#define XEMBED_FOCUS_PREV 7
/* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */
#define XEMBED_MODALITY_ON 10
#define XEMBED_MODALITY_OFF 11
#define XEMBED_REGISTER_ACCELERATOR 12
#define XEMBED_UNREGISTER_ACCELERATOR 13
#define XEMBED_ACTIVATE_ACCELERATOR 14
/* Details for XEMBED_FOCUS_IN: */
#define XEMBED_FOCUS_CURRENT 0
#define XEMBED_FOCUS_FIRST 1
#define XEMBED_FOCUS_LAST 2
/* Ewmh hints list */
enum
{
/* ICCCM */
wm_state,
wm_class,
wm_name,
/* EWMH */
net_supported,
net_wm_name,
@ -60,7 +35,6 @@ enum
net_supporting_wm_check,
net_wm_window_opacity,
net_wm_window_type_normal,
net_wm_window_type_desktop,
net_wm_window_type_dock,
net_wm_window_type_splash,
net_wm_window_type_dialog,
@ -70,8 +44,7 @@ enum
net_wm_state_fullscreen,
net_wm_state_sticky,
net_wm_state_demands_attention,
net_wm_state_hidden,
net_system_tray_opcode,
net_wm_system_tray_opcode,
net_system_tray_message_data,
net_system_tray_s,
net_system_tray_visual,
@ -99,33 +72,10 @@ enum
net_last
};
static inline void
ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4)
{
XClientMessageEvent e;
e.type = ClientMessage;
e.message_type = ATOM(atom);
e.window = w;
e.format = 32;
e.data.l[0] = d0;
e.data.l[1] = d1;
e.data.l[2] = d2;
e.data.l[3] = d3;
e.data.l[4] = d4;
XSendEvent(W->dpy, d, false, StructureNotifyMask, (XEvent*)&e);
XSync(W->dpy, False);
}
void ewmh_init(void);
void ewmh_set_wm_state(Window w, int state);
void ewmh_get_client_list(void);
long ewmh_get_xembed_state(Window win);
void ewmh_update_wmfs_props(void);
void ewmh_manage_state(long data[], struct client *c);
bool ewmh_manage_state_sticky(Window win);
void ewmh_manage_window_type(struct client *c);
bool ewmh_manage_window_type_desktop(Window win);
#endif /* EWMH_H */

73
src/fifo.c Normal file
View File

@ -0,0 +1,73 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* File created by David Delassus.
* For license, see COPYING.
*/
#include <sys/stat.h> /* access */
#include "wmfs.h"
#include "util.h"
#include "config.h"
#include "fifo.h"
static void
fifo_open(void)
{
if(W->fifo.fd)
close(W->fifo.fd);
if(!(W->fifo.fd = open(W->fifo.path, O_RDONLY | O_NDELAY, 0)))
warnxl("Can't open FIFO: %s\n", strerror(errno));
}
void
fifo_init(void)
{
xasprintf(&(W->fifo.path), "%s/wmfs-%s.fifo", P_tmpdir, DisplayString(W->dpy));
/* Check if fifo already exists */
if(access(W->fifo.path, F_OK) != -1)
unlink(W->fifo.path);
if(mkfifo(W->fifo.path, 0644) < 0)
warnxl("Can't create FIFO: %s\n", strerror(errno));
fifo_open();
}
static void
fifo_parse(char *cmd)
{
void (*func)(Uicb);
char *p, *arg = NULL;
/* remove trailing newline */
if((p = strchr(cmd, '\n')))
*p = '\0';
/* If an argument is present, delimit function string */
if((p = strchr(cmd, ' ')))
{
*p = '\0';
arg = p + 1;
}
/* call the UICB function, p + 1 is command or NULL */
if((func = uicb_name_func(cmd)))
func(arg);
XSync(W->dpy, false);
}
void
fifo_read(void)
{
char buf[256] = { 0 };
int ret;
if((ret = read(W->fifo.fd, buf, sizeof(buf) - 1)) > 0)
fifo_parse(buf);
else if(!ret)
fifo_open();
}

View File

@ -10,25 +10,10 @@
#include "util.h"
#include "tag.h"
#include "status.h"
#include "systray.h"
#include "client.h"
#define ELEM_FREE_BARWIN(e) \
while(!SLIST_EMPTY(&e->bars)) \
{ \
b = SLIST_FIRST(&e->bars); \
SLIST_REMOVE_HEAD(&e->bars, enext); \
barwin_remove(b); \
}
static void infobar_elem_tag_init(struct element *e);
static void infobar_elem_tag_update(struct element *e);
static void infobar_elem_status_init(struct element *e);
static void infobar_elem_status_update(struct element *e);
static void infobar_elem_systray_init(struct element *e);
static void infobar_elem_systray_update(struct element *e);
static void infobar_elem_launcher_init(struct element *e);
static void infobar_elem_launcher_update(struct element *e);
const struct elem_funcs
{
@ -37,10 +22,12 @@ const struct elem_funcs
void (*func_update)(struct element *e);
} elem_funcs[] =
{
{ 't', infobar_elem_tag_init, infobar_elem_tag_update },
{ 's', infobar_elem_status_init, infobar_elem_status_update },
{ 'y', infobar_elem_systray_init, infobar_elem_systray_update },
{ 'l', infobar_elem_launcher_init, infobar_elem_launcher_update },
{ 't', infobar_elem_tag_init, infobar_elem_tag_update },
{ 's', infobar_elem_status_init, status_manage },
/* { 'l', infobar_elem_layout_init, infobar_elem_layout_update },
{ 'S', infobar_elem_selbar_init, infobar_elem_selbar_update },
*/
{ '\0', NULL, NULL }
};
@ -61,54 +48,32 @@ infobar_elem_tag_init(struct element *e)
j = e->geo.x;
e->geo.h -= (e->infobar->theme->tags_border_width << 1);
e->statusctx = &e->infobar->theme->tags_n_sl;
e->statusctx->flags |= STATUS_BLOCK_REFRESH;
if(SLIST_EMPTY(&e->bars) || (e->infobar->screen->flags & SCREEN_TAG_UPDATE))
TAILQ_FOREACH(t, &e->infobar->screen->tags, next)
{
if((e->infobar->screen->flags & SCREEN_TAG_UPDATE))
s = draw_textw(e->infobar->theme, t->name) + PAD;
/* Init barwin */
b = barwin_new(e->infobar->bar->win, j, 0, s, e->geo.h, 0, 0, false);
/* Set border */
if(e->infobar->theme->tags_border_width)
{
ELEM_FREE_BARWIN(e);
SLIST_INIT(&e->bars);
XSetWindowBorder(W->dpy, b->win, e->infobar->theme->tags_border_col);
XSetWindowBorderWidth(W->dpy, b->win, e->infobar->theme->tags_border_width);
}
TAILQ_FOREACH(t, &e->infobar->screen->tags, next)
{
s = draw_textw(e->infobar->theme, t->name) + PAD;
b->ptr = (void*)t;
barwin_map(b);
/* Init barwin */
b = barwin_new(e->infobar->bar->win, j, 0, s, e->geo.h, 0, 0, false);
b->mousebinds = W->tmp_head.tag;
/* Status doesn't have theme yet */
t->statusctx.theme = e->infobar->theme;
t->statusctx.flags |= STATUS_BLOCK_REFRESH;
SLIST_INSERT_TAIL(&e->bars, b, enext, prev);
/* Set border */
if(e->infobar->theme->tags_border_width)
{
XSetWindowBorder(W->dpy, b->win, e->infobar->theme->tags_border_col);
XSetWindowBorderWidth(W->dpy, b->win, e->infobar->theme->tags_border_width);
}
b->ptr = (void*)t;
barwin_map(b);
b->mousebinds = W->tmp_head.tag;
SLIST_INSERT_TAIL(&e->bars, b, enext, prev);
prev = b;
j += s;
}
}
else
{
SLIST_FOREACH(b, &e->bars, enext)
{
barwin_move(b, j, 0);
j += b->geo.w;
}
prev = b;
j += s;
}
e->infobar->screen->elemupdate |= FLAGINT(ElemTag);
}
static void
@ -126,44 +91,15 @@ infobar_elem_tag_update(struct element *e)
{
b->fg = e->infobar->theme->tags_s.fg;
b->bg = e->infobar->theme->tags_s.bg;
e->statusctx = &e->infobar->theme->tags_s_sl;
}
else
{
/* Normal tag */
if(SLIST_EMPTY(&t->clients))
{
b->fg = e->infobar->theme->tags_n.fg;
b->bg = e->infobar->theme->tags_n.bg;
e->statusctx = &e->infobar->theme->tags_n_sl;
}
/* Urgent tag */
else if(t->flags & TAG_URGENT)
{
b->fg = e->infobar->theme->tags_u.fg;
b->bg = e->infobar->theme->tags_u.bg;
e->statusctx = &e->infobar->theme->tags_u_sl;
}
/* Occupied tag */
else
{
b->fg = e->infobar->theme->tags_o.fg;
b->bg = e->infobar->theme->tags_o.bg;
e->statusctx = &e->infobar->theme->tags_o_sl;
}
b->fg = e->infobar->theme->tags_n.fg;
b->bg = e->infobar->theme->tags_n.bg;
}
barwin_refresh_color(b);
/* Manage status line */
e->statusctx->barwin = b;
status_copy_mousebind(e->statusctx);
status_render(e->statusctx);
t->statusctx.barwin = b;
status_copy_mousebind(&t->statusctx);
status_render(&t->statusctx);
draw_text(b->dr, e->infobar->theme, (PAD >> 1),
TEXTY(e->infobar->theme, e->geo.h), b->fg, t->name);
@ -181,123 +117,17 @@ infobar_elem_status_init(struct element *e)
e->geo.w = e->infobar->geo.w - e->geo.x - (en ? e->infobar->geo.w - en->geo.x : 0);
if(!(b = SLIST_FIRST(&e->bars)))
{
b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
barwin_refresh_color(b);
SLIST_INSERT_HEAD(&e->bars, b, enext);
e->infobar->statusctx = status_new_ctx(b, e->infobar->theme);
e->infobar->statusctx.status = strdup("wmfs2");
e->infobar->statusctx.update = true;
}
else
{
barwin_move(b, e->geo.x, e->geo.y);
barwin_resize(b, e->geo.w, e->geo.h);
}
b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
b->fg = e->infobar->theme->bars.fg;
b->bg = e->infobar->theme->bars.bg;
barwin_map(b);
}
static void
infobar_elem_status_update(struct element *e)
{
if(e->infobar->statusctx.update)
status_manage(&e->infobar->statusctx);
else
{
status_render(&e->infobar->statusctx);
status_copy_mousebind(&e->infobar->statusctx);
}
}
SLIST_INSERT_HEAD(&e->bars, b, enext);
static void
infobar_elem_systray_init(struct element *e)
{
struct barwin *b;
/* Activate systray mask; no more systray element allowed now */
W->flags |= WMFS_SYSTRAY;
W->systray.infobar = e->infobar;
e->geo.w = systray_get_width();
infobar_elem_placement(e);
if(!(b = SLIST_FIRST(&e->bars)))
{
b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
XFreePixmap(W->dpy, b->dr);
SLIST_INSERT_HEAD(&e->bars, b, enext);
W->systray.barwin = b;
systray_acquire();
}
else
{
barwin_move(b, e->geo.x, e->geo.y);
barwin_resize(b, e->geo.w, e->geo.h);
}
XMoveResizeWindow(W->dpy, W->systray.win, 0, 0, e->geo.w, e->geo.h);
}
static void
infobar_elem_systray_update(struct element *e)
{
(void)e;
systray_update();
}
static void
infobar_elem_launcher_init(struct element *e)
{
struct barwin *b;
if(!(W->flags & WMFS_LAUNCHER))
e->geo.w = 1;
infobar_elem_placement(e);
if(!(b = SLIST_FIRST(&e->bars)))
{
b = barwin_new(e->infobar->bar->win, e->geo.x, 0, e->geo.w, e->geo.h, 0, 0, false);
b->fg = e->infobar->theme->bars.fg;
b->bg = e->infobar->theme->bars.bg;
SLIST_INSERT_HEAD(&e->bars, b, enext);
}
else
{
barwin_move(b, e->geo.x, e->geo.y);
barwin_resize(b, e->geo.w, e->geo.h);
}
barwin_refresh_color(b);
barwin_refresh(b);
}
static void
infobar_elem_launcher_update(struct element *e)
{
struct barwin *b = SLIST_FIRST(&e->bars);
int l;
if(!(W->flags & WMFS_LAUNCHER))
return;
barwin_refresh_color(b);
l = draw_textw(e->infobar->theme, e->data) + 2;
draw_text(b->dr, e->infobar->theme, 1, TEXTY(e->infobar->theme, e->geo.h), b->fg, e->data);
/* Cursor */
XDrawLine(W->dpy, b->dr, W->gc, l, 2, l, e->geo.h - 4);
barwin_refresh(b);
e->infobar->screen->elemupdate |= FLAGINT(ElemStatus);
e->infobar->status = strdup("wmfs2");
}
#define ELEM_INIT(a) \
@ -306,7 +136,6 @@ infobar_elem_launcher_update(struct element *e)
SLIST_INIT(&e->bars); \
e->infobar = i; \
e->type = j; \
e->data = NULL; \
e->align = a; \
e->func_init = elem_funcs[j].func_init; \
e->func_update = elem_funcs[j].func_update; \
@ -330,16 +159,15 @@ infobar_elem_init(struct infobar *i)
break;
}
/* Only one systray element in a wmfs session */
if(i->elemorder[n] == 'y' && W->flags & WMFS_SYSTRAY)
continue;
for(j = 0; j < (int)LEN(elem_funcs); ++j)
if(elem_funcs[j].c == i->elemorder[n])
{
ELEM_INIT(Left);
TAILQ_INSERT_TAIL(&i->elements, e, next);
if(TAILQ_EMPTY(&i->elements))
TAILQ_INSERT_HEAD(&i->elements, e, next);
else
TAILQ_INSERT_TAIL(&i->elements, e, next);
e->func_init(e);
es = e;
@ -355,7 +183,7 @@ infobar_elem_init(struct infobar *i)
for(k = l - 1; k >= n; --k)
{
/* Only one status */
if(i->elemorder[k] == 's' || (i->elemorder[n] == 'y' && W->flags & WMFS_SYSTRAY))
if(i->elemorder[k] == 's')
continue;
for(j = 0; j < (int)LEN(elem_funcs); ++j)
@ -388,49 +216,30 @@ infobar_elem_init(struct infobar *i)
}
void
infobar_elem_update(struct infobar *i, int type)
infobar_elem_update(struct infobar *i)
{
struct element *e;
TAILQ_FOREACH(e, &i->elements, next)
if(type == e->type || type == -1)
if(i->screen->elemupdate & FLAGINT(e->type))
e->func_update(e);
}
void
infobar_elem_reinit(struct infobar *i)
infobar_elem_remove(struct element *e)
{
struct element *e;
struct barwin *b;
barwin_refresh_color(i->bar);
TAILQ_REMOVE(&e->infobar->elements, e, next);
TAILQ_FOREACH(e, &i->elements, next)
while(!SLIST_EMPTY(&e->bars))
{
/* Status element found, scan from the tail now */
if(e->type == ElemStatus)
{
struct element *ee;
TAILQ_FOREACH_REVERSE(ee, &i->elements, esub, next)
{
if(e == ee)
break;
ee->func_init(ee);
ee->func_update(ee);
}
e->func_init(e);
e->func_update(e);
return;
}
e->func_init(e);
e->func_update(e);
b = SLIST_FIRST(&e->bars);
SLIST_REMOVE_HEAD(&e->bars, enext);
barwin_remove(b);
}
barwin_refresh(i->bar);
free(e);
}
struct infobar*
@ -455,6 +264,8 @@ infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos,
/* struct elements */
infobar_elem_init(i);
SLIST_INIT(&i->statushead);
/* Render, only if pos is Top or Bottom */
if(!map)
return i;
@ -470,7 +281,7 @@ infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos,
void
infobar_refresh(struct infobar *i)
{
infobar_elem_update(i, -1);
infobar_elem_update(i);
barwin_refresh(i->bar);
}
@ -479,21 +290,13 @@ void
infobar_remove(struct infobar *i)
{
struct element *e;
struct barwin *b;
free(i->elemorder);
free(i->name);
free(i->status);
if(i == W->systray.infobar)
systray_freeicons();
while(!TAILQ_EMPTY(&i->elements))
{
e = TAILQ_FIRST(&i->elements);
TAILQ_REMOVE(&i->elements, e, next);
ELEM_FREE_BARWIN(e);
free(e);
}
TAILQ_FOREACH(e, &i->elements, next)
infobar_elem_remove(e);
barwin_remove(i->bar);
@ -516,49 +319,8 @@ infobar_free(struct screen *s)
}
}
void
uicb_infobar_toggle_hide(Uicb iname)
{
struct client *c;
struct infobar *i;
if(iname)
i = infobar_gb_name(iname);
else
i = SLIST_FIRST(&W->screen->infobars);
if(i->pos == BarHide)
{
i->pos = i->opos;
if(infobar_placement(i, i->pos))
{
barwin_map(i->bar);
barwin_map_subwin(i->bar);
barwin_refresh_color(i->bar);
infobar_refresh(i);
}
}
else
{
i->opos = i->pos;
i->pos = BarHide;
barwin_unmap_subwin(i->bar);
barwin_unmap(i->bar);
switch(i->opos)
{
case BarTop:
i->screen->ugeo.y -= i->geo.h;
case BarBottom:
i->screen->ugeo.h += i->geo.h;
case BarHide:
default:
break;
}
}
SLIST_FOREACH(c, &W->h.client, next)
layout_fix_hole(c);
}

View File

@ -8,16 +8,16 @@
#include "wmfs.h"
#include "util.h"
#include "draw.h"
#include "tag.h"
enum { ElemTag = 0, ElemStatus, ElemSystray, ElemLauncher, ElemCustom, ElemLast };
enum { ElemTag = 0, ElemStatus, ElemCustom, ElemLast };
struct infobar *infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos, const char *elem);
void infobar_elem_update(struct infobar *i, int type);
void infobar_elem_update(struct infobar *i);
void infobar_refresh(struct infobar *i);
void infobar_remove(struct infobar *i);
void infobar_free(struct screen *s);
void infobar_elem_reinit(struct infobar *i);
/* Basic placement of elements */
static inline void
@ -63,13 +63,16 @@ infobar_placement(struct infobar *i, enum barpos p)
}
static inline void
infobar_elem_screen_update(struct screen *s, int type)
infobar_elem_screen_update(struct screen *s, int addf)
{
struct infobar *i;
SLIST_FOREACH(i, &s->infobars, next)
infobar_elem_update(i, type);
s->elemupdate |= FLAGINT(addf);
SLIST_FOREACH(i, &s->infobars, next)
infobar_elem_update(i);
s->elemupdate &= ~FLAGINT(addf);
}
static inline struct infobar*
@ -88,6 +91,4 @@ infobar_gb_name(const char *name)
return SLIST_FIRST(&s->infobars);
}
void uicb_infobar_toggle_hide(Uicb iname);
#endif /* INFOBAR_H */

View File

@ -1,438 +0,0 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <X11/Xutil.h>
#include "wmfs.h"
#include "event.h"
#include "util.h"
#include "infobar.h"
#include "config.h"
static int
qsort_string_compare(const void * a, const void * b)
{
return (strcmp(*(char **)a, *(char **)b));
}
static char **
complete_on_command(char *start)
{
struct dirent *content;
DIR *dir;
char **paths, *path, *p, **namelist = NULL;
int i, count;
if(!(path = getenv("PATH")) || !start)
return NULL;
/* split PATH into paths */
path = p = xstrdup(path);
for(count = 1, p = path; strchr(p, ':'); ++p, ++count);
paths = xcalloc(count, sizeof(*paths));
for(paths[0] = p = path, count = 1; (p = strchr(p, ':')); ++p, ++count)
{
paths[count] = p + 1;
*p = '\0';
}
paths[count] = NULL;
/* recursively open PATH */
for(i = count = 0; paths[i]; ++i)
{
if(!(dir = opendir(paths[i])))
continue;
while((content = readdir(dir)))
{
if(strncmp(content->d_name, ".", 1)
&& !strncmp(content->d_name, start, strlen(start)))
{
namelist = xrealloc(namelist, ++count, sizeof(*namelist));
namelist[count - 1] = xstrdup(content->d_name + strlen(start));
}
}
closedir(dir);
}
if(count)
{
qsort(namelist, count, sizeof(char *), qsort_string_compare);
namelist = xrealloc(namelist, ++count, sizeof(*namelist));
namelist[count - 1] = NULL;
}
free(paths);
free(path);
return namelist;
}
/*
* Complete a filename or directory name.
* works like complete_on_command.
*/
static char **
complete_on_files(char *start)
{
struct dirent *content = NULL;
struct stat st;
DIR *dir;
char *home, *path, *dirname = NULL;
char **namelist = NULL, *filepath, *p = start;
int count = 0;
/*
* Search the directory to open and set
* the beginning of file to complete on pointer 'p'.
*/
if(*p == '\0' || !strrchr(p, '/'))
path = xstrdup(".");
else
{
if(!(home = getenv("HOME")))
return NULL;
/* remplace ~ by $HOME in dirname */
if(!strncmp(p, "~/", 2) && home)
xasprintf(&dirname, "%s%s", home, p+1);
else
dirname = xstrdup(p);
/* Set p to filename to be complete
* and path the directory containing the file
* /foooooo/baaaaaar/somethinglikethis<tab>
* <---- path - ---><------- p ------>
*/
p = strrchr(dirname, '/');
if(p != dirname)
{
*(p++) = '\0';
path = xstrdup(dirname);
}
else
{
path = xstrdup("/");
p++;
}
}
if((dir = opendir(path)))
{
while((content = readdir(dir)))
{
if(!strcmp(content->d_name, ".")
|| !strcmp(content->d_name, "..")
|| strncmp(content->d_name, p, strlen(p)))
continue;
/* If it's a directory append '/' to the completion */
xasprintf(&filepath, "%s/%s", path, content->d_name);
if(filepath && stat(filepath, &st) != -1)
{
namelist = xrealloc(namelist, ++count, sizeof(*namelist));
if(S_ISDIR(st.st_mode))
xasprintf(&namelist[count - 1], "%s/", content->d_name + strlen(p));
else
namelist[count - 1] = xstrdup(content->d_name + strlen(p));
}
else
warnl("%s", filepath);
free(filepath);
}
closedir(dir);
}
if(count)
{
namelist = xrealloc(namelist, ++count, sizeof(*namelist));
namelist[count - 1] = NULL;
}
free(dirname);
free(path);
return namelist;
}
static void
complete_cache_free(struct launcher_ccache *cache)
{
int i;
/* release memory */
free(cache->start);
if(cache->namelist)
{
for(i = 0; cache->namelist[i]; i++)
free(cache->namelist[i]);
free(cache->namelist);
}
/* init */
cache->hits = 0;
cache->start = NULL;
cache->namelist = NULL;
}
static char *
complete(struct launcher_ccache *cache, char *start)
{
char *p = NULL, *comp = NULL;
if(!start || !cache)
return NULL;
if((p = strrchr(start, ' ')))
p++;
else
p = start;
if(cache->start && !strcmp(cache->start, start))
{
if(cache->namelist && !cache->namelist[cache->hits])
cache->hits = 0;
}
else
{
complete_cache_free(cache);
cache->start = xstrdup(start);
if(p == start)
cache->namelist = complete_on_command(p);
else
cache->namelist = complete_on_files(p);
}
if(cache->namelist && cache->namelist[cache->hits])
comp = cache->namelist[cache->hits];
return comp;
}
#define LAUNCHER_INIT_ELEM(width) \
SLIST_FOREACH(ib, &W->screen->infobars, next) \
{ \
TAILQ_FOREACH(e, &ib->elements, next) \
if(e->type == ElemLauncher) \
{ \
e->geo.w = width; \
e->data = data; \
} \
infobar_elem_reinit(ib); \
}
static void
launcher_process(struct launcher *l)
{
struct infobar *ib;
struct element *e;
struct launcher_ccache cache = {NULL, NULL, 0};
bool loop = true, found = false, lastwastab = false;
char tmpbuf[512] = { 0 }, buf[512] = { 0 };
char tmp[32] = { 0 };
char *p, *data, *arg, *end, *cmd = xstrdup(l->command);
int i, pos = 0, histpos = 0;
void (*func)(Uicb);
XEvent ev;
KeySym ks;
W->flags |= WMFS_LAUNCHER;
/* Prepare elements */
xasprintf(&data, "%s ", l->prompt);
LAUNCHER_INIT_ELEM(l->width);
XGrabKeyboard(W->dpy, W->root, true, GrabModeAsync, GrabModeAsync, CurrentTime);
while(loop)
{
XNextEvent(W->dpy, &ev);
if(ev.type != KeyPress)
{
EVENT_HANDLE(&ev);
continue;
}
/* Get pressed key */
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
/* Check Ctrl-c / Ctrl-d */
if(ev.xkey.state & ControlMask)
{
switch(ks)
{
case XK_c:
case XK_d:
ks = XK_Escape;
break;
case XK_p:
ks = XK_Up;
break;
case XK_n:
ks = XK_Down;
break;
}
}
/* Check if there is a keypad */
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
ks = XK_Return;
/* Manage pressed keys */
switch(ks)
{
case XK_Up:
if(l->nhisto)
{
if(histpos >= (int)l->nhisto)
histpos = 0;
strncpy(buf, l->histo[l->nhisto - ++histpos], sizeof(buf));
pos = strlen(buf);
}
break;
case XK_Down:
if(l->nhisto && histpos > 0 && histpos < (int)l->nhisto)
{
strncpy(buf, l->histo[l->nhisto - --histpos], sizeof(buf));
pos = strlen(buf);
}
break;
case XK_Return:
/* Get function name only, if cmds are added in command */
arg = NULL;
if((p = strchr(cmd, ' ')))
{
*p = '\0';
xasprintf(&arg, "%s %s", p + 1, buf);
}
if((func = uicb_name_func(cmd)))
{
if(arg)
{
func(arg);
free(arg);
}
else
func(buf);
}
/* Histo */
if(l->nhisto + 1 > HISTOLEN)
{
for(i = l->nhisto - 1; i > 1; --i)
strncpy(l->histo[i], l->histo[i - 1], sizeof(l->histo[i]));
l->nhisto = 0;
}
/* Store in histo array */
strncpy(l->histo[l->nhisto++], buf, sizeof(buf));
loop = false;
break;
case XK_Escape:
loop = false;
break;
/* Completion */
case XK_Tab:
buf[pos] = '\0';
if(lastwastab)
++cache.hits;
else
{
cache.hits = 0;
strncpy(tmpbuf, buf, sizeof(tmpbuf));
}
if(pos && (end = complete(&cache, tmpbuf)))
{
strncpy(buf, tmpbuf, sizeof(buf));
strncat(buf, end, sizeof(buf));
found = true;
}
lastwastab = true;
/* start a new round of tabbing */
if(!found)
cache.hits = 0;
pos = strlen(buf);
break;
case XK_BackSpace:
lastwastab = false;
if(pos)
buf[--pos] = '\0';
break;
default:
lastwastab = false;
strncat(buf, tmp, sizeof(tmp));
++pos;
break;
}
free(data);
xasprintf(&data, "%s %s", l->prompt, buf);
/* Update EVERY launcher element of the screen */
SLIST_FOREACH(ib, &W->screen->infobars, next)
{
TAILQ_FOREACH(e, &ib->elements, next)
{
if(e->type != ElemLauncher)
continue;
e->data = data;
e->func_update(e);
}
}
}
XUngrabKeyboard(W->dpy, CurrentTime);
complete_cache_free(&cache);
free(cmd);
free(data);
/* 'Close' launcher elements */
W->flags ^= WMFS_LAUNCHER;
data = NULL;
LAUNCHER_INIT_ELEM(1);
}
void
uicb_launcher(Uicb cmd)
{
struct launcher *l;
if(!cmd)
return;
SLIST_FOREACH(l, &W->h.launcher, next)
if(!strcmp(l->name, cmd))
{
launcher_process(l);
break;
}
}

View File

@ -1,13 +0,0 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#ifndef LAUNCHER_H
#define LAUNCHER_H
#include "wmfs.h"
void uicb_launcher(Uicb cmd);
#endif /* LAUNCHER_H */

View File

@ -4,7 +4,6 @@
*/
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include "layout.h"
#include "config.h"
@ -13,9 +12,6 @@
#include "event.h"
#include "util.h"
/* Shift in client split to keep clients's parent at close arrange */
static int shiftv = 1, shifth = 1;
void
layout_save_set(struct tag *t)
{
@ -27,7 +23,7 @@ layout_save_set(struct tag *t)
l = xcalloc(1, sizeof(struct layout_set));
SLIST_INIT(&l->geos);
FOREACH_NFCLIENT(c, &t->clients, tnext)
SLIST_FOREACH(c, &t->clients, tnext)
{
g = xcalloc(1, sizeof(struct geo_list));
g->geo = c->geo;
@ -53,7 +49,7 @@ layout_apply_set(struct tag *t, struct layout_set *l)
struct client *c;
int nc = 1;
FOREACH_NFCLIENT(c, &t->clients, tnext)
SLIST_FOREACH(c, &t->clients, tnext)
++nc;
/* TODO: Adapt different client number case */
@ -99,9 +95,8 @@ layout_free_set(struct tag *t)
{
struct layout_set *l;
while(!TAILQ_EMPTY(&t->sets))
TAILQ_FOREACH(l, &t->sets, next)
{
l = TAILQ_FIRST(&t->sets);
TAILQ_REMOVE(&t->sets, l, next);
FREE_LIST(geo_list, l->geos);
free(l);
@ -153,7 +148,7 @@ _historic_set(struct tag *t, bool prev)
if(ev.type == KeyPress)
{
XKeyPressedEvent *ke = &ev.xkey;
keysym = XkbKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0, 0);
keysym = XKeycodeToKeysym(W->dpy, (KeyCode)ke->keycode, 0);
_REV_BORDER();
@ -233,26 +228,20 @@ layout_split(struct client *c, bool vertical)
if(vertical)
{
c->geo.w >>= 1;
c->geo.w += shiftv;
geo.x = c->geo.x + c->geo.w;
geo.w >>= 1;
/* Remainder */
geo.w += (og.x + og.w) - (geo.x + geo.w);
shiftv = -shiftv;
}
else
{
c->geo.h >>= 1;
c->geo.h += shifth;
geo.y = c->geo.y + c->geo.h;
geo.h >>= 1;
/* Remainder */
geo.h += (og.y + og.h) - (geo.y + geo.h);
shifth = -shifth;
}
return geo;
@ -286,7 +275,7 @@ layout_split_check_row_dir(struct client *c, struct client *g, enum position p)
struct client *cc;
int s = 0, cs = (LDIR(p) ? g->geo.h : g->geo.w);
FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
SLIST_FOREACH(cc, &c->tag->clients, tnext)
if(GEO_PARENTROW(cgeo, cc->geo, RPOS(p))
&& GEO_CHECK_ROW(cc->geo, g->geo, p))
{
@ -330,8 +319,6 @@ layout_split_arrange_closed(struct client *ghost)
bool b = false;
enum position p;
if(!(ghost->flags & CLIENT_TILED))
return;
/* Search for single parent for easy resize
* Example case:
@ -360,7 +347,7 @@ layout_split_arrange_closed(struct client *ghost)
&& layout_split_check_row_dir(c, ghost, p))
{
g = c->geo;
FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
SLIST_FOREACH(cc, &c->tag->clients, tnext)
if(GEO_PARENTROW(g, cc->geo, RPOS(p))
&& GEO_CHECK_ROW(cc->geo, ghost->geo, p))
{
@ -373,64 +360,26 @@ layout_split_arrange_closed(struct client *ghost)
layout_save_set(ghost->tag);
}
/*
* Integrate a client in split layout:
* - Check if there is no sc
* - Check if sc is on a different tag than c
* - Check if sc is not in free mode
*
* So from there, sc is not compatible, so we will integrate
* c in the larger tiled client of c tag:
* - Check if the larger client is correct
*
* Checks all failed? Get first tiled client of the tag to integrate in.
* Still no client, it means that c is the first tiled client of the tag, then maximize it.
*/
/* Integrate a client in split layout: split sc and fill c in new geo */
void
layout_split_integrate(struct client *c, struct client *sc)
{
struct geo g;
bool f = false;
/* No sc or not compatible, get the largest of the tag */
if(!sc
|| sc == c
|| sc->tag != c->tag
|| (sc->flags & CLIENT_FREE)
|| !COMPCLIENT(c, sc))
sc = client_get_larger(c->tag, c->flags & CLIENT_IGNORE_TAG);
/* Largest not correct */
if(!sc || sc == c)
/* No sc */
if(!sc || sc == c || sc->tag != c->tag)
{
FOREACH_NFCLIENT(sc, &c->tag->clients, tnext)
if(sc != c && !(sc->flags & CLIENT_TABBED))
{
f = true;
break;
}
/* Ok there is no client to integrate in */
if(!f)
/*
* Not even a first client in list, then
* maximize the lonely client
*/
if(!(sc = SLIST_NEXT(SLIST_FIRST(&c->tag->clients), tnext)))
{
client_maximize(c);
c->flags |= CLIENT_TILED;
W->flags &= ~WMFS_TABNOC;
return;
}
}
/* Tab Next Opened Client option */
if(W->flags & WMFS_TABNOC && COMPCLIENT(c, sc))
{
W->flags ^= WMFS_TABNOC;
_client_tab(c, sc);
return;
}
/* If there are clients but we can tab with them, split the screen. */
c->flags |= CLIENT_TILED;
g = layout_split(sc, (sc->geo.h < sc->geo.w));
client_moveresize(c, &g);
@ -440,7 +389,6 @@ layout_split_integrate(struct client *c, struct client *sc)
client_fac_hint(sc);
layout_save_set(c->tag);
W->flags &= ~WMFS_TABNOC;
}
/* Arrange inter-clients holes:
@ -459,7 +407,7 @@ layout_split_integrate(struct client *c, struct client *sc)
* |_____|----'| -> |_____|__v__|
* ^^^ void
*/
void
inline void
layout_fix_hole(struct client *c)
{
struct client *cr = client_next_with_pos(c, Right);
@ -512,7 +460,7 @@ layout_rotate(struct tag *t, void (*pfunc)(struct geo*, struct geo*, struct geo*
float f1 = (float)t->screen->ugeo.w / (float)t->screen->ugeo.h;
float f2 = 1 / f1;
FOREACH_NFCLIENT(c, &t->clients, tnext)
SLIST_FOREACH(c, &t->clients, tnext)
{
pfunc(&g, ug, &c->geo);
@ -526,7 +474,7 @@ layout_rotate(struct tag *t, void (*pfunc)(struct geo*, struct geo*, struct geo*
}
/* Rotate sometimes do not set back perfect size.. */
FOREACH_NFCLIENT(c, &t->clients, tnext)
SLIST_FOREACH(c, &t->clients, tnext)
layout_fix_hole(c);
layout_save_set(t);
@ -570,7 +518,7 @@ uicb_layout_vmirror(Uicb cmd)
(void)cmd;
struct client *c;
FOREACH_NFCLIENT(c, &W->screen->seltag->clients, tnext)
SLIST_FOREACH(c, &W->screen->seltag->clients, tnext)
{
c->geo.x = W->screen->ugeo.w - (c->geo.x + c->geo.w);
client_moveresize(c, &c->geo);
@ -585,7 +533,7 @@ uicb_layout_hmirror(Uicb cmd)
(void)cmd;
struct client *c;
FOREACH_NFCLIENT(c, &W->screen->seltag->clients, tnext)
SLIST_FOREACH(c, &W->screen->seltag->clients, tnext)
{
c->geo.y = W->screen->ugeo.h - (c->geo.y + c->geo.h);
client_moveresize(c, &c->geo);
@ -593,52 +541,3 @@ uicb_layout_hmirror(Uicb cmd)
layout_save_set(W->screen->seltag);
}
#define LAYOUT_INTEGRATE_DIR(D) \
void uicb_layout_integrate_##D(Uicb cmd) \
{ \
(void)cmd; \
if(W->client) \
layout_integrate(W->client, D); \
}
static void
layout_integrate(struct client *c, enum position p)
{
struct client *n;
struct client ghost = *c;
if(!(c->flags & CLIENT_TILED))
return;
if((n = client_next_with_pos(c, p))
&& (n->flags & CLIENT_TILED))
{
layout_split_integrate(c, n);
layout_split_arrange_closed(&ghost);
}
}
LAYOUT_INTEGRATE_DIR(Left);
LAYOUT_INTEGRATE_DIR(Right);
LAYOUT_INTEGRATE_DIR(Top);
LAYOUT_INTEGRATE_DIR(Bottom);
void
layout_client(struct client *c)
{
if(c->flags & (CLIENT_IGNORE_LAYOUT | CLIENT_FULLSCREEN))
{
c->flags &= ~CLIENT_IGNORE_LAYOUT;
return;
}
if(c->flags & CLIENT_FREE)
{
layout_split_arrange_closed(c);
c->flags ^= CLIENT_TILED;
client_moveresize(c, &c->geo);
XRaiseWindow(W->dpy, c->frame);
}
else if(!(c->flags & CLIENT_TABBED))
layout_split_integrate(c, c->tag->sel);
}

View File

@ -7,7 +7,6 @@
#define LAYOUT_H
#include "wmfs.h"
#include "client.h"
/* Check lateral direction (if p is Right or Left) */
#define LDIR(P) (P < Top)
@ -34,8 +33,7 @@ void layout_save_set(struct tag *t);
void layout_free_set(struct tag *t);
void layout_split_integrate(struct client *c, struct client *sc);
void layout_split_arrange_closed(struct client *ghost);
void layout_fix_hole(struct client *c);
void layout_client(struct client *c);
inline void layout_fix_hole(struct client *c);
void uicb_layout_vmirror(Uicb cmd);
void uicb_layout_hmirror(Uicb cmd);
void uicb_layout_rotate_left(Uicb cmd);
@ -43,12 +41,5 @@ void uicb_layout_rotate_right(Uicb cmd);
void uicb_layout_prev_set(Uicb cmd);
void uicb_layout_next_set(Uicb cmd);
/* Generated */
void uicb_layout_integrate_Left(Uicb);
void uicb_layout_integrate_Right(Uicb);
void uicb_layout_integrate_Top(Uicb);
void uicb_layout_integrate_Bottom(Uicb);
#endif /* LAYOUT_H */

View File

@ -9,14 +9,11 @@
#include "client.h"
#include "draw.h"
#define _REV_SBORDER(c) draw_reversed_rect(W->root, c, false);
#define _REV_BORDER() \
do { \
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \
#define _REV_BORDER() \
do { \
SLIST_FOREACH(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \
} while(/* CONSTCOND */ 0);
static void
mouse_resize(struct client *c)
{
@ -24,17 +21,11 @@ mouse_resize(struct client *c)
XEvent ev;
Window w;
int d, u, ox, oy, ix, iy;
int mx, my;
XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (unsigned int *)&u);
XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u);
XGrabServer(W->dpy);
if(c->flags & CLIENT_FREE)
{
_REV_SBORDER(c);
}
else
_REV_BORDER();
_REV_BORDER();
if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER))
c = c->tabmaster;
@ -42,8 +33,6 @@ mouse_resize(struct client *c)
ix = ox;
iy = oy;
c->flags |= CLIENT_MOUSE;
do
{
XMaskEvent(W->dpy, MouseMask | SubstructureRedirectMask, &ev);
@ -51,68 +40,31 @@ mouse_resize(struct client *c)
if(ev.type != MotionNotify)
continue;
mx = ev.xmotion.x_root;
my = ev.xmotion.y_root;
_REV_BORDER();
if(c->flags & CLIENT_FREE)
{
_REV_SBORDER(c);
mx -= c->screen->ugeo.x;
my -= c->screen->ugeo.y;
c->geo.w = ((mx - c->geo.x <= c->sizeh[MINW] + c->border + c->border)
? c->sizeh[MINW] + c->border + c->border
: mx - c->geo.x);
c->geo.h = ((my - c->geo.y <= (c->sizeh[MINH] + c->tbarw + c->border))
? c->sizeh[MINH] + c->tbarw + c->border
: my - c->geo.y);
client_geo_hints(&c->geo, (int*)c->sizeh);
/* For border preview cohesion */
c->geo.h += c->tbarw + c->border;
c->geo.w += c->border + c->border;
_REV_SBORDER(c);
}
if(ix >= c->geo.x + (c->geo.w >> 1))
_fac_resize(c, Right, ev.xmotion.x_root - ox);
else
{
_REV_BORDER();
_fac_resize(c, Left, ox - ev.xmotion.x_root);
if(ix >= c->rgeo.x + (c->geo.w >> 1))
_fac_resize(c, Right, mx - ox);
else
_fac_resize(c, Left, ox - mx);
if(iy >= c->geo.y + (c->geo.h >> 1))
_fac_resize(c, Bottom, ev.xmotion.y_root - oy);
else
_fac_resize(c, Top, oy - ev.xmotion.y_root);
if(iy >= c->rgeo.y + (c->geo.h >> 1))
_fac_resize(c, Bottom, my - oy);
else
_fac_resize(c, Top, oy - my);
ox = ev.xmotion.x_root;
oy = ev.xmotion.y_root;
ox = mx;
oy = my;
_REV_BORDER();
}
_REV_BORDER();
XSync(W->dpy, false);
} while(ev.type != ButtonRelease);
if(c->flags & CLIENT_FREE)
{
_REV_SBORDER(c);
client_moveresize(c, &c->geo);
}
else
{
_REV_BORDER();
client_apply_tgeo(c->tag);
layout_save_set(c->tag);
}
_REV_BORDER();
c->flags &= ~CLIENT_MOUSE;
client_apply_tgeo(c->tag);
layout_save_set(c->tag);
XUngrabServer(W->dpy);
}
@ -136,6 +88,7 @@ mouse_drag_tag(struct client *c, Window w)
return NULL;
}
#define _REV_SBORDER(c) draw_reversed_rect(W->root, c, false);
void
mouse_move(struct client *c, void (*func)(struct client*, struct client*))
{
@ -143,21 +96,13 @@ mouse_move(struct client *c, void (*func)(struct client*, struct client*))
struct tag *t = NULL;
XEvent ev;
Window w;
int d, u, ox, oy;
int ocx, ocy;
ocx = c->geo.x;
ocy = c->geo.y;
int d, u;
if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER))
c = c->tabmaster;
XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u);
_REV_SBORDER(c);
c->flags |= CLIENT_MOUSE;
do
{
XMaskEvent(W->dpy, MouseMask | SubstructureRedirectMask, &ev);
@ -165,33 +110,23 @@ mouse_move(struct client *c, void (*func)(struct client*, struct client*))
if(ev.type != MotionNotify)
continue;
if(!func && c->flags & CLIENT_FREE)
XQueryPointer(W->dpy, W->root, &w, &w, &d, &d, &d, &d, (uint *)&u);
if(!(c2 = client_gb_win(w)))
if(!(c2 = client_gb_frame(w)))
c2 = client_gb_titlebar(w);
if(c2)
{
_REV_SBORDER(c);
c->geo.x = (ocx + (ev.xmotion.x_root - ox));
c->geo.y = (ocy + (ev.xmotion.y_root - oy));
_REV_SBORDER(c);
if(c2 != last)
{
_REV_SBORDER(last);
_REV_SBORDER(c2);
last = c2;
}
}
else
{
c2 = NULL;
XQueryPointer(W->dpy, W->root, &w, &w, &d, &d, &d, &d, (uint *)&u);
if((c2 = client_gb_win(w)) || (c2 = client_gb_frame(w)) || (c2 = client_gb_titlebar(w)))
{
if(c2 != last)
{
_REV_SBORDER(last);
_REV_SBORDER(c2);
last = c2;
}
}
else
t = mouse_drag_tag(c, w);
}
t = mouse_drag_tag(c, w);
XSync(W->dpy, false);
@ -202,15 +137,7 @@ mouse_move(struct client *c, void (*func)(struct client*, struct client*))
else if(t && t != (struct tag*)c)
tag_client(t, c);
else
{
_REV_SBORDER(c);
/* No func mean free client resize */
if(!func)
client_moveresize(c, &c->geo);
}
c->flags &= ~CLIENT_MOUSE;
}
void
@ -228,7 +155,7 @@ uicb_mouse_move(Uicb cmd)
(void)cmd;
if(W->client && mouse_check_client(W->client))
mouse_move(W->client, (W->client->flags & CLIENT_FREE ? NULL : client_swap2));
mouse_move(W->client, client_swap2);
}
void
@ -238,5 +165,4 @@ uicb_mouse_tab(Uicb cmd)
if(W->client && mouse_check_client(W->client))
mouse_move(W->client, _client_tab);
}

View File

@ -42,7 +42,7 @@ string_to_opt(char *s)
ret.fnum = strtod(s, NULL);
ret.boolean = (!strcmp(s, "true")
|| !strcmp(s, "True")
|| !strcmp(s, "true")
|| !strcmp(s, "TRUE")
|| !strcmp(s, "1"));

View File

@ -21,7 +21,6 @@ screen_new(struct geo *g, int id)
s->geo = s->ugeo = *g;
s->seltag = NULL;
s->id = id;
s->flags = 0;
TAILQ_INIT(&s->tags);
SLIST_INIT(&s->infobars);
@ -102,10 +101,10 @@ screen_select(struct screen *s)
void
uicb_screen_next(Uicb cmd)
{
struct screen *s = SLIST_NEXT(W->screen, next);
struct screen *s;
(void)cmd;
if(!s)
if(!(s = SLIST_NEXT(W->screen, next)))
s = SLIST_FIRST(&W->h.screen);
screen_select(s);
@ -114,39 +113,51 @@ uicb_screen_next(Uicb cmd)
void
uicb_screen_prev(Uicb cmd)
{
struct screen *s = SLIST_FIRST(&W->h.screen);
struct screen *s;
(void)cmd;
while(SLIST_NEXT(s, next) && SLIST_NEXT(s, next) != s)
s = SLIST_NEXT(s, next);
SLIST_FOREACH(s, &W->h.screen, next)
if(SLIST_NEXT(W->screen, next) == s)
{
screen_select(s);
return;
}
screen_select(s);
screen_select(SLIST_FIRST(&W->h.screen));
}
static void
screen_move_client(struct client *c, struct screen *s)
{
tag_client(s->seltag, c);
}
void
uicb_screen_move_client_next(Uicb cmd)
{
struct screen *s = SLIST_NEXT(W->screen, next);
struct screen *s;
(void)cmd;
if(!s)
if(!(s = SLIST_NEXT(W->screen, next)))
s = SLIST_FIRST(&W->h.screen);
if(W->client)
tag_client(s->seltag, W->client);
screen_move_client(W->client, s);
}
void
uicb_screen_move_client_prev(Uicb cmd)
{
struct screen *s = SLIST_FIRST(&W->h.screen);
struct screen *s;
(void)cmd;
while(SLIST_NEXT(s, next) && SLIST_NEXT(s, next) != s)
s = SLIST_NEXT(s, next);
SLIST_FOREACH(s, &W->h.screen, next)
if(SLIST_NEXT(W->screen, next) == s)
{
screen_move_client(W->client, s);
return;
}
if(W->client)
tag_client(s->seltag, W->client);
screen_move_client(W->client, SLIST_FIRST(&W->h.screen));
}
void

View File

@ -21,27 +21,23 @@ screen_gb_id(int id)
return SLIST_FIRST(&W->h.screen);
}
static inline struct screen*
screen_gb_geo(int x, int y)
{
struct screen *s;
SLIST_FOREACH(s, &W->h.screen, next)
if(INAREA(x, y, s->geo))
return s;
return SLIST_FIRST(&W->h.screen);
}
static inline struct screen*
screen_gb_mouse(void)
{
struct screen *s;
Window w;
int d, x, y;
XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (unsigned int *)&d);
return screen_gb_geo(x, y);
SLIST_FOREACH(s, &W->h.screen, next)
if(INAREA(x, y, s->geo))
break;
if(!s)
s = SLIST_FIRST(&W->h.screen);
return s;
}
void screen_init(void);

View File

@ -8,11 +8,10 @@
#include "config.h"
#include "infobar.h"
#include "util.h"
#include "draw.h"
#include <string.h>
struct status_seq*
static struct status_seq*
status_new_seq(char type, int narg, int minarg, char *args[], int *shift)
{
struct status_seq *sq = xcalloc(1, sizeof(struct status_seq));
@ -34,124 +33,17 @@ status_new_seq(char type, int narg, int minarg, char *args[], int *shift)
return sq;
}
struct status_ctx
status_new_ctx(struct barwin *b, struct theme *t)
{
struct status_ctx ctx = { .barwin = b, .theme = t };
SLIST_INIT(&ctx.statushead);
SLIST_INIT(&ctx.gcache);
return ctx;
}
static void
status_gcache_free(struct status_ctx *ctx)
{
struct status_gcache *gc;
while(!SLIST_EMPTY(&ctx->gcache))
{
gc = SLIST_FIRST(&ctx->gcache);
SLIST_REMOVE_HEAD(&ctx->gcache, next);
free(gc->datas);
free(gc->name);
free(gc);
}
}
void
status_free_ctx(struct status_ctx *ctx)
{
free(ctx->status);
status_flush_list(ctx);
status_gcache_free(ctx);
}
static void
status_graph_draw(struct status_ctx *ctx, struct status_seq *sq, struct status_gcache *gc)
{
int max = 0;
int i, j, y;
float c;
int ys = sq->geo.y + sq->geo.h - 1;
/* If invalid maximum, we have to compute it ourselves */
if(sq->data[2] <= 0)
{
for(i = sq->geo.x + sq->geo.w - 1, j = gc->ndata - 1;
j >= 0 && i >= sq->geo.x;
--j, --i)
{
if(gc->datas[j] > max)
max = gc->datas[j];
}
}
else
max = sq->data[2];
XSetForeground(W->dpy, W->gc, sq->color2);
for(i = sq->geo.x + sq->geo.w - 1, j = gc->ndata - 1;
j >= 0 && i >= sq->geo.x;
--j, --i)
{
/* You divided by zero didn't you? */
if(gc->datas[j])
{
c = (float)max / (float)gc->datas[j];
y = ys - (sq->geo.h / (c > 1 ? c : 1)) + 1;
draw_line(ctx->barwin->dr, i, y, i, ys);
}
}
}
static void
status_graph_process(struct status_ctx *ctx, struct status_seq *sq, char *name)
{
int j;
struct status_gcache *gc;
/* Graph already exist and have a cache */
SLIST_FOREACH(gc, &ctx->gcache, next)
if(!strcmp(name, gc->name))
{
/* shift buffer to remove unused old value */
if(gc->ndata > (sq->geo.w << 1))
for(gc->ndata /= 2, j = 0;
j < gc->ndata;
gc->datas[j] = gc->datas[j + gc->ndata], ++j);
gc->datas[gc->ndata++] = sq->data[1];
status_graph_draw(ctx, sq, gc);
return;
}
if(sq->data[1] > sq->data[2])
sq->data[1] = sq->data[2];
/* No? Make a cache for it */
gc = xcalloc(1, sizeof(struct status_gcache));
gc->name = xstrdup(name);
gc->ndata = 1;
gc->datas = xcalloc(sq->geo.w << 2, sizeof(int));
gc->datas[0] = sq->data[1];
SLIST_INSERT_HEAD(&ctx->gcache, gc, next);
status_graph_draw(ctx, sq, gc);
}
/* Parse mousebind sequence next normal sequence: \<seq>[](button;func;cmd) */
static char*
status_parse_mouse(struct status_seq *sq, char *str)
status_parse_mouse(struct status_seq *sq, struct element *e, char *str)
{
struct mousebind *m;
struct barwin *b = SLIST_FIRST(&e->bars);
char *end, *arg[3] = { NULL };
int i;
if(*str != '(' || !(end = strchr(str, ')')))
return str;
return str + 1;
i = parse_args(++str, ';', ')', 3, arg);
@ -162,6 +54,7 @@ status_parse_mouse(struct status_seq *sq, char *str)
m->func = uicb_name_func(arg[1]);
m->cmd = (i > 1 ? xstrdup(arg[2]) : NULL);
SLIST_INSERT_HEAD(&b->mousebinds, m, next);
SLIST_INSERT_HEAD(&sq->mousebinds, m, snext);
return end + 1;
@ -173,28 +66,23 @@ status_parse_mouse(struct status_seq *sq, char *str)
str = end + 2; \
continue; \
}
void
status_parse(struct status_ctx *ctx)
static void
status_parse(struct element *e)
{
struct status_seq *sq, *prev = NULL;
int i, tmp, shift = 0;
char *dstr = xstrdup(ctx->status), *sauv = dstr;
char type, *p, *pp, *end, *arg[10] = { NULL };
int i, shift = 0;
char *dstr = xstrdup(e->infobar->status), *sauv = dstr;
char type, *p, *end, *arg[6] = { NULL };
for(; *dstr; ++dstr)
{
/* Check if this is a sequence */
if(*dstr != '^' && *dstr != '\\')
if(*dstr != '\\')
continue;
p = ++dstr;
/* Search for correct end of sequence (] without \ behind) */
if((end = strchr(p, ']')))
while(*(end - 1) == '\\')
end = strchr(end + 1, ']');
if(!(strchr("sRpPig", *p)) || !end)
if(!(strchr("sR", *p)) || !(end = strchr(p, ']')))
continue;
/* Then parse & list it */
@ -211,10 +99,6 @@ status_parse(struct status_ctx *ctx)
sq->color = color_atoh(arg[1 + shift]);
sq->str = xstrdup(arg[2 + shift]);
/* Remove \ from string */
for(pp = sq->str; (pp = strchr(sq->str, '\\'));)
memmove(pp, pp + 1, strlen(pp));
break;
/*
@ -230,83 +114,16 @@ status_parse(struct status_ctx *ctx)
sq->color = color_atoh(arg[3 + shift]);
break;
/*
* Progress bar sequence: \p[left/right;w;h;bord;val;valmax;bg;fg] OR x;y
* Position bar sequence: \P[left/right;w;h;tickbord;val;valmax;bg;fg] OR x;y
*/
case 'p':
case 'P':
i = parse_args(p + 2, ';', ']', 9, arg);
STATUS_CHECK_ARGS(i, 7, 8, dstr, end);
sq = status_new_seq(type, i, 7, arg, &shift);
sq->geo.w = ATOI(arg[1 + shift]);
sq->geo.h = ATOI(arg[2 + shift]);
sq->data[0] = ATOI(arg[3 + shift]); /* Border */
sq->data[1] = ((tmp = ATOI(arg[4 + shift])) ? tmp : 1); /* Value */
sq->data[2] = ATOI(arg[5 + shift]); /* Value Max */
sq->color = color_atoh(arg[6 + shift]);
sq->color2 = color_atoh(arg[7 + shift]);
break;
/*
* Graph sequence: \g[left/right;w;h;val;valmax;bg;fg;name] OR x;y
*/
case 'g':
i = parse_args(p + 2, ';', ']', 9, arg);
STATUS_CHECK_ARGS(i, 7, 8, dstr, end);
sq = status_new_seq(type, i, 7, arg, &shift);
sq->geo.w = ATOI(arg[1 + shift]);
sq->geo.h = ATOI(arg[2 + shift]);
sq->data[1] = ATOI(arg[3 + shift]); /* Value */
sq->data[2] = ATOI(arg[4 + shift]); /* Value Max */
sq->color = color_atoh(arg[5 + shift]);
sq->color2 = color_atoh(arg[6 + shift]);
sq->str = xstrdup(arg[7 + shift]);
break;
/*
* Image sequence: \i[left/right;w;h;/path/img] OR \i[x;y;w;h;/path/img]
*/
#ifdef HAVE_IMLIB2
case 'i':
i = parse_args(p + 2, ';', ']', 5, arg);
STATUS_CHECK_ARGS(i, 3, 4, dstr, end);
sq = status_new_seq(type, i, 3, arg, &shift);
sq->geo.w = ATOI(arg[1 + shift]);
sq->geo.h = ATOI(arg[2 + shift]);
sq->str = xstrdup(arg[3 + shift]);
break;
#endif /* HAVE_IMLIB2 */
}
if(sq->align == Right)
SLIST_INSERT_HEAD(&ctx->statushead, sq, next);
else
SLIST_INSERT_TAIL(&ctx->statushead, sq, next, prev);
SLIST_INSERT_TAIL(&e->infobar->statushead, sq, next, prev);
/*
* Optional mousebind sequence(s) \<seq>[](button;func;cmd)
* Parse it while there is a mousebind sequence.
*/
dstr = end + 1;
do
dstr = status_parse_mouse(sq, dstr);
while(*dstr == '(');
--dstr;
dstr = ++end;
while((*(dstr = status_parse_mouse(sq, e, dstr)) == '('));
prev = sq;
}
@ -314,49 +131,40 @@ status_parse(struct status_ctx *ctx)
free(sauv);
}
#define STATUS_ALIGN(align) \
if(align == Left) \
{ \
sq->geo.x = left; \
left += sq->geo.w; \
} \
else if(align == Right) \
{ \
sq->geo.x = ctx->barwin->geo.w - right - sq->geo.w; \
right += sq->geo.w; \
#define STATUS_ALIGN(align) \
if(align == Left) \
{ \
sq->geo.x = left; \
left += sq->geo.w; \
} \
else if(align == Right) \
{ \
sq->geo.x = e->geo.w - right - sq->geo.w; \
right += sq->geo.w; \
}
#define STORE_MOUSEBIND() \
if(!SLIST_EMPTY(&sq->mousebinds)) \
SLIST_FOREACH(m, &sq->mousebinds, snext) \
m->area = sq->geo;
#define NOALIGN_Y() \
if(sq->align != NoAlign) \
sq->geo.y = (ctx->barwin->geo.h >> 1) - (sq->geo.h >> 1);
static void
status_apply_list(struct status_ctx *ctx)
status_apply_list(struct element *e)
{
struct status_seq *sq;
struct barwin *b = SLIST_FIRST(&e->bars);
struct mousebind *m;
struct geo g;
int left = 0, right = 0, w, h;
int left = 0, right = 0;
SLIST_FOREACH(sq, &ctx->statushead, next)
SLIST_FOREACH(sq, &e->infobar->statushead, next)
{
switch(sq->type)
{
/* Text */
case 's':
sq->geo.w = draw_textw(ctx->theme, sq->str);
sq->geo.h = ctx->theme->font.height;
sq->geo.w = draw_textw(e->infobar->theme, sq->str);
sq->geo.h = e->infobar->theme->font.height;
if(sq->align != NoAlign)
sq->geo.y = TEXTY(ctx->theme, ctx->barwin->geo.h);
sq->geo.y = TEXTY(e->infobar->theme, e->geo.h);
STATUS_ALIGN(sq->align);
draw_text(ctx->barwin->dr, ctx->theme, sq->geo.x, sq->geo.y, sq->color, sq->str);
draw_text(b->dr, e->infobar->theme, sq->geo.x, sq->geo.y, sq->color, sq->str);
if(!SLIST_EMPTY(&sq->mousebinds))
SLIST_FOREACH(m, &sq->mousebinds, snext)
@ -369,259 +177,75 @@ status_apply_list(struct status_ctx *ctx)
/* Rectangle */
case 'R':
NOALIGN_Y();
STATUS_ALIGN(sq->align);
draw_rect(ctx->barwin->dr, &sq->geo, sq->color);
STORE_MOUSEBIND();
break;
/* Progress */
case 'p':
NOALIGN_Y();
STATUS_ALIGN(sq->align);
draw_rect(ctx->barwin->dr, &sq->geo, sq->color);
/* Progress bar geo */
g.x = sq->geo.x + sq->data[0];
g.y = sq->geo.y + sq->data[0];
g.w = sq->geo.w - sq->data[0] - sq->data[0];
g.h = sq->geo.h - sq->data[0] - sq->data[0];
if(sq->data[1] > sq->data[2])
sq->data[1] = sq->data[2];
if(sq->geo.w > sq->geo.h)
g.w /= ((float)sq->data[2] / (float)sq->data[1]);
else
{
g.y += g.h;
g.h /= ((float)sq->data[2] / (float)sq->data[1]);
g.y -= g.h;
}
draw_rect(ctx->barwin->dr, &g, sq->color2);
STORE_MOUSEBIND();
break;
/* Position */
case 'P':
NOALIGN_Y();
STATUS_ALIGN(sq->align);
draw_rect(ctx->barwin->dr, &sq->geo, sq->color);
if(sq->data[1] > sq->data[2])
sq->data[1] = sq->data[2];
g.x = sq->geo.x + ((sq->geo.w - sq->data[0]) / ((float)sq->data[2] / (float)sq->data[1]));
g.y = sq->geo.y;
g.w = sq->data[0];
g.h = sq->geo.h;
draw_rect(ctx->barwin->dr, &g, sq->color2);
STORE_MOUSEBIND();
break;
/* Graph */
case 'g':
NOALIGN_Y();
STATUS_ALIGN(sq->align);
draw_rect(ctx->barwin->dr, &sq->geo, sq->color);
status_graph_process(ctx, sq, sq->str);
STORE_MOUSEBIND();
break;
/* Image */
#ifdef HAVE_IMLIB2
case 'i':
draw_image_load(sq->str, &w, &h);
if(sq->geo.w <= 0)
sq->geo.w = w;
if(sq->geo.h <= 0)
sq->geo.h = h;
if(sq->align != NoAlign)
sq->geo.y = (ctx->barwin->geo.h >> 1) - (sq->geo.h >> 1);
sq->geo.y = (e->geo.h >> 1) - (sq->geo.h >> 1);
STATUS_ALIGN(sq->align);
draw_image(ctx->barwin->dr, &sq->geo);
STORE_MOUSEBIND();
draw_rect(b->dr, sq->geo, sq->color);
if(!SLIST_EMPTY(&sq->mousebinds))
SLIST_FOREACH(m, &sq->mousebinds, snext)
m->area = sq->geo;
break;
#endif /* HAVE_IMLIB2 */
}
}
}
/* Render current statustext of an element */
void
status_render(struct status_ctx *ctx)
status_render(struct element *e)
{
if(!ctx->status)
struct barwin *b = SLIST_FIRST(&e->bars);
if(!e->infobar->status)
return;
if(!(ctx->flags & STATUS_BLOCK_REFRESH))
barwin_refresh_color(ctx->barwin);
barwin_refresh_color(b);
/* Use simple text instead sequence if no sequence found */
if(SLIST_EMPTY(&ctx->statushead))
if(SLIST_EMPTY(&e->infobar->statushead))
{
int l = draw_textw(ctx->theme, ctx->status);
draw_text(ctx->barwin->dr, ctx->theme, ctx->barwin->geo.w - l,
TEXTY(ctx->theme, ctx->barwin->geo.h), ctx->barwin->fg, ctx->status);
int l = draw_textw(e->infobar->theme, e->infobar->status);
draw_text(b->dr, e->infobar->theme, e->geo.w - l,
TEXTY(e->infobar->theme, e->geo.h), b->fg, e->infobar->status);
}
else
status_apply_list(ctx);
status_apply_list(e);
barwin_refresh(ctx->barwin);
}
void
status_flush_list(struct status_ctx *ctx)
{
struct status_seq *sq;
struct mousebind *m;
/* Flush previous linked list of status sequences */
while(!SLIST_EMPTY(&ctx->statushead))
{
sq = SLIST_FIRST(&ctx->statushead);
SLIST_REMOVE_HEAD(&ctx->statushead, next);
while(!SLIST_EMPTY(&sq->mousebinds))
{
m = SLIST_FIRST(&sq->mousebinds);
SLIST_REMOVE_HEAD(&sq->mousebinds, snext);
free((void*)m->cmd);
free(m);
}
free(sq->str);
free(sq);
}
SLIST_INIT(&ctx->statushead);
}
void
status_copy_mousebind(struct status_ctx *ctx)
{
struct mousebind *m;
struct status_seq *sq;
if(!ctx->barwin)
return;
/* Flush barwin head of status mousebinds */
SLIST_INIT(&ctx->barwin->statusmousebinds);
SLIST_FOREACH(sq, &ctx->statushead, next)
{
SLIST_FOREACH(m, &sq->mousebinds, snext)
SLIST_INSERT_HEAD(&ctx->barwin->statusmousebinds, m, next);
}
barwin_refresh(b);
}
/* Parse and render statustext */
void
status_manage(struct status_ctx *ctx)
status_manage(struct element *e)
{
if(!ctx->status)
return;
struct status_seq *sq;
struct mousebind *m;
struct barwin *b = SLIST_FIRST(&e->bars);
ctx->update = false;
status_flush_list(ctx);
status_parse(ctx);
status_render(ctx);
status_copy_mousebind(ctx);
}
void
status_flush_surface(void)
{
struct barwin *b;
while(!SLIST_EMPTY(&W->h.vbarwin))
/*
* Flush previous linked list of status sequences
* and mousebind of status barwin
*/
while(!SLIST_EMPTY(&e->infobar->statushead))
{
b = SLIST_FIRST(&W->h.vbarwin);
SLIST_REMOVE_HEAD(&W->h.vbarwin, vnext);
barwin_remove(b);
sq = SLIST_FIRST(&e->infobar->statushead);
SLIST_REMOVE_HEAD(&e->infobar->statushead, next);
free(sq->str);
free(sq);
}
}
static void
status_surface(int x, int y, int w, int h, Color bg, char *status)
{
struct barwin *b;
struct screen *s;
struct status_ctx ctx;
int d;
Window rw;
if(!status)
return;
if(x + y < 0)
XQueryPointer(W->dpy, W->root, &rw, &rw, &x, &y, &d, &d, (unsigned int *)&d);
s = screen_gb_geo(x, y);
if(x + w > s->geo.x + s->geo.w)
x -= w;
if(y + h > s->geo.y + s->geo.h)
y -= h;
b = barwin_new(W->root, x, y, w, h, 0, bg, false);
barwin_map(b);
/* Use client theme */
ctx = status_new_ctx(b, W->ctheme);
ctx.status = xstrdup(status);
SLIST_INSERT_HEAD(&W->h.vbarwin, b, vnext);
status_manage(&ctx);
status_free_ctx(&ctx);
}
void
uicb_status_surface(Uicb cmd)
{
char *p, *ccmd = xstrdup(cmd);
int s, w, h, x = -1, y = -1;
Color bg;
if(!ccmd || !(p = strchr(ccmd, ' ')))
return;
*p = '\0';
++p;
if(!(((s = sscanf(ccmd, "%d,%d,#%x", &w, &h, &bg)) == 3)
|| (s = sscanf(ccmd, "%d,%d,%d,%d,#%x", &x, &y, &w, &h, &bg)) == 5))
while(!SLIST_EMPTY(&b->mousebinds))
{
free(ccmd);
return;
m = SLIST_FIRST(&b->mousebinds);
SLIST_REMOVE_HEAD(&b->mousebinds, next);
free((void*)m->cmd);
free(m);
}
status_surface(x, y, w, h, bg, p);
free(ccmd);
status_parse(e);
status_render(e);
}
/* Syntax: "<infobar name> <status string>" */
@ -644,9 +268,8 @@ uicb_status(Uicb cmd)
SLIST_FOREACH(ib, &s->infobars, next)
if(!strcmp(cmd, ib->name))
{
free(ib->statusctx.status);
ib->statusctx.status = xstrdup(p);
ib->statusctx.update = true;
free(ib->status);
ib->status = xstrdup(p);
infobar_elem_screen_update(s, ElemStatus);
}
}

View File

@ -8,16 +8,8 @@
#include "wmfs.h"
struct status_ctx status_new_ctx(struct barwin *b, struct theme *t);
void status_free_ctx(struct status_ctx *ctx);
void status_flush_list(struct status_ctx *ctx);
void status_flush_mousebind(struct status_ctx *ctx);
void status_copy_mousebind(struct status_ctx *ctx);
void status_parse(struct status_ctx *ctx);
void status_render(struct status_ctx *ctx);
void status_manage(struct status_ctx *ctx);
void status_flush_surface(void);
void status_render(struct element *e);
void status_manage(struct element *e);
void uicb_status(Uicb cmd);
void uicb_status_surface(Uicb cmd);
#endif /* STATUS_H */

View File

@ -1,200 +0,0 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#include "wmfs.h"
#include "systray.h"
#include "ewmh.h"
#include "infobar.h"
#define SYSTRAY_SPACING (2)
void
systray_acquire(void)
{
Window w = 0;
XSetWindowAttributes wattr =
{
.event_mask = ButtonPressMask | ExposureMask,
.override_redirect = true,
.background_pixmap = ParentRelative,
.background_pixel = W->systray.infobar->theme->bars.bg,
};
if(!(W->flags & WMFS_SYSTRAY) || W->systray.win)
return;
if(XGetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s]) != None)
{
warnx("Can't initialize system tray: owned by another process.");
return;
}
SLIST_INIT(&W->systray.head);
/* Init systray window */
w = XCreateSimpleWindow(W->dpy, W->systray.barwin->win, 0, 0,
W->systray.barwin->geo.h, W->systray.barwin->geo.h, 0, 0, 0);
XChangeWindowAttributes(W->dpy, w, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
XSelectInput(W->dpy, w, KeyPressMask | ButtonPressMask);
XMapRaised(W->dpy, w);
XSetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s], w, CurrentTime);
if(XGetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s]) != w)
{
warnl("System tray: can't get systray manager");
systray_freeicons();
return;
}
ewmh_send_message(W->root, W->root, "MANAGER", CurrentTime,
W->net_atom[net_system_tray_s], w, 0, 0);
XSync(W->dpy, false);
W->systray.win = w;
}
void
systray_add(Window win)
{
struct _systray *s;
if(!(W->flags & WMFS_SYSTRAY))
return;
s = xcalloc(1, sizeof(struct _systray));
s->win = win;
s->geo.h = W->systray.barwin->geo.h;
s->geo.w = W->systray.barwin->geo.h + SYSTRAY_SPACING;
ewmh_set_wm_state(s->win, NormalState);
XSelectInput(W->dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask);
XReparentWindow(W->dpy, s->win, W->systray.win, 0, 0);
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
XEMBED_EMBEDDED_NOTIFY, 0, W->systray.win, 0);
SLIST_INSERT_HEAD(&W->systray.head, s, next);
W->systray.redim = true;
}
void
systray_del(struct _systray *s)
{
if(!(W->flags & WMFS_SYSTRAY))
return;
SLIST_REMOVE(&W->systray.head, s, _systray, next);
free(s);
W->systray.redim = true;
}
void
systray_state(struct _systray *s)
{
long flags;
int code = 0;
if(!(W->flags & WMFS_SYSTRAY) || !(flags = ewmh_get_xembed_state(s->win)))
return;
if(flags & XEMBED_MAPPED)
{
code = XEMBED_WINDOW_ACTIVATE;
XMapRaised(W->dpy, s->win);
ewmh_set_wm_state(s->win, NormalState);
}
else
{
code = XEMBED_WINDOW_DEACTIVATE;
XUnmapWindow(W->dpy, s->win);
ewmh_set_wm_state(s->win, WithdrawnState);
}
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, code, 0, 0, 0);
}
void
systray_freeicons(void)
{
struct _systray *i;
if(!(W->flags & WMFS_SYSTRAY))
return;
while(!SLIST_EMPTY(&W->systray.head))
{
i = SLIST_FIRST(&W->systray.head);
SLIST_REMOVE_HEAD(&W->systray.head, next);
XUnmapWindow(W->dpy, i->win);
XReparentWindow(W->dpy, i->win, W->root, 0, 0);
free(i);
}
XSetSelectionOwner(W->dpy, W->net_atom[net_system_tray_s], None, CurrentTime);
W->systray.barwin->geo.w = 0;
infobar_elem_reinit(W->systray.infobar);
XSync(W->dpy, false);
}
struct _systray*
systray_find(Window win)
{
struct _systray *i;
if(!(W->flags & WMFS_SYSTRAY))
return NULL;
SLIST_FOREACH(i, &W->systray.head, next)
if(i->win == win)
return i;
return NULL;
}
int
systray_get_width(void)
{
int w = 1;
struct _systray *i;
SLIST_FOREACH(i, &W->systray.head, next)
w += i->geo.w + SYSTRAY_SPACING;
return w;
}
void
systray_update(void)
{
int x = 1;
struct _systray *i;
if(!(W->flags & WMFS_SYSTRAY))
return;
if(W->systray.redim)
{
W->systray.redim = false;
infobar_elem_reinit(W->systray.infobar);
}
SLIST_FOREACH(i, &W->systray.head, next)
{
XMapWindow(W->dpy, i->win);
XMoveResizeWindow(W->dpy, i->win, (i->geo.x = x), 0, i->geo.w, i->geo.h);
x += i->geo.w + SYSTRAY_SPACING;
}
}

View File

@ -1,20 +0,0 @@
/*
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
* For license, see COPYING.
*/
#ifndef SYSTRAY_H
#define SYSTRAY_H
#include "wmfs.h"
void systray_acquire(void);
void systray_add(Window win);
void systray_del(struct _systray *s);
void systray_state(struct _systray *s);
void systray_freeicons(void);
struct _systray *systray_find(Window win);
int systray_get_width(void);
void systray_update(void);
#endif /* SYSTRAY_H */

112
src/tag.c
View File

@ -22,6 +22,7 @@ tag_new(struct screen *s, char *name)
t = xcalloc(1, sizeof(struct tag));
t->screen = s;
t->name = xstrdup(name);
t->flags = 0;
t->id = 0;
t->sel = NULL;
@ -30,11 +31,6 @@ tag_new(struct screen *s, char *name)
if((l = TAILQ_LAST(&s->tags, tsub)))
t->id = l->id + 1;
if(!name || !strlen(name))
xasprintf(&t->name, "%d", t->id + 1);
else
t->name = xstrdup(name);
SLIST_INIT(&t->clients);
TAILQ_INIT(&t->sets);
@ -46,31 +42,20 @@ tag_new(struct screen *s, char *name)
void
tag_screen(struct screen *s, struct tag *t)
{
struct client *c;
/* Return to the previous tag */
if(t == s->seltag && TAILQ_NEXT(TAILQ_FIRST(&s->tags), next))
if(t == s->seltag)
t = t->prev;
if(!t)
t = TAILQ_FIRST(&s->tags);
/* Move clients which ignore tags */
SLIST_FOREACH(c, &W->h.client, next)
if (c->flags & CLIENT_IGNORE_TAG)
tag_client(t, c);
t->prev = s->seltag;
s->seltag = t;
clients_arrange_map();
/* Update focus */
if(!SLIST_EMPTY(&t->clients) && !(W->flags & WMFS_SCAN))
client_focus( client_tab_next(t->sel));
t->flags &= ~TAG_URGENT;
infobar_elem_screen_update(s, ElemTag);
ewmh_update_wmfs_props();
@ -86,7 +71,7 @@ tag_client(struct tag *t, struct client *c)
if(c->tag == t)
return;
if(!(c->flags & (CLIENT_IGNORE_LAYOUT | CLIENT_FREE)))
if(!(c->flags & CLIENT_IGNORE_LAYOUT))
layout_split_arrange_closed(c);
if(!(c->flags & CLIENT_REMOVEALL))
@ -102,10 +87,7 @@ tag_client(struct tag *t, struct client *c)
/* Client remove */
if(!t)
{
infobar_elem_screen_update(c->screen, ElemTag);
return;
}
c->prevtag = c->tag;
c->tag = t;
@ -113,9 +95,16 @@ tag_client(struct tag *t, struct client *c)
client_update_props(c, CPROP_LOC);
/*
* Insert in new tag list before
* layout_split_integrate, because of set historic.
*/
SLIST_INSERT_HEAD(&t->clients, c, tnext);
infobar_elem_screen_update(c->screen, ElemTag);
if(c->flags & CLIENT_IGNORE_LAYOUT)
c->flags ^= CLIENT_IGNORE_LAYOUT;
else if(!(c->flags & CLIENT_TABBED))
layout_split_integrate(c, t->sel);
if(c->flags & CLIENT_TABMASTER && c->prevtag)
{
@ -123,14 +112,9 @@ tag_client(struct tag *t, struct client *c)
SLIST_FOREACH(cc, &c->prevtag->clients, tnext)
if(cc->tabmaster == c)
{
cc->flags |= CLIENT_IGNORE_LAYOUT;
tag_client(t, cc);
}
}
layout_client(c);
if(t != c->screen->seltag || c->flags & CLIENT_TABBED)
client_unmap(c);
}
@ -169,8 +153,8 @@ uicb_tag_next(Uicb cmd)
struct tag *t;
if((t = TAILQ_NEXT(W->screen->seltag, next)))
tag_screen(W->screen, t);
else if(W->flags & WMFS_TAGCIRC)
tag_screen(W->screen, t);
else if( /* CIRCULAR OPTION */ 1)
tag_screen(W->screen, TAILQ_FIRST(&W->screen->tags));
}
@ -182,7 +166,7 @@ uicb_tag_prev(Uicb cmd)
if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
tag_screen(W->screen, t);
else if(W->flags & WMFS_TAGCIRC)
else if( /* CIRCULAR OPTION */ 1)
tag_screen(W->screen, TAILQ_LAST(&W->screen->tags, tsub));
}
@ -192,29 +176,19 @@ uicb_tag_client(Uicb cmd)
struct tag *t;
int id = ATOI(cmd);
if(W->client && (t = tag_gb_id(W->screen, id)))
if((t = tag_gb_id(W->screen, id)))
tag_client(t, W->client);
}
void
uicb_tag_client_and_set(Uicb cmd)
{
uicb_tag_client(cmd);
uicb_tag_set(cmd);
}
void
uicb_tag_move_client_next(Uicb cmd)
{
(void)cmd;
struct tag *t;
if(!W->client)
return;
if((t = TAILQ_NEXT(W->screen->seltag, next)))
tag_client(t, W->client);
else if(W->flags & WMFS_TAGCIRC)
else if( /* CIRCULAR OPTION */ 1)
tag_client(TAILQ_FIRST(&W->screen->tags), W->client);
}
@ -224,12 +198,9 @@ uicb_tag_move_client_prev(Uicb cmd)
(void)cmd;
struct tag *t;
if(!W->client)
return;
if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
tag_client(t, W->client);
else if(W->flags & WMFS_TAGCIRC)
else if( /* CIRCULAR OPTION */ 1)
tag_client(TAILQ_LAST(&W->screen->tags, tsub), W->client);
}
@ -247,8 +218,6 @@ uicb_tag_click(Uicb cmd)
static void
tag_remove(struct tag *t)
{
TAILQ_REMOVE(&t->screen->tags, t, next);
free(t->name);
layout_free_set(t);
@ -256,47 +225,14 @@ tag_remove(struct tag *t)
free(t);
}
void
uicb_tag_new(Uicb cmd)
{
struct screen *s = W->screen;
struct infobar *i;
tag_new(s, (char*)cmd);
s->flags |= SCREEN_TAG_UPDATE;
SLIST_FOREACH(i, &s->infobars, next)
infobar_elem_reinit(i);
s->flags ^= SCREEN_TAG_UPDATE;
}
void
uicb_tag_del(Uicb cmd)
{
struct infobar *i;
struct tag *t = W->screen->seltag;
(void)cmd;
if(SLIST_EMPTY(&t->clients)
&& TAILQ_NEXT(TAILQ_FIRST(&W->screen->tags), next))
{
tag_screen(W->screen, TAILQ_NEXT(t, next));
tag_remove(t);
W->screen->flags |= SCREEN_TAG_UPDATE;
SLIST_FOREACH(i, &W->screen->infobars, next)
infobar_elem_reinit(i);
W->screen->flags ^= SCREEN_TAG_UPDATE;
}
}
void
tag_free(struct screen *s)
{
while(!TAILQ_EMPTY(&s->tags))
tag_remove(TAILQ_FIRST(&s->tags));
struct tag *t;
TAILQ_FOREACH(t, &s->tags, next)
{
TAILQ_REMOVE(&s->tags, t, next);
tag_remove(t);
}
}

View File

@ -8,6 +8,7 @@
#include "wmfs.h"
static inline struct tag*
tag_gb_id(struct screen *s, int id)
{
@ -29,11 +30,9 @@ void uicb_tag_set_with_name(Uicb cmd);
void uicb_tag_next(Uicb cmd);
void uicb_tag_prev(Uicb cmd);
void uicb_tag_client(Uicb cmd);
void uicb_tag_client_and_set(Uicb cmd);
void uicb_tag_move_client_next(Uicb cmd);
void uicb_tag_move_client_prev(Uicb cmd);
void uicb_tag_click(Uicb cmd);
void uicb_tag_new(Uicb cmd);
void uicb_tag_del(Uicb cmd);
#endif /* TAG_H */

View File

@ -46,28 +46,6 @@ xcalloc(size_t nmemb, size_t size)
return ret;
}
/** realloc with error support and size_t overflow check
* \param ptr old pointer
* \param nmemb number of objects
* \param size size of single object
* \return non null void pointer
*/
void *
xrealloc(void *ptr, size_t nmemb, size_t size)
{
void *ret;
if(SIZE_MAX / nmemb < size)
err(EXIT_FAILURE, "xrealloc(%p, %zu, %zu), "
"size_t overflow detected", ptr, nmemb, size);
if((ret = realloc(ptr, nmemb * size)) == NULL)
err(EXIT_FAILURE, "realloc(%p, %zu)", ptr, nmemb * size);
return ret;
}
/** asprintf wrapper
* \param strp target string
* \param fmt format
@ -130,7 +108,7 @@ spawn(const char *format, ...)
if(!(sh = getenv("SHELL")) || sh[0] != '/')
sh = "/bin/sh";
if(!(pid = fork()))
if((pid = fork()) == 0)
{
setsid();
if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1)
@ -148,8 +126,8 @@ parse_args(char *str, char delim, char end, int narg, char *args[])
{
int i = 0;
for(args[0] = str; *str && (*str != end || *(str - 1) == '\\') && i < narg; ++str)
if(*str == delim && i < narg - 1)
for(args[0] = str; *str && *str != end && i < narg; ++str)
if(*str == delim)
{
*str = '\0';
args[++i] = ++str;

View File

@ -23,7 +23,7 @@
/* Insert at the end with SLIST */
#define SLIST_INSERT_TAIL(head, elem, field, prev) \
if(!prev) \
if(SLIST_EMPTY(head)) \
SLIST_INSERT_HEAD(head, elem, field); \
else \
SLIST_INSERT_AFTER(prev, elem, field);
@ -49,12 +49,9 @@
static inline Color
color_atoh(const char *col)
{
XColor xcolor;
int shift = (col[0] == '#');
if(!XAllocNamedColor(W->dpy, DefaultColormap(W->dpy, W->xscreen), col, &xcolor, &xcolor))
warnl("Error: cannot allocate color \"%s\".", col);
return xcolor.pixel;
return (Color)strtol(col + shift, NULL, 16);
}
static inline void
@ -66,14 +63,6 @@ swap_ptr(void **x, void **y)
*y = t;
}
static inline void
swap_int(int *x, int *y)
{
*y = *x ^ *y;
*x = *y ^ *x;
*y = *x ^ *y;
}
static inline enum position
str_to_position(char *str)
{
@ -89,7 +78,6 @@ str_to_position(char *str)
void *xmalloc(size_t nmemb, size_t size);
void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *ptr, size_t nmemb, size_t size);
int xasprintf(char **strp, const char *fmt, ...);
char *xstrdup(const char *str);
pid_t spawn(const char *format, ...);

View File

@ -3,17 +3,10 @@
* For license, see COPYING.
*/
#include <string.h>
#include <getopt.h>
#include <signal.h>
#include <sys/wait.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#ifdef HAVE_IMLIB2
#include <Imlib2.h>
#endif /* HAVE_IMLIB2 */
#include "wmfs.h"
#include "event.h"
#include "ewmh.h"
@ -22,8 +15,7 @@
#include "util.h"
#include "config.h"
#include "client.h"
#include "layout.h"
#include "systray.h"
#include "fifo.h"
int
wmfs_error_handler(Display *d, XErrorEvent *event)
@ -161,16 +153,6 @@ wmfs_xinit(void)
* Barwin linked list
*/
SLIST_INIT(&W->h.barwin);
SLIST_INIT(&W->h.vbarwin);
/*
* Optional dep init
*/
#ifdef HAVE_IMLIB2
imlib_context_set_display(W->dpy);
imlib_context_set_visual(DefaultVisual(W->dpy, W->xscreen));
imlib_context_set_colormap(DefaultColormap(W->dpy, W->xscreen));
#endif /* HAVE_IMLIB2 */
W->flags |= WMFS_RUNNING;
}
@ -207,7 +189,7 @@ wmfs_scan(void)
int i, n, rf, nscreen = 0;
int tag = -1, screen = -1, flags = -1;
unsigned long ir, il;
long *ret = NULL, *tret = NULL;
long *ret, *tret;
bool getg = false;
XWindowAttributes wa;
Window usl, usl2, *w = NULL, tm, focus;
@ -221,7 +203,7 @@ wmfs_scan(void)
if(XGetWindowProperty(W->dpy, W->root, W->net_atom[wmfs_current_tag], 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il,
(unsigned char**)&tret)
== Success && tret)
== Success && ret)
{
nscreen = (int)ir;
}
@ -244,15 +226,6 @@ wmfs_scan(void)
if(!wa.override_redirect && wa.map_state == IsViewable)
{
if(ewmh_get_xembed_state(w[i]))
{
systray_add(w[i]);
continue;
}
if(ewmh_manage_window_type_desktop(w[i]))
continue;
if(XGetWindowProperty(W->dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il,
(unsigned char**)&ret)
@ -320,16 +293,11 @@ wmfs_scan(void)
if(getg)
c->flags |= CLIENT_IGNORE_LAYOUT;
client_map(c);
tag_client(tag_gb_id(c->screen, tag), c);
if(getg && tag <= TAILQ_LAST(&c->screen->tags, tsub)->id - 1)
if(getg)
client_moveresize(c, &g);
/* In a removed tag */
else
{
c->geo = g;
layout_client(c);
}
client_get_name(c);
}
@ -360,10 +328,6 @@ wmfs_scan(void)
if((fc = client_gb_win(focus)) && fc != W->client)
client_focus(fc);
SLIST_FOREACH(c, &W->h.client, next)
if(c->flags & CLIENT_TILED)
layout_fix_hole(c);
W->flags &= ~WMFS_SCAN;
if(tret)
@ -373,26 +337,39 @@ wmfs_scan(void)
XSync(W->dpy, false);
}
static inline void
wmfs_sigchld(void)
{
if(W->flags & WMFS_SIGCHLD)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
W->flags ^= WMFS_SIGCHLD;
}
}
static void
wmfs_loop(void)
{
XEvent ev;
int maxfd, fd = ConnectionNumber(W->dpy);
fd_set iset;
while((W->flags & WMFS_RUNNING) && !XNextEvent(W->dpy, &ev))
while(W->flags & WMFS_RUNNING)
{
/* Manage SIGCHLD event here, X is not safe with it */
wmfs_sigchld();
EVENT_HANDLE(&ev);
maxfd = fd + 1;
FD_ZERO(&iset);
FD_SET(fd, &iset);
if(W->fifo.fd > 0)
{
maxfd += W->fifo.fd;
FD_SET(W->fifo.fd, &iset);
}
if(select(maxfd, &iset, NULL, NULL, NULL) > 0)
{
if(FD_ISSET(fd, &iset))
{
while((W->flags & WMFS_RUNNING) && XPending(W->dpy))
{
XNextEvent(W->dpy, &ev);
EVENT_HANDLE(&ev);
}
}
else if(W->fifo.fd > 0 && FD_ISSET(W->fifo.fd, &iset))
fifo_read();
}
}
}
@ -405,6 +382,7 @@ wmfs_init(void)
screen_init();
event_init();
config_init();
fifo_init();
}
void
@ -415,10 +393,16 @@ wmfs_quit(void)
struct theme *t;
struct client *c;
struct mousebind *m;
struct launcher *l;
/* Will free:
*
* Screens -> tags
* -> Infobars -> Elements
*/
ewmh_update_wmfs_props();
screen_free();
XFreeGC(W->dpy, W->rgc);
while(!SLIST_EMPTY(&W->h.client))
@ -426,32 +410,29 @@ wmfs_quit(void)
c = SLIST_FIRST(&W->h.client);
client_update_props(c, CPROP_LOC | CPROP_FLAG | CPROP_GEO);
c->flags |= (CLIENT_IGNORE_LAYOUT | CLIENT_REMOVEALL);
XMapWindow(W->dpy, c->win);
client_remove(c);
}
/* Will free:
*
* Screens -> tags
* -> Infobars -> Elements
*/
screen_free();
/* Conf stuffs */
while(!SLIST_EMPTY(&W->h.theme))
{
t = SLIST_FIRST(&W->h.theme);
SLIST_REMOVE_HEAD(&W->h.theme, next);
XFreeFontSet(W->dpy, t->font.fontset);
status_free_ctx(&t->tags_n_sl);
status_free_ctx(&t->tags_s_sl);
status_free_ctx(&t->tags_o_sl);
status_free_ctx(&t->tags_u_sl);
status_free_ctx(&t->client_n_sl);
status_free_ctx(&t->client_s_sl);
free(t);
}
while(!SLIST_EMPTY(&W->h.rule))
{
r = SLIST_FIRST(&W->h.rule);
SLIST_REMOVE_HEAD(&W->h.rule, next);
free(r->class);
free(r->instance);
free(r->role);
free(r->name);
free(r);
}
while(!SLIST_EMPTY(&W->h.keybind))
{
k = SLIST_FIRST(&W->h.keybind);
@ -468,25 +449,11 @@ wmfs_quit(void)
free(m);
}
while(!SLIST_EMPTY(&W->h.launcher))
/* FIFO stuffs */
if(W->fifo.fd > 0)
{
l = SLIST_FIRST(&W->h.launcher);
SLIST_REMOVE_HEAD(&W->h.launcher, next);
free((void*)l->name);
free((void*)l->prompt);
free((void*)l->command);
free(l);
}
while(!SLIST_EMPTY(&W->h.rule))
{
r = SLIST_FIRST(&W->h.rule);
SLIST_REMOVE_HEAD(&W->h.rule, next);
free(r->class);
free(r->instance);
free(r->role);
free(r->name);
free(r);
close(W->fifo.fd);
unlink(W->fifo.path);
}
/* close log */
@ -494,6 +461,8 @@ wmfs_quit(void)
fclose(W->log), W->log = NULL;
W->flags &= ~WMFS_RUNNING;
XCloseDisplay(W->dpy);
}
/** Reload WMFS binary
@ -515,101 +484,41 @@ uicb_quit(Uicb cmd)
W->flags &= ~WMFS_RUNNING;
}
static void
exec_uicb_function(Display *dpy, Window root, char *func, char *cmd)
{
Atom utf8s = XInternAtom(dpy, "UTF8_STRING", false);
XClientMessageEvent e = {
.type = ClientMessage,
.message_type = XInternAtom(dpy, "_WMFS_FUNCTION", false),
.window = root,
.format = 32,
.data.l[4] = true
};
XChangeProperty(dpy,root, XInternAtom(dpy, "_WMFS_FUNCTION", false), utf8s,
8, PropModeReplace, (unsigned char*)func, strlen(func));
if(!cmd)
cmd = "";
XChangeProperty(dpy, root, XInternAtom(dpy, "_WMFS_CMD", false), utf8s,
8, PropModeReplace, (unsigned char*)cmd, strlen(cmd));
XSendEvent(dpy, root, false, StructureNotifyMask, (XEvent*)&e);
XSync(dpy, False);
}
static void
signal_handle(int sig)
{
switch (sig)
{
case SIGQUIT:
case SIGTERM:
W->flags &= ~WMFS_RUNNING;
break;
case SIGCHLD:
W->flags |= WMFS_SIGCHLD;
break;
}
}
int
main(int argc, char **argv)
{
int i;
bool r;
Display *dpy;
char path[MAX_PATH_LEN] = { 0 };
struct sigaction sa;
(void)argc;
sprintf(path, "%s/"CONFIG_DEFAULT_PATH, getenv("HOME"));
/* Opt */
while((i = getopt(argc, argv, "hvC:c:")) != -1)
{
switch(i)
{
default:
case 'h':
printf("usage: %s [-hv] [-c <func> <cmd] [-C <file>]\n"
" -h Show this page\n"
" -v Show WMFS version\n"
" -c <func> <cmd> Execute a specified UICB function\n"
" -C <file> Launch WMFS with a specified configuration file\n", argv[0]);
exit(EXIT_SUCCESS);
break;
case 'v':
printf("wmfs("WMFS_VERSION") 2 beta\n");
exit(EXIT_SUCCESS);
break;
case 'c':
if(!(dpy = XOpenDisplay(NULL)))
{
fprintf(stderr, "%s: Can't open X server\n", argv[0]);
exit(EXIT_FAILURE);
}
exec_uicb_function(dpy, DefaultRootWindow(dpy), optarg, argv[optind]);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'C':
strncpy(path, optarg, MAX_PATH_LEN);
break;
}
}
W = (struct wmfs*)xcalloc(1, sizeof(struct wmfs));
/* Default path ~/.config/wmfs/wmfsrc */
W->confpath = path;
sprintf(W->confpath, "%s/"CONFIG_DEFAULT_PATH, getenv("HOME"));
/* Opt */
while((i = getopt(argc, argv, "hvC:")) != -1)
{
switch(i)
{
case 'h':
printf("usage: %s [-hv] [-C <file>]\n"
" -h Show this page\n"
" -v Show WMFS version\n"
" -C <file> Launch WMFS with a specified configuration file\n", argv[0]);
free(W);
exit(EXIT_SUCCESS);
break;
case 'v':
printf("wmfs("WMFS_VERSION") 2 beta\n");
free(W);
exit(EXIT_SUCCESS);
break;
case 'C':
strncpy(W->confpath, optarg, sizeof(W->confpath));
break;
}
}
/* Get X display */
if(!(W->dpy = XOpenDisplay(NULL)))
@ -618,14 +527,6 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
/* Set signal handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_handle;
sigemptyset(&sa.sa_mask);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
/* Core */
wmfs_init();
wmfs_scan();
@ -638,7 +539,5 @@ main(int argc, char **argv)
if(r)
execvp(argv[0], argv);
XCloseDisplay(W->dpy);
return 1;
}

View File

@ -92,51 +92,26 @@ struct barwin
Color fg, bg;
void *ptr; /* Special cases */
SLIST_HEAD(mbhead, mousebind) mousebinds;
SLIST_HEAD(, mousebind) statusmousebinds;
SLIST_ENTRY(barwin) next; /* global barwin */
SLIST_ENTRY(barwin) enext; /* element barwin */
SLIST_ENTRY(barwin) vnext; /* volatile barwin */
};
struct status_seq
{
struct geo geo;
enum position align;
int data[4];
char type;
char *str;
Color color, color2;
Color color;
SLIST_HEAD(, mousebind) mousebinds;
SLIST_ENTRY(status_seq) next;
};
struct status_ctx
{
struct barwin *barwin;
struct theme *theme;
#define STATUS_BLOCK_REFRESH 0x01
Flags flags;
char *status;
bool update;
SLIST_HEAD(, status_gcache) gcache;
SLIST_HEAD(, status_seq) statushead;
};
struct status_gcache
{
char *name;
int *datas;
int ndata;
SLIST_ENTRY(status_gcache) next;
};
struct element
{
struct geo geo;
struct infobar *infobar;
struct status_ctx *statusctx;
int type;
char *data;
enum position align;
void (*func_init)(struct element *e);
void (*func_update)(struct element *e);
@ -150,11 +125,12 @@ struct infobar
struct geo geo;
struct screen *screen;
struct theme *theme;
struct status_ctx statusctx;
enum barpos opos, pos;
enum barpos pos;
char *elemorder;
char *name;
char *status;
TAILQ_HEAD(esub, element) elements;
SLIST_HEAD(, status_seq) statushead;
SLIST_ENTRY(infobar) next;
};
@ -162,9 +138,8 @@ struct screen
{
struct geo geo, ugeo;
struct tag *seltag;
#define SCREEN_TAG_UPDATE 0x01
Flags flags;
int id;
Flags elemupdate;
TAILQ_HEAD(tsub, tag) tags;
SLIST_HEAD(, infobar) infobars;
SLIST_ENTRY(screen) next;
@ -178,11 +153,8 @@ struct tag
struct client *sel;
struct client *prevsel;
struct tag *prev;
struct status_ctx statusctx;
char *name;
int id;
#define TAG_URGENT 0x01
#define TAG_IGNORE_ENTER 0x02
Flags flags;
SLIST_HEAD(, client) clients;
TAILQ_HEAD(ssub, layout_set) sets;
@ -213,10 +185,6 @@ struct client
#define CLIENT_REMOVEALL 0x200
#define CLIENT_MAPPED 0x400
#define CLIENT_FULLSCREEN 0x800
#define CLIENT_FREE 0x1000
#define CLIENT_TILED 0x2000
#define CLIENT_MOUSE 0x4000
#define CLIENT_IGNORE_TAG 0x8000
Flags flags;
Window win, frame, tmp;
SLIST_ENTRY(client) next; /* Global list */
@ -267,14 +235,12 @@ struct theme
int bars_width;
/* struct elements */
struct colpair tags_n, tags_s, tags_o, tags_u; /* normal / selected / occupied */
struct status_ctx tags_n_sl, tags_s_sl, tags_o_sl, tags_u_sl; /* status line */
struct colpair tags_n, tags_s; /* normal / selected */
int tags_border_width;
Color tags_border_col;
/* client / frame */
struct colpair client_n, client_s;
struct status_ctx client_n_sl, client_s_sl, client_f_sl;
Color frame_bg;
int client_titlebar_width;
int client_border_width;
@ -291,38 +257,12 @@ struct rule
char *name;
int tag, screen;
#define RULE_FREE 0x01
#define RULE_TAB 0x02
#define RULE_MAX 0x02
#define RULE_IGNORE_TAG 0x04
Flags flags;
SLIST_ENTRY(rule) next;
};
struct launcher
{
char *name;
char *prompt;
char *command;
#define HISTOLEN 64
char histo[HISTOLEN][256];
int nhisto;
int width;
SLIST_ENTRY(launcher) next;
};
struct launcher_ccache
{
char *start;
char **namelist;
size_t hits;
};
struct _systray
{
struct geo geo;
Window win;
SLIST_ENTRY(_systray) next;
};
#define MAX_PATH_LEN 8192
struct wmfs
@ -333,30 +273,23 @@ struct wmfs
int xscreen, xdepth;
int xmaxw, xmaxh;
int nscreen;
unsigned int client_mod;
Flags numlockmask;
#define WMFS_SCAN 0x001
#define WMFS_RUNNING 0x002
#define WMFS_RELOAD 0x004
#define WMFS_SYSTRAY 0x008
#define WMFS_LOG 0x010
#define WMFS_LAUNCHER 0x020
#define WMFS_SIGCHLD 0x040
#define WMFS_TABNOC 0x080 /* tab next opened client */
#define WMFS_TAGCIRC 0x100 /* tab_next on last tag -> go to first tag / tab_prev on first tag -> go to last tag */
#define WMFS_AUTOFOCUS 0x200
#define WMFS_SCAN 0x01
#define WMFS_RUNNING 0x02
#define WMFS_RELOAD 0x04
Flags flags;
GC gc, rgc;
Atom *net_atom;
char **argv;
char *confpath;
char confpath[MAX_PATH_LEN];
struct barwin *last_clicked_barwin;
struct theme *ctheme;
#define CFOCUS_ENTER 0x01
#define CFOCUS_CLICK 0x02
Flags cfocus; /* Focus configuration, can be set to 0, CFOCUS_ENTER or CFOCUS_CLICK*/
int padding;
/* FIFO stuffs */
struct
{
char *path;
int fd;
} fifo;
/* Log file */
FILE *log;
@ -371,8 +304,6 @@ struct wmfs
SLIST_HEAD(, theme) theme;
SLIST_HEAD(, rule) rule;
SLIST_HEAD(, mousebind) mousebind;
SLIST_HEAD(, launcher) launcher;
SLIST_HEAD(, barwin) vbarwin;
} h;
/*
@ -387,19 +318,6 @@ struct wmfs
struct mbhead root;
} tmp_head;
/*
* Because there is only one systray per display,
* set struct there
*/
struct
{
struct barwin *barwin;
struct infobar *infobar;
bool redim;
Window win;
SLIST_HEAD(, _systray) head;
} systray;
/*
* Selected screen, client
*/

788
wmfs.1
View File

@ -1,788 +0,0 @@
.\" title: wmfs
.\" dev: xorg62
.\" man: arpinux
.\"
.TH "WMFS" "1" "2012/05/02" "wmfs" "manual of wmfs"
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.SH "NAME"
wmfs \- Window Manager From Scratch
.SH "SYNOPSIS"
\fBwmfs\fR [\fB\-hv\fR] [\fB\-C <file>\fR] [\fB\-c <uicb_function> <cmd>\fR]
.sp
.SH "DESCRIPTION"
\fBWMFS\fR is a lightweight and highly configurable tiling window manager for X written in C\&.
.sp
.SH "OPTIONS"
.PP
\fB\-C <file>\fR
.RS 4
Load a configuration file\&.
.RE
.PP
\fB\-c <uicb_function> <cmd>\fR
.RS 4
Execute an uicb function to control WMFS\&.
.RE
.PP
\fB\-v\fR
.RS 4
Print version information to standard output, then exit\&.
.RE
.PP
\fB\-h\fR
.RS 4
Print help information, then exit\&.
.RE
.SH "DEFAULT KEY BINDINGS"
.PP
\fBControl\-Alt + r\fR
.RS 4
Reload WMFS binary
.RE
.PP
\fBSuper + Return\fR
.RS 4
Run a terminal (urxvt by default)
.RE
.PP
\fBSuper + q\fR
.RS 4
Quit the selected client
.RE
.PP
\fBControl\-Alt + q\fR
.RS 4
Exit WMFS
.RE
.PP
\fBSuper + f \fR
.RS 4
Toggle free the selected client
.RE
.PP
\fBSuper + Shift + f \fR
.RS 4
Toggle ignore_tag the selected client
.RE
.PP
\fBSuper + Shift + h \fR
.RS 4
Toggle infobar visibility
.RE
.PP
\fBAlt + Tab\fR
.RS 4
Give the focus to the next client
.RE
.PP
\fBAlt\-Shift + Tab\fR
.RS 4
Give the focus to the previous client
.RE
.PP
\fBAlt + h\fR
.RS 4
Give the focus to the client on the left
.RE
.PP
\fBAlt + l\fR
.RS 4
Give the focus to the client on the right
.RE
.PP
\fBAlt + k\fR
.RS 4
Give the focus to the client on the top
.RE
.PP
\fBAlt + j\fR
.RS 4
Give the focus to the client on the bottom
.RE
.PP
\fBSuper + Tab\fR
.RS 4
Give the focus to the next tabbed client
.RE
.PP
\fBSuper\-Shift + Tab\fR
.RS 4
Give the focus to the previous tabbed client
.RE
.PP
\fBControl\-Shift + h\fR
.RS 4
Swap with the client on the left
.RE
.PP
\fBControl\-Shift + l\fR
.RS 4
Swap with the client on the right
.RE
.PP
\fBControl\-Shift + k\fR
.RS 4
Swap with the client on the top
.RE
.PP
\fBControl\-Shift + j\fR
.RS 4
Swap with the client on the bottom
.RE
.PP
\fBAlt\-Shift + h\fR
.RS 4
Tab in the client on the left
.RE
.PP
\fBAlt\-Shift + l\fR
.RS 4
Tab in the client on the right
.RE
.PP
\fBAlt\-Shift + k\fR
.RS 4
Tab in the client on the top
.RE
.PP
\fBAlt\-Shift + j\fR
.RS 4
Tab in the client on the bottom
.RE
.PP
\fBAlt\-Shift + u\fR
.RS 4
Untab the client
.RE
.PP
\fBSuper + h\fR
.RS 4
Increase the client to the left
.RE
.PP
\fBSuper + l\fR
.RS 4
Decrease the client from the left
.RE
.PP
\fBSuper + k\fR
.RS 4
Increase the client to the top
.RE
.PP
\fBSuper + j\fR
.RS 4
Decrease the client from the top
.RE
.PP
\fBSuper\-Control + h\fR
.RS 4
Decrease the client from the right
.RE
.PP
\fBSuper\-Control + l\fR
.RS 4
Increase the client to the right
.RE
.PP
\fBSuper\-Control + k\fR
.RS 4
Decrease the client from the bottom
.RE
.PP
\fBSuper\-Control + j\fR
.RS 4
Increase the client to the bottom
.RE
.PP
\fBControl + Right\fR
.RS 4
Next tag
.RE
.PP
\fBControl + Left\fR
.RS 4
Previous tag
.RE
.PP
\fBControl + Up\fR
.RS 4
Next screen
.RE
.PP
\fBControl + Down\fR
.RS 4
Previous screen
.RE
.PP
\fBSuper + m\fR
.RS 4
Vertical mirror layout
.RE
.PP
\fBSuper\-Shift + m\fR
.RS 4
Horizontal mirror layout
.RE
.PP
\fBSuper + r\fR
.RS 4
Rotate layout right
.RE
.PP
\fBSuper\-Shift + r\fR
.RS 4
Rotate layout left
.RE
.PP
\fBSuper\-Control\-Alt + h\fR
.RS 4
Integrate client in left layout
.RE
.PP
\fBSuper\-Control\-Alt + j\fR
.RS 4
Integrate client in bottom layout
.RE
.PP
\fBSuper\-Control\-Alt + k\fR
.RS 4
Integrate client in top layout
.RE
.PP
\fBSuper\-Control\-Alt + l\fR
.RS 4
Integrate client in right layout
.RE
.PP
\fBSuper + o\fR
.RS 4
Restore previous layout
.RE
.PP
\fBSuper\-Shift + o\fR
.RS 4
Restore next layout
.RE
.PP
\fBSuper + p\fR
.RS 4
Display a launcher in the statusbar to run an unix command\fR
.RE
.PP
\fBSuper + F[1\&.\&.9]\fR
.RS 4
Change tag view
.RE
.PP
\fBSuper\-Shift + F[1\&.\&.9]\fR
.RS 4
Transfert the selected client to the wanted tag
.RE
.PP
\fBSuper + -\fR
.RS 4
Delete current tag\fR
.RE
.PP
\fBSuper\-Shift + -\fR
.RS 4
Add current tag\fR
.RE
.SH "CONFIGURATION"
WMFS is configured by \fI$HOME/\&.config/wmfs/wmfsrc\fR\&.
.RE
.PP
\fB\ include:\fR
wmfsrc supports ”@include” to split configuration file by section\&.
.RS 2
\fB\ Usage:\fR "@include ~/.config/wmfs/wmfs_themes"\&.
.RE
.PP
\fB\ [themes]\fR
wmfsrc supports themes for client and statusbar\&.
.RS 2
\fB Misc\fR
.RS 2
\fB\ name:\fR
theme name, will be used in next sections\&.
.PP
\fB\ font:\fR
theme font in XLFD format\&.
.PP
.RE
\fB\ Bars\fR
.RS 2
\fB\ bars_width:\fR
bar height in pixels\&.
.PP
\fB\ bars_fg/bg:\fR
statusbar text/background color\&.
.PP
.RE
\fB\ Tags\fR
.RS 2
\fB\ tags_normal_fg/bg:\fR
normal tag text/button color\&.
.PP
\fB\ tags_normal_statusline:\fR
normal tag statusline\&.
.PP
\fB\ tags_sel_fg/bg:\fR
selected tag text/button color\&.
.PP
\fB\ tags_sel_statusline:\fR
selected tag statusline\&.
.PP
\fB\ tags_occupied_fg/bg:\fR
occupied tag text/button color\&.
.PP
\fB\ tags_occupied_statusline:\fR
occupied tag statusline\&.
.PP
\fB\ tags_urgent_fg/bg:\fR
urgent tag text/button color\&.
.PP
\fB\ tags_urgent_statusline:\fR
urgent tag statusline\&.
.PP
\fB\ tags_border_color:\fR
tag button border color\&.
.PP
\fB\ tags_border_width:\fR
tag button border width\&.
.PP
.RE
\fB\ Clients\fR
.RS 2
\fB\ client_normal_fg/bg:\fR
normal client titlebar text/background color\&.
.PP
\fB\ client_normal_statusline:\fR
normal client statusline\&.
.PP
\fB\ client_sel_fg/bg:\fR
selected client titlebar text/background color\&.
.PP
\fB\ client_sel_statusline:\fR
selected client statusline\&.
.PP
\fB\ frame_bg:\fR
client border color\&.
.PP
\fB\ client_titlebar_width:\fR
client titlebar height in pixels\&.
.PP
\fB\ client_border_width:\fR
client border height in pixels\&.
.RE
.PP
.RE
\fB\ [bars]\fR
.RS 2
\fB\ position:\fR
statusbar position on screen (0=Top; 1=Bottom, 2=Hide)\&.
.PP
\fB\ screen:\fR
screen to display statusbar (start ar 0), set to\fB -1\fR to display on every screen\&.
.PP
\fB\ elements:\fR
ordered statusbar elements t=Tags, s=Statustext, y=Systray, l=Launcher\&.
.PP
\fB\ theme:\fR
names of the statusbar theme\&.
.RE
.PP
.RE
\fB\ [tags]\fR
.RS 2
\fB\ circular:\fR
enable tag wrapping. default is true\&.
.PP
\fB\ screen:\fR
screen to display tag. use no screen option or screen =\fB -1\fR to set tag on each screen\&.
.PP
\fB\ name:\fR
display tagname\&.
.PP
\fB\ statusline:\fR
draw a custom statusline in the specific tag (can display any sequences)\&.
.PP
\fB\ mousebinds:\fR
mouse actions on the tag buttons\&.
.RE
.PP
.RE
\fB\ [client]\fR
.RS 2
\fB\ theme:\fR
apply theme to client by default\&.
.PP
\fB\ key_modifier:\fR
key modifier to perform actions on clients\&.
.PP
\fB\ focus:\fR
select the focus mouse options; enter=focus follow mouse, click=click to focus, everything-else=disable focus mouse support\&.
.PP
\fB\ mousebinds:\fR
mouse actions on client\&.
.PP
\fB\ padding:\fR
enable padding between clients. default is 0\&.
.PP
\fB\ autofocus:\fR
give focus to new created clients. default is false\&.
.RE
.PP
.RE
\fB\ [rules]\fR
specific rules for clients: to identify an application, use xprop\&.
.RS 2
\fB\ instance:\fR
first part of WM_CLASS\&.
.PP
\fB\ class:\fR
second part of WM_CLASS\&.
.PP
\fB\ role:\fR
WM_WINDOW_ROLE\&.
.PP
\fB\ name:\fR
_NET_WM_NAME\&.
.PP
\fB\ theme:\fR
apply theme to client\&.
.PP
\fB\ tag:\fR
specify a tag to display client (start at 0)\&.
.PP
\fB\ screen:\fR
display client on a specific screen\&.
.PP
\fB\ free:\fR
client in auto-free mode (true/false)\&.
.PP
\fB\ tab:\fR
open client in a tab (true/false)\&.
.PP
\fB\ ignore_tag:\fR
specify to client to ignore tags (client is displayed on every tag)\&.
.RE
.PP
.RE
\fB\ [launchers]\fR
.RS 2
\fB\ name:\fR
launcher-name, will be used in the [keys] section\&.
.PP
\fB\ prompt:\fR
display text at the beginning of the prompt\&.
.PP
\fB\ command:\fR
command used by the launcher. can be an uicb function or an uicb function + extension\&.
.RE
.PP
.RE
\fB\ [keys]\fR
.RS 2
each line is contained within\fB\ [key]...[/key]\fR
.PP
\fB\ mod:\fR
key modifier (Alt, Control, Shift, Super)\&.
.PP
\fB\ key:\fR
key to press, you can identify it with "xev"\&.
.PP
\fB\ func:\fR
uicb function to launch\&.
.PP
\fB\ cmd:\fR
if\fB\ func = "spawn"\fR set the external command to launch\&.
.sp
.SH "STATUS"
statusbars, tags, surfaces and titlebars support sequences to display text, images bars and graphs through the\fB\ wmfs -c status\fR command.
.PP
\fB\ Syntax\fR
.PP
.RS 4
\fB\ position:\fR “left/right” (relative) or “x;y” (absolute)\&.
.PP
\fB\ dimension:\fR “ww;hh” for width;height of the rectangle or the image, to display an image at its original size, set it to “0;0”\&.
.PP
\fB\ color:\fR ”#rrggbb”\&.
.PP
\fB\ imagepath:\fR absolute path for the image\&.
.PP
\fB\ border:\fR width of the progressbar border in pixels\&.
.PP
\fB\ curser:\fR width of the curser in the positionbar\&.
.PP
\fB\ value:\fR a variable, to draw progressbar\&.
.PP
\fB\ valuemax:\fR maximum value of the value used in the progressbar\&.
.RE
.PP
\fB\ basic usage:\fR
wmfs -c status "<barname> TEXT visible on 'barname'"\&.
.PP
\fB\ display colors:\fR
wmfs -c status "<barname> ^s[<position>;<color>;<text>]"\&.
.PP
\fB\ display rectangles:\fR
wmfs -c status "<barname> ^R[<position>;<dimensions>;<color>]"\&.
.PP
\fB\ display images:\fR
wmfs -c status "<barname> ^i[<position>;<dimensions>;<imagepath>]"\&.
.PP
\fB\ display progressbars:\fR
wmfs -c status "<barname> ^p[<position>;<dimensions>;<border>;<value>;<valuemax>;<bgcolor>;<fgcolor>]"\&.
.PP
\fB\ display positionbars:\fR
wmfs -c status "<barname> ^P[<position>;<dimensions>;<curser>;<value>;<valuemax>;<bgcolor>;<fgcolor>]"\&.
.PP
\fB\ display graph:\fR
wmfs -c status "<barname> ^g[<position>;<dimensions>;<value>;<valuemax>;<bgcolor>;<fgcolor>;<name>]"\&.
.RE
.PP
\fB\ mousebinds:\fR
sequences supports mousebinds with format\fB\ (<key>;<uicb-function>)\fR or\fB\ (<key>;<spawn>;<command>)\fR
.RE
.PP
\fB\ surfaces:\fR
you can display popups from the statusbar with the mousebind\fB\ (<key>;status_surface;<position>,<dimension>,<color> <datas>)\fR
.PP
.sp
.SH "UICB Functions"
UICB functions list. for “User Interface Call Backs”\&.
.PP
\fB\ usage in the wmfsrc:\fR func = "tag_next"\fB\ or\fR func = "spawn" cmd = "urxvt -e vim"\&.
.RE
\fB\ usage in the status.sh:\fR wmfs -c status "<barname> ^s[<position>;<color>;next](1;tag_next)"\&.
.RE
\fB\ usage in your terminal:\fR wmfs -c tag_next\&.
.PP
\fB\ spawn\fR
.RS 4
launch a command. ex: func = "spawn" cmd = "urxvtc -e screen irssi"\&.
.RE
.PP
\fB\ quit\fR
.RS 4
quit wmfs\&.
.RE
.PP
\fB\ reload\fR
.RS 4
reload wmfs\&.
.RE
.PP
\fB\ tag_set\fR
.RS 4
set tag by number\&.
.RE
.PP
\fB\ tag\fR
.RS 4
set tag by name\&.
.RE
.PP
\fB\ tag_next/prev\fR
.RS 4
set next/previous tag\&.
.RE
.PP
\fB\ tag_client\fR
.RS 4
tag the client\&.
.RE
.PP
\fB\ tag_client_and_set\fR
.RS 4
teg the client and set the tag\&.
.RE
.PP
\fB\ tag_move_client_next/prev\fR
.RS 4
tag the client with next/previous tag\&.
.RE
.PP
\fB\ tag_click\fR
.RS 4
display tag with a clic on tag button\&.
.RE
.PP
\fB\ tag_new/del\fR
.RS 4
add/delete a tag\&.
.RE
.PP
\fB infobar_toggle_hide\fR
.RS 4
toggle specific infobar visibility (infobar_name as cmd)\&.
.RE
.PP
\fB\ layout_vmirror\fR
.RS 4
vertical mirror tiling\&.
.RE
.PP
\fB\ layout_hmirror\fR
.RS 4
horizontal mirror tiling\&.
.RE
.PP
\fB\ layout_rotate_left\fR
.RS 4
tiling rotate anti/clockwise\&.
.RE
.PP
\fB\ layout_prev_set\fR
.RS 4
back to previous set layout\&.
.RE
.PP
\fB\ layout_next_set\fR
.RS 4
go to next set layout\&.
.RE
.PP
\fB\ layout_integrate_left/right/top/bottom\fR
.RS 4
client integration in the client zone by direction\&.
.RE
.PP
\fB\ client_close\fR
.RS 4
close the client\&.
.RE
.PP
\fB\ client_resize_right/left/top/bottom\fR
.RS 4
resize client with direction\&.
.RE
.PP
\fB\ client_focus_right/left/top/bottom\fR
.RS 4
focus client with direction\&.
.RE
.PP
\fB\ client_tab_right/left/top/bottom\fR
.RS 4
tab client with direction\&.
.RE
.PP
\fB\ client_swap_right/left/top/bottom\fR
.RS 4
swap client with direction\&.
.RE
.PP
\fB\ client_focus_next/prev\fR
.RS 4
move focus to the next/previous client\&.
.RE
.PP
\fB\ client_swap_next/prev\fR
.RS 4
swap with the next/previous client\&.
.RE
.PP
\fB\ client_untab\fR
.RS 4
untab the client\&.
.RE
.PP
\fB\ client_focus_next_tab\fR
.RS 4
move focus to next tab-client\&.
.RE
.PP
\fB\ client_focus_prev_tab\fR
.RS 4
move focus to previous tab-client\&.
.RE
.PP
\fB\ client_focus_click\fR
.RS 4
give focus to client with a clic\&.
.RE
.PP
\fB\ client_toggle_free\fR
.RS 4
toggle free the selected client\&.
.RE
.PP
\fB\ client_toggle_ignore_tag\fR
.RS 4
toggle ignore_tag the selected client\&.
.RE
.PP
\fB\ client_tab_next_opened\fR
.RS 4
open the client in a tab\&.
.RE
.PP
\fB\ status\fR
.RS 4
display the argument text in the statusbar\&.
.RE
.PP
\fB\ status_surface\fR
.RS 4
display a surface. can contain sequences\&.
.RE
.PP
\fB\ mouse_resize\fR
.RS 4
resize the client\&.
.RE
.PP
\fB\ mouse_move\fR
.RS 4
move the client\&.
.RE
.PP
\fB\ mouse_swap\fR
.RS 4
swap the client\&.
.RE
.PP
\fB\ mouse_tab\fR
.RS 4
tab the client\&.
.RE
.PP
\fB\ screen_next/prev\fR
.RS 4
go to next/previous screen\&.
.RE
.PP
\fB\ screen_move_client_next/prev\fR
.RS 4
move the client to next/previous screen\&.
.RE
.PP
\fB\ launcher\fR
.RS 4
native prompt. ex:\fB\ func = "launcher" cmd = "exec"\fR display the “exec” launcher\&.
.RE
.PP
.sp
.SH "BUGS"
WMFS isn\'t stable for now\&. So it certainly contains some bugs\&.
.sp
.SH "AUTHOR"
Martin Duquesnoy <\fIxorg62@gmail\&.com\fR\&[1]>\&.
.sp
.SH "WWW"
Main site: \fIhttps://github\&.com/xorg62/wmfs\fR
.PP
Wiki: \fIhttps://github\&.com/xorg62/wmfs/wiki\fR
.PP
Bug tracker: \fIhttps://github\&.com/xorg62/wmfs/issues\fR
.sp
.SH "COPYING"
WMFS is under the BSD license\&. See COPYING for more information\&.
.RE

View File

@ -1,7 +0,0 @@
[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=wmfs
Comment=Window Manager From Scratch
TryExec=wmfs
Exec=wmfs

52
wmfs.vim Normal file
View File

@ -0,0 +1,52 @@
" Vim syntax file
" Language: WMFS Configuration file
" Maintainer: David Delassus <david.jose.delassus@gmail.com>
" Latest Revision: 17 October 2011
if exists("b:current_syntax")
finish
endif
syn case ignore
" Keywords
syn keyword wmfsBlockTheme font
syn keyword wmfsBlockThemeBars bars_width bars_fg bars_bg
syn keyword wmfsBlockThemeTags tags_normal_fg tags_normal_bg tags_sel_fg tags_sel_bg tags_border_color tags_border_width
syn keyword wmfsBlockThemeClient client_normal_fg client_normal_bg client_sel_fg client_sel_bg frame_bg client_titlebar_width client_border_width
syn keyword wmfsBlockBar position screen elements theme
syn keyword wmfsBlockTag screen name
syn keyword wmfsBlockKey mod key func cmd
syn keyword wmfsTodo contained TODO FIXME XXX NOTE
" Matches
syn match wmfsNumber /\S\@<!\d\+\(\.\d\+\)\?\(\S\@!\|}\@=\)/ nextgroup=wmfsNumber
syn match wmfsNumber '\d\+' contained display
syn match wmfsNumber '[-+]\d\+' contained display
" Regions
syn region wmfsComment start="#" end="$" contains=wmfsTodo
syn region wmfsString start='"' end='"' contains=CONTAINED
syn region wmfsSection start="\[" end="\]"
syn region wmfsList start="{" end="}" contains=wmfsNumber,wmfsString
let b:current_syntax = "wmfs"
hi def link wmfsTodo Todo
hi def link wmfsComment Comment
hi def link wmfsSection Statement
hi def link wmfsList Statement
hi def link wmfsNumber Number
hi def link wmfsString String
hi def link wmfsBlockTheme Identifier
hi def link wmfsBlockThemeBars Identifier
hi def link wmfsBlockThemeTags Identifier
hi def link wmfsBlockThemeClient Identifier
hi def link wmfsBlockBar Identifier
hi def link wmfsBlockTag Identifier
hi def link wmfsBlockKey Identifier

93
wmfsrc
View File

@ -22,34 +22,16 @@
# Element tags
tags_normal_fg = "#AABBAA"
tags_normal_bg = "#223322"
# tags_normal_statusline = ""
tags_sel_fg = "#223322"
tags_sel_bg = "#AABBAA"
# tags_sel_statusline = ""
tags_occupied_fg = "#AABBAA"
tags_occupied_bg = "#445544"
tags_occupied_statusline = "\R[0;0;100;1;#AABBAA]"
tags_urgent_fg = "#223322"
tags_urgent_bg = "#CC5544"
# tags_urgent_statusline = ""
tags_border_color = "#112211"
tags_border_width = 1
# Frame / Client
client_normal_fg = "#AABBAA"
client_normal_bg = "#223322"
client_normal_statusline = "\s[3;9;#121212;x] \s[2;8;#ff0000;x](1;client_close)"
client_sel_fg = "#223322"
client_sel_bg = "#AABBAA"
client_sel_statusline = "\s[3;9;#121212;x] \s[2;8;#ff0000;x](1;client_close)"
# client_free_statusline = ""
frame_bg = "#555555"
client_titlebar_width = 12
client_border_width = 1
@ -70,13 +52,11 @@
#
# t Tags
# s Statustext (will take available space)
# y Systray (can be set only ONE time among all element)
# l Launcher (will be expended at launcher use)
[bar]
position = 0
screen = 0
elements = "tlsy" # element order in bar
elements = "ts" # element order in bar
theme = "default"
[/bar]
@ -91,14 +71,10 @@
[tags]
# Tag wrapping navigation
circular = false
# Use no screen option or screen = -1 to set tag on each screen
[tag]
screen = -1
name = "1"
# statusline=""
[/tag]
[tag] name = "2" [/tag]
@ -118,34 +94,16 @@
[client]
# Padding between clients (default: 0) :
#padding = 75
# Give focus to new created client (default = false)
autofocus = false
theme = "default"
key_modifier = "Super"
# Focus type:
# enter : focus follow mouse (default)
# click : click to focus
# everything-else : disable mouse focus support
focus = enter
[mouse] button = "1" func = "client_focus_click" [/mouse]
[mouse] button = "1" func = "mouse_swap" [/mouse]
[mouse] button = "2" func = "mouse_tab" [/mouse]
[mouse] button = "3" func = "mouse_resize" [/mouse]
[mouse] button = "4" func = "client_focus_next_tab" [/mouse]
[mouse] button = "5" func = "client_focus_prev_tab" [/mouse]
[mouse] button = "1" func = "client_focus_click" [/mouse]
[mouse] button = "1" func = "mouse_swap" [/mouse]
[mouse] button = "2" func = "mouse_tab" [/mouse]
[mouse] button = "3" func = "mouse_resize" [/mouse]
[/client]
[rules]
[rule]
# use instance = "*" for a all-clients rule
instance = "chromium"
# role = ""
@ -156,28 +114,12 @@
screen = 0
free = false
tab = false
max = false
ignore_tag = false
[/rule]
[/rules]
[launchers]
# command can be an uicb function or an uicb function + extension (see example)
[launcher]
name = "exec"
prompt = "Run:"
# Example of uicb + ext:
# command = "spawn xterm -e"
command = "spawn"
width = 150
[/launcher]
[/launchers]
[keys]
[key] mod = {"Super"} key = "Return" func = "spawn" cmd = "urxvt || xterm" [/key]
@ -204,9 +146,6 @@
[key] mod = {"Super", "Shift"} key = "F7" func = "tag_client" cmd = "6" [/key]
[key] mod = {"Super", "Shift"} key = "F8" func = "tag_client" cmd = "7" [/key]
[key] mod = {"Super"} key = "minus" func = "tag_del" [/key]
[key] mod = {"Super", "Shift"} key = "minus" func = "tag_new" [/key]
# tag function: cmd = nameofthetag
#[key] mod = {"Super"} key = "z" func = "tag" cmd = "2" [/key]
@ -252,7 +191,6 @@
[key] mod = {"Alt", "Shift"} key = "k" func = "client_tab_top" [/key]
[key] mod = {"Alt", "Shift"} key = "j" func = "client_tab_bottom" [/key]
[key] mod = {"Alt", "Shift"} key = "u" func = "client_untab" [/key]
[key] mod = {"Super"} key = "t" func = "client_tab_next_opened" [/key]
# Layout manipulation
[key] mod = {"Super"} key = "m" func = "layout_vmirror" [/key]
@ -260,25 +198,8 @@
[key] mod = {"Super"} key = "r" func = "layout_rotate_right" [/key]
[key] mod = {"Super", "Shift"} key = "r" func = "layout_rotate_left" [/key]
[key] mod = {"Control", "Super", "Alt"} key = "h" func = "layout_integrate_left" [/key]
[key] mod = {"Control", "Super", "Alt"} key = "j" func = "layout_integrate_bottom" [/key]
[key] mod = {"Control", "Super", "Alt"} key = "k" func = "layout_integrate_top" [/key]
[key] mod = {"Control", "Super", "Alt"} key = "l" func = "layout_integrate_right" [/key]
# Layout set historic travelling function (TESTING)
[key] mod = {"Super"} key = "o" func = "layout_prev_set" [/key]
[key] mod = {"Super", "Shift"} key = "o" func = "layout_next_set" [/key]
# Toggle client free/tile
[key] mod = {"Super"} key = "f" func = "client_toggle_free" [/key]
# Toggle client ignore_tag
[key] mod = {"Super", "Shift"} key = "f" func = "client_toggle_ignore_tag" [/key]
# Toggle infobar visibility
[key] mod = {"Super", "Shift"} key = "h" func = "infobar_toggle_hide" cmd = "default" [/key]
# Launcher
[key] mod = {"Super"} key = "p" func = "launcher" cmd = "exec" [/key]
[key] mod = {"Super"} key = "p" func = "layout_next_set" [/key]
[/keys]