39 Commits

Author SHA1 Message Date
Philippe Pepiot
b9e67982f8 Fix possible leak in parse.c. Fixes #149
If stat() fail and open() worked, file wasn't closed

Reported-by: mlq <mlq@pwmt.org>
Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-11-01 14:02:53 +01:00
Philippe Pepiot
0400fb5454 Wait childs in main loop, fixes #142 Signed-off-by: Philippe Pepiot <phil@philpep.org> 2011-11-01 14:02:46 +01:00
Martin Duquesnoy
a7371e9445 Client/Event: Fix focus issue & client manual moving to next screen segfault 2011-10-27 19:06:54 +02:00
Martin Duquesnoy
a3a2f33ddf Event: Use MAX_EV instead of dynamic handle_event size: fix multi-head possible segfault 2011-09-01 17:43:58 +02:00
Martin Duquesnoy
13d8a0acc8 Infobar: Add Infobar element: see elements_order in [bar] 2011-08-04 18:43:51 +02:00
Martin Duquesnoy
02cd7d91e9 Event: Simplify layout switch 2011-08-04 10:36:42 +02:00
Martin Duquesnoy
71f4b9df89 Event: Replace ugly consecutive if by do_mousebind function 2011-08-04 10:25:59 +02:00
Martin Duquesnoy
8f040ed7a4 Wmfs: Add INAREA macro to replace ugly ifs 2011-08-04 09:53:58 +02:00
Martin Duquesnoy
e5a804cee8 Selbar: Dynamic selbar position is back 2011-08-04 09:18:32 +02:00
Martin Duquesnoy
48bdc94538 Infobar: Improve selbar render: draw it on infobar barwin directly 2011-08-04 09:00:24 +02:00
Martin Duquesnoy
a501bd1127 Merge branch 'master' of git.wmfs.info:wmfs 2011-08-03 20:17:22 +02:00
Philippe Pepiot
ec5b71b371 Build System: Freetype only when use Xft
Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-08-03 20:15:13 +02:00
Joris van Zwieten
5e2bcf03d6 Fix segfault on selbar de-allocation. fixes #138 2011-08-03 20:04:16 +02:00
Martin Duquesnoy
fb04cef137 Infobar: Use pointer in infobar_init 2011-08-03 06:44:58 +02:00
Martin Duquesnoy
acffbdc188 Infobar: fix selbar (above statustext) 2011-08-03 06:26:47 +02:00
Martin Duquesnoy
b42c42245a Wmfs: Fix warnings 2011-08-03 06:17:07 +02:00
Martin Duquesnoy
570a3f0e64 Draw: Add bool arg to parse_image_block to don't save mouse bind at textw call 2011-08-01 23:38:03 +02:00
Martin Duquesnoy
39080f9952 Status: Use InfoBar* instead of win in StatusMouse struct 2011-08-01 23:26:51 +02:00
Philippe Pepiot
8958dbfe70 BuildSystem: Add xft support for old build system fixes #139 2011-08-01 13:52:40 +02:00
Martin Duquesnoy
84d30e25e2 Status: securize if in statustext_mouse 2011-07-31 19:03:23 +02:00
Martin Duquesnoy
31d875c438 Status: Allow void command argument in mouse action sequence 2011-07-31 18:57:20 +02:00
Martin Duquesnoy
c1fcd0dac7 Status: Multi (;;) dynamic mouse section possible 2011-07-31 16:06:39 +02:00
Martin Duquesnoy
8344b1cc82 Status: Dynamic mouse action: new format \b[x;y;w;h;col;(1;spawn;xterm)]\ (last arg of sequences b,s and i 2011-07-31 14:43:09 +02:00
Martin Duquesnoy
92831181e7 Status: Dynamic mouse bind with text sequence: (button;func;cmd)\s[1;10;#ffffff;clickable text]\ 2011-07-30 17:53:09 +02:00
Martin Duquesnoy
1934aa713d Status: Add dynamic mouse bind: (1;spawn;xterm)\b[;;;;]\ = clickable rectangle 2011-07-30 17:40:39 +02:00
Martin Duquesnoy
bbf11ac274 Wmfs: Fix help line 2011-07-29 17:51:39 +02:00
Martin Duquesnoy
2ec2bf4760 Barwin: Replace simple functions by macros 2011-07-29 17:48:06 +02:00
Martin Duquesnoy
08d55605da Code: cosmetic + warning fix 2011-07-29 17:19:09 +02:00
Martin Duquesnoy
69ec9d7db0 Apply pierreN patch: _NET_WM_NAME attribute in rules 2011-07-29 17:17:21 +02:00
Martin Duquesnoy
9c3130a17c BarWindow/Event: Make barwindows linked to improve render with expose event 2011-07-29 11:53:22 +02:00
Martin Duquesnoy
4e2459318c Init: init trayicons head 2011-07-29 10:55:05 +02:00
Martin Duquesnoy
58f6f674ca WMFS: Use SLIST from sys/queue.h instead homemade linked list 2011-07-29 10:54:08 +02:00
Martin Duquesnoy
5d80ec8538 Barwin: Remove useless check and fix wmfsrc 2011-07-28 09:54:23 +02:00
Martin Duquesnoy
7e33c322ff Wmfs: Remove unused var 2011-07-28 09:35:17 +02:00
Martin Duquesnoy
d1f5acf938 Util: Remove unused function 2011-07-28 09:34:16 +02:00
Martin Duquesnoy
6ed013fc7c Wmfs: Remove update_status and option 2011-07-28 00:10:36 +02:00
Martin Duquesnoy
4e33bc9bf7 Status: Remove status management (status_path, status_timing, threading), use loop in status script now (see scripts/status.sh) 2011-07-28 00:08:43 +02:00
Martin Duquesnoy
7bfba91a92 Update README 2011-07-27 14:20:26 +02:00
Philippe Pepiot
54687912c5 Old build system can still be used 2011-07-27 14:15:40 +02:00
28 changed files with 938 additions and 733 deletions

87
Makefile.in Normal file
View File

@@ -0,0 +1,87 @@
PROG=wmfs
MAN=wmfs.1
# wmfs version
VERSION=$(shell scripts/setlocalversion)
SRCS= \
src/barwin.c \
src/client.c \
src/config.c \
src/draw.c \
src/event.c \
src/ewmh.c \
src/frame.c \
src/infobar.c \
src/init.c \
src/launcher.c \
src/layout.c \
src/menu.c \
src/mouse.c \
src/parse_api.c \
src/parse.c \
src/screen.c \
src/status.c \
src/systray.c \
src/tag.c \
src/util.c \
src/color.c \
src/split.c \
src/cfactor.c \
src/wmfs.c
# flags
CFLAGS+= -DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\"
CFLAGS+= -DWMFS_VERSION=\"${VERSION}\"
CFLAGS+= -Wall -Wextra
OBJS= ${SRCS:.c=.o}
all: ${PROG} ${MAN}.gz
${PROG}: ${OBJS} src/structs.h src/wmfs.h src/parse.h
${CC} -o $@ ${OBJS} ${LDFLAGS}
${MAN}.gz: ${MAN}
gzip -cn -9 ${MAN} > $@
.c.o:
${CC} -c ${CFLAGS} $< -o $@
.PHONY: all clean distclean install uninstall dist
clean:
rm -f ${OBJS} wmfs ${MAN}.gz
distclean: clean
rm -f Makefile
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
mkdir -p ${DESTDIR}${PREFIX}/bin
install ${PROG} ${DESTDIR}${PREFIX}/bin
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
mkdir -p ${DESTDIR}${MANPREFIX}/man1
install -m 644 ${MAN}.gz ${DESTDIR}${MANPREFIX}/man1/
@echo installing xsession file to ${DESTDIR}${PREFIX}/share/xsessions
mkdir -p ${DESTDIR}${PREFIX}/share/xsessions
install -m 644 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/
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
rm -f ${DESTDIR}${PREFIX}/bin/wmfs
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
rm -f ${DESTDIR}${MANPREFIX}/man1/wmfs.1.gz
@echo removing xsession file from ${DESTDIR}${PREFIX}/share/xsessions
rm -f ${DESTDIR}${PREFIX}/share/xsessions/wmfs.desktop
@echo removing config file from ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
rm -f ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/wmfsrc
rmdir ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
dist:
@echo "Generate wmfs-`date +%Y%m`.tar.gz"
git archive --format=tar --prefix=wmfs-`date +%Y%m`/ master | gzip -c > wmfs-`date +%Y%m`.tar.gz

7
README
View File

@@ -21,11 +21,11 @@ LICENSE : BSD, see COPYING.
REQUIREMENT : REQUIREMENT :
- libx11 - libx11
- libxft (optional) - libxft (optional)
\- freetype - freetype
- libxinerama (optional) - libxinerama (optional)
- libxrandr (optional) - libxrandr (optional)
- imlib2 (optional) - imlib2 (optional)
- cmake>=2.8 (build system) - cmake>=2.8 (build system, optional)
OS : OS :
- GNU/Linux : Supported. - GNU/Linux : Supported.
@@ -35,6 +35,9 @@ INSTALL :
mkdir build/ && cd build/ mkdir build/ && cd build/
cmake .. cmake ..
You can also use old build system if you don't want^Whave cmake
./configure && make
DISTROS : DISTROS :
- wmfs port for FreeBSD at x11-wm/wmfs - wmfs port for FreeBSD at x11-wm/wmfs
- wmfs is available with AUR in ArchLinux (wmfs or wmfs-git) - wmfs is available with AUR in ArchLinux (wmfs or wmfs-git)

111
configure vendored Executable file
View File

@@ -0,0 +1,111 @@
#!/bin/sh
LIBS="x11"
USE_XINERAMA="xinerama"
USE_XRANDR="xrandr"
USE_IMLIB2="imlib2"
USE_XFT="xft freetype2"
OS=`uname -s`
PREFIX=/usr/local
MANPREFIX="$PREFIX/man"
XDG_CONFIG_DIR="$PREFIX/etc/xdg"
while true; do
case "$1" in
--without-xinerama)
USE_XINERAMA=""; shift;;
--without-xrandr)
USE_XRANDR=""; shift;;
--without-imlib2)
USE_IMLIB2=""; shift;;
--without-xft)
USE_XFT=""; 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;;
--man-prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
MANPREFIX=$2; shift 2;;
--help|-h)
echo "Usage: ./configure [options]
--without-imlib2 : compile without imlib2 support
--without-xrandr : compile without xrandr support
--without-xinerama : compile without xinerama support
--without-xft : compile without xft support
--prefix DIRECTORY : install binary with specified prefix (default $PREFIX)
--xdg-config-dir DIRECTORY : install configuration to specified directory (default $XDG_CONFIG_DIR)
--man-prefix DIRECTORY : install man page to specified prefix (default $MANPREFIX)"
exit 0;;
*) break;;
esac
done
LIBS="$LIBS $USE_XINERAMA $USE_XRANDR $USE_IMLIB2 $USE_XFT"
which pkg-config >/dev/null 2>&1
if [ $? -eq 0 ];
then
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 -I/usr/local/include/freetype2"
LDFLAGS="-L/usr/local/lib";;
OpenBSD)
CFLAGS="-I/usr/X11R6/include -I/usr/X11R6/include/freetype2 -I/usr/local/include"
LDFLAGS="-L/usr/X11R6/lib -L/usr/local/lib";;
NetBSD)
CFLAGS="-I/usr/X11R7/include -I/usr/X11R7/include/freetype2 -I/usr/local/include"
LDFLAGS="-L/usr/X11R7/lib -L/usr/local/lib";;
Linux)
CFLAGS="-I/usr/include/freetype2"
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"
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
[ -n "$USE_XRANDR" ] && LDFLAGS="$LDFLAGS -lXrandr"
[ -n "$USE_IMLIB2" ] && LDFLAGS="$LDFLAGS -lImlib2"
[ -n "$USE_XFT" ] && LDFLAGS="$LDFLAGS -lXft -lfreetype"
fi
[ -n "$USE_XINERAMA" ] && CFLAGS="$CFLAGS -DHAVE_XINERAMA"
[ -n "$USE_XRANDR" ] && CFLAGS="$CFLAGS -DHAVE_XRANDR"
[ -n "$USE_IMLIB2" ] && CFLAGS="$CFLAGS -DHAVE_IMLIB"
[ -n "$USE_XFT" ] && CFLAGS="$CFLAGS -DHAVE_XFT"
LDFLAGS="$LDFLAGS -lpthread"
cat > Makefile << EOF
PREFIX=$PREFIX
XDG_CONFIG_DIR=$XDG_CONFIG_DIR
MANPREFIX=$MANPREFIX
CFLAGS+=$CFLAGS
LDFLAGS+=$LDFLAGS
EOF
cat Makefile.in >> Makefile
echo "Compilation resume:
OS=$OS
CFLAGS=$CFLAGS
LDFLAGS=$LDFLAGS
PREFIX=$PREFIX
MANPREFIX=$MANPREFIX
XDG_CONFIG_DIR=$XDG_CONFIG_DIR
You can run 'make' now :-)
"

View File

@@ -8,4 +8,4 @@ statustext()
wmfs -s "`date`" wmfs -s "`date`"
} }
statustext while true; do statustext; sleep 10; done

View File

@@ -98,7 +98,10 @@ barwin_create(Window parent,
bw->bg = bg; bw->bg = bg;
bw->fg = fg; bw->fg = fg;
FLAGAPPLY(bw->flags, stipple, StippleFlag); FLAGAPPLY(bw->flags, stipple, StippleFlag);
bw->stipple_color = -1; bw->stipple_color = 0xffffffff;
/* Attach */
SLIST_INSERT_HEAD(&bwhead, bw, next);
return bw; return bw;
} }
@@ -123,8 +126,6 @@ barwin_draw_text(BarWindow *bw, int x, int y, char *text)
void void
barwin_color_set(BarWindow *bw, uint bg, char *fg) barwin_color_set(BarWindow *bw, uint bg, char *fg)
{ {
CHECK(bw);
bw->bg = bg; bw->bg = bg;
bw->fg = fg; bw->fg = fg;
@@ -134,7 +135,7 @@ barwin_color_set(BarWindow *bw, uint bg, char *fg)
bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade); bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade);
} }
if(bw->flags & StippleFlag && bw->stipple_color == -1) if(bw->flags & StippleFlag && bw->stipple_color == 0xffffffff)
bw->stipple_color = getcolor(fg); bw->stipple_color = getcolor(fg);
return; return;
@@ -146,8 +147,7 @@ barwin_color_set(BarWindow *bw, uint bg, char *fg)
void void
barwin_delete(BarWindow *bw) barwin_delete(BarWindow *bw)
{ {
CHECK(bw); SLIST_REMOVE(&bwhead, bw, BarWindow, next);
XSelectInput(dpy, bw->win, NoEventMask); XSelectInput(dpy, bw->win, NoEventMask);
XDestroyWindow(dpy, bw->win); XDestroyWindow(dpy, bw->win);
XFreePixmap(dpy, bw->dr); XFreePixmap(dpy, bw->dr);
@@ -156,77 +156,6 @@ barwin_delete(BarWindow *bw)
return; return;
} }
/** Delete the BarWindow sub windows
* \param bw BarWindow pointer
*/
void
barwin_delete_subwin(BarWindow *bw)
{
CHECK(bw);
XDestroySubwindows(dpy, bw->win);
return;
}
/** Map a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_map(BarWindow *bw)
{
CHECK(!(bw->flags & MappedFlag));
XMapWindow(dpy, bw->win);
bw->flags |= MappedFlag;
return;
}
/** Map the subwindows of a BarWindow
* Use for the BarWindow special border...
* \param bw BarWindow pointer
*/
void
barwin_map_subwin(BarWindow *bw)
{
CHECK(bw);
XMapSubwindows(dpy, bw->win);
return;
}
/** Unmap a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_unmap(BarWindow *bw)
{
CHECK(bw->flags & MappedFlag);
XUnmapWindow(dpy, bw->win);
bw->flags &= ~MappedFlag;
return;
}
/** Unmap the BarWindow sub windows
* \param bw BarWindow pointer
*/
void
barwin_unmap_subwin(BarWindow *bw)
{
CHECK(bw);
XUnmapSubwindows(dpy, bw->win);
return;
}
/** Move a BarWindow /** Move a BarWindow
* \param bw BarWindow pointer * \param bw BarWindow pointer
* \param x X position * \param x X position
@@ -235,7 +164,7 @@ barwin_unmap_subwin(BarWindow *bw)
void void
barwin_move(BarWindow *bw, int x, int y) barwin_move(BarWindow *bw, int x, int y)
{ {
if(!bw || (bw->geo.x == x && bw->geo.y == y)) if(bw->geo.x == x && bw->geo.y == y)
return; return;
XMoveWindow(dpy, bw->win, (bw->geo.x = x), (bw->geo.y = y)); XMoveWindow(dpy, bw->win, (bw->geo.x = x), (bw->geo.y = y));
@@ -251,7 +180,7 @@ barwin_move(BarWindow *bw, int x, int y)
void void
barwin_resize(BarWindow *bw, int w, int h) barwin_resize(BarWindow *bw, int w, int h)
{ {
if(!bw || (bw->geo.width == w && bw->geo.height == h)) if(bw->geo.width == w && bw->geo.height == h)
return; return;
/* Frame */ /* Frame */
@@ -285,8 +214,6 @@ barwin_resize(BarWindow *bw, int w, int h)
void void
barwin_refresh_color(BarWindow *bw) barwin_refresh_color(BarWindow *bw)
{ {
CHECK(bw);
XSetForeground(dpy, gc, bw->bg); XSetForeground(dpy, gc, bw->bg);
XFillRectangle(dpy, bw->dr, gc, 0, 0, bw->geo.width, bw->geo.height); XFillRectangle(dpy, bw->dr, gc, 0, 0, bw->geo.width, bw->geo.height);
@@ -312,15 +239,3 @@ barwin_refresh_color(BarWindow *bw)
return; return;
} }
/** Refresh the BarWindow
* \param bw BarWindow pointer
*/
void
barwin_refresh(BarWindow *bw)
{
CHECK(bw);
XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0);
return;
}

View File

@@ -108,10 +108,10 @@ static void
_cfactor_arrange_row(Client *c, Position p, int fac) _cfactor_arrange_row(Client *c, Position p, int fac)
{ {
Geo cgeo = c->frame_geo; Geo cgeo = c->frame_geo;
Client *cc; Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
/* Travel clients to search parents of row and apply fact */ /* Travel clients to search parents of row and apply fact */
for(cc = tiled_client(c->screen, clients); cc; cc = tiled_client(c->screen, cc->next)) for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p)) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p))
{ {
cc->tilefact[p] += fac; cc->tilefact[p] += fac;
@@ -131,13 +131,13 @@ static bool
_cfactor_check_geo_row(Client *c, Position p, int fac) _cfactor_check_geo_row(Client *c, Position p, int fac)
{ {
Geo cgeo = c->frame_geo; Geo cgeo = c->frame_geo;
Client *cc; Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
int e, f[4] = { 0 }; int e, f[4] = { 0 };
f[p] += fac; f[p] += fac;
/* Travel clients to search parents of row and check geos */ /* Travel clients to search parents of row and check geos */
for(cc = tiled_client(c->screen, clients); cc; cc = tiled_client(c->screen, cc->next)) for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p)) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p))
{ {
(Geo)cfactor_geo(cc->wrgeo, f, &e); (Geo)cfactor_geo(cc->wrgeo, f, &e);

View File

@@ -87,11 +87,7 @@ CLIENT_ACTION_DIR(swapsel, Bottom);
void void
client_attach(Client *c) client_attach(Client *c)
{ {
if(clients) SLIST_INSERT_HEAD(&clients, c, next);
clients->prev = c;
c->next = clients;
clients = c;
return; return;
} }
@@ -126,10 +122,7 @@ client_configure(Client *c)
void void
client_detach(Client *c) client_detach(Client *c)
{ {
Client **cc; SLIST_REMOVE(&clients, c, Client, next);
for(cc = &clients; *cc && *cc != c; cc = &(*cc)->next);
*cc = c->next;
return; return;
} }
@@ -147,10 +140,10 @@ client_get_next(void)
if(!sel || ishide(sel, selscreen)) if(!sel || ishide(sel, selscreen))
return NULL; return NULL;
for(c = sel->next; c && ishide(c, selscreen); c = c->next); for(c = SLIST_NEXT(sel, next); c && ishide(c, selscreen); c = SLIST_NEXT(c, next));
if(!c && conf.client_round) if(!c && conf.client_round)
for(c = clients; c && ishide(c, selscreen); c = c->next); for(c = SLIST_FIRST(&clients); c && ishide(c, selscreen); c = SLIST_NEXT(c, next));
return c; return c;
} }
@@ -161,19 +154,19 @@ client_get_next(void)
Client* Client*
client_get_prev(void) client_get_prev(void)
{ {
Client *c = NULL, *d; Client *c = NULL, *d = SLIST_FIRST(&clients);
screen_get_sel(); screen_get_sel();
if(!sel || ishide(sel, selscreen)) if(!sel || ishide(sel, selscreen))
return NULL; return NULL;
for(d = clients; d != sel; d = d->next) for(; d != sel; d = SLIST_NEXT(d, next))
if(!ishide(d, selscreen)) if(!ishide(d, selscreen))
c = d; c = d;
if(!c && conf.client_round) if(!c && conf.client_round)
for(; d; d = d->next) for(; d; d = SLIST_NEXT(d, next))
if(!ishide(d, selscreen)) if(!ishide(d, selscreen))
c = d; c = d;
@@ -273,7 +266,7 @@ client_focus(Client *c)
if((sel = c)) if((sel = c))
{ {
/* Set focusontag option */ /* Set focusontag option */
for(cc = clients; cc; cc = cc->next) SLIST_FOREACH(cc, &clients, next)
if(cc->focusontag == (int)c->tag) if(cc->focusontag == (int)c->tag)
cc->focusontag = -1; cc->focusontag = -1;
@@ -302,13 +295,13 @@ client_focus(Client *c)
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
if(conf.bars.selbar) if(conf.bars.selbar)
infobar_draw_selbar(&infobar[sel->screen]); _infobar_draw(&infobar[sel->screen]);
} }
else else
{ {
XSetInputFocus(dpy, ROOT, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, ROOT, RevertToPointerRoot, CurrentTime);
if(conf.bars.selbar) if(conf.bars.selbar)
infobar_draw_selbar(&infobar[selscreen]); _infobar_draw(&infobar[selscreen]);
} }
return; return;
@@ -338,10 +331,10 @@ client_urgent(Client *c, bool u)
*/ */
Client* client_gb_win(Window w) Client* client_gb_win(Window w)
{ {
Client *c = clients; Client *c = SLIST_FIRST(&clients);
while(c && c->win != w) while(c && c->win != w)
c = c->next; c = SLIST_NEXT(c, next);
return c; return c;
} }
@@ -352,10 +345,10 @@ client_urgent(Client *c, bool u)
*/ */
Client* client_gb_frame(Window w) Client* client_gb_frame(Window w)
{ {
Client *c = clients; Client *c = SLIST_FIRST(&clients);
while(c && c->frame != w) while(c && c->frame != w)
c = c->next; c = SLIST_NEXT(c, next);
return c; return c;
} }
@@ -366,13 +359,13 @@ client_urgent(Client *c, bool u)
*/ */
Client* client_gb_titlebar(Window w) Client* client_gb_titlebar(Window w)
{ {
Client *c = clients; Client *c = SLIST_FIRST(&clients);
if(!(TBARH - BORDH)) if(!(TBARH - BORDH))
return NULL; return NULL;
while(c && c->titlebar->win != w) while(c && c->titlebar->win != w)
c = c->next; c = SLIST_NEXT(c, next);
return c; return c;
} }
@@ -383,10 +376,10 @@ client_urgent(Client *c, bool u)
*/ */
Client* client_gb_resize(Window w) Client* client_gb_resize(Window w)
{ {
Client *c = clients; Client *c = SLIST_FIRST(&clients);
while(c && (c->resize[Right] != w) && (c->resize[Left] != w)) while(c && (c->resize[Right] != w) && (c->resize[Left] != w))
c = c->next; c = SLIST_NEXT(c, next);
return c; return c;
} }
@@ -398,13 +391,13 @@ client_urgent(Client *c, bool u)
*/ */
Client* client_gb_button(Window w, int *n) Client* client_gb_button(Window w, int *n)
{ {
Client *c = clients; Client *c;
int i; int i;
if(!BUTTONWH || !(TBARH - BORDH)) if(!BUTTONWH || !(TBARH - BORDH))
return NULL; return NULL;
for(; c; c = c->next) SLIST_FOREACH(c, &clients, next)
for(i = 0; i < conf.titlebar.nbutton; ++i) for(i = 0; i < conf.titlebar.nbutton; ++i)
if(c->button[i] == w) if(c->button[i] == w)
{ {
@@ -422,17 +415,16 @@ client_urgent(Client *c, bool u)
*/ */
Client* client_gb_pos(Client *c, int x, int y) Client* client_gb_pos(Client *c, int x, int y)
{ {
Client *cc = clients; Client *cc;
if((x | y) < 0 || x > spgeo[c->screen].x + spgeo[c->screen].width if((x | y) < 0 || x > spgeo[c->screen].x + spgeo[c->screen].width
|| y > spgeo[c->screen].y + spgeo[c->screen].height) || y > spgeo[c->screen].y + spgeo[c->screen].height)
return NULL; return NULL;
for(; cc; cc = cc->next) SLIST_FOREACH(cc, &clients, next)
if(cc != c && cc->screen == c->screen && cc->tag == c->tag if(cc != c && cc->screen == c->screen && cc->tag == c->tag
&& (cc->flags & TileFlag)) && (cc->flags & TileFlag))
if(cc->frame_geo.x < x && cc->frame_geo.x + cc->frame_geo.width > x if(INAREA(x, y, cc->frame_geo))
&& cc->frame_geo.y < y && cc->frame_geo.y + cc->frame_geo.height > y)
return cc; return cc;
return c; return c;
@@ -468,7 +460,7 @@ client_get_name(Client *c)
frame_update(c); frame_update(c);
if(conf.bars.selbar && c == sel) if(conf.bars.selbar && c == sel)
infobar_draw_selbar(&infobar[c->screen]); _infobar_draw(&infobar[c->screen]);
return; return;
} }
@@ -597,6 +589,7 @@ client_set_rules(Client *c)
ulong n, il; ulong n, il;
uchar *data = NULL; uchar *data = NULL;
char wwrole[256] = { 0 }; char wwrole[256] = { 0 };
char netwmname[256] = { 0 };
bool applied_tag_rule = False; bool applied_tag_rule = False;
bool applied_screen_rule = False; bool applied_screen_rule = False;
@@ -619,14 +612,24 @@ client_set_rules(Client *c)
XFree(data); XFree(data);
} }
/* Apply Rule if class || instance || role match */ /* Get _NET_WM_NAME */
if(XGetWindowProperty(dpy, c->win, ATOM("_NET_WM_NAME"), 0, 0x77777777, False,
ATOM("UTF8_STRING"), &rf, &f, &n, &il, &data) == Success && data)
{
strncpy(netwmname, (char*)data, sizeof(netwmname));
XFree(data);
}
/* Apply Rule if class || instance || role || name match */
for(i = 0; i < conf.nrule; ++i) for(i = 0; i < conf.nrule; ++i)
{ {
if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class)) if((xch.res_class && conf.rule[i].class && !strcmp(xch.res_class, conf.rule[i].class))
|| (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance))) || (xch.res_name && conf.rule[i].instance && !strcmp(xch.res_name, conf.rule[i].instance)))
{ {
if((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role)) if(((strlen(wwrole) && conf.rule[i].role && !strcmp(wwrole, conf.rule[i].role))
|| (!strlen(wwrole) || !conf.rule[i].role)) || (!strlen(wwrole) || !conf.rule[i].role))
&& ((strlen(netwmname) && conf.rule[i].name && !strcmp(netwmname, conf.rule[i].name))
|| (!strlen(netwmname) || !conf.rule[i].name)))
{ {
if(conf.rule[i].screen != -1) if(conf.rule[i].screen != -1)
c->screen = conf.rule[i].screen; c->screen = conf.rule[i].screen;
@@ -649,7 +652,7 @@ client_set_rules(Client *c)
client_maximize(c); client_maximize(c);
} }
if(c->tag != (uint)seltag[selscreen]) if(c->tag != seltag[selscreen])
{ {
tags[c->screen][c->tag].flags |= RequestUpdateFlag; tags[c->screen][c->tag].flags |= RequestUpdateFlag;
client_focus(NULL); client_focus(NULL);
@@ -755,7 +758,7 @@ client_manage(Window w, XWindowAttributes *wa, bool ar)
tags[c->screen][c->tag].flags |= CleanFactFlag; tags[c->screen][c->tag].flags |= CleanFactFlag;
cfactor_clean(c); cfactor_clean(c);
at.event_mask = PropertyChangeMask; at.event_mask = EnterWindowMask | LeaveWindowMask | StructureNotifyMask | PropertyChangeMask;
frame_create(c); frame_create(c);
client_size_hints(c); client_size_hints(c);
@@ -767,7 +770,7 @@ client_manage(Window w, XWindowAttributes *wa, bool ar)
/* Transient for tag setting */ /* Transient for tag setting */
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
for(t = clients; t && t->win != trans; t = t->next); for(t = SLIST_FIRST(&clients); t && t->win != trans; t = SLIST_NEXT(t, next));
if(t) if(t)
{ {
@@ -783,7 +786,7 @@ client_manage(Window w, XWindowAttributes *wa, bool ar)
client_set_rules(c); client_set_rules(c);
client_get_name(c); client_get_name(c);
if(c->tag == (uint)seltag[selscreen]) if(c->tag == seltag[selscreen])
{ {
client_raise(c); client_raise(c);
client_map(c); client_map(c);
@@ -804,7 +807,7 @@ client_manage(Window w, XWindowAttributes *wa, bool ar)
if(!conf.client.set_new_win_master) if(!conf.client.set_new_win_master)
layout_set_client_master(c); layout_set_client_master(c);
if(c->tag == (uint)seltag[selscreen]) if(c->tag == seltag[selscreen])
client_focus(c); client_focus(c);
if(conf.client.new_client_get_mouse) if(conf.client.new_client_get_mouse)
@@ -1146,16 +1149,13 @@ client_unhide(Client *c)
void void
client_focus_next(Client *c) client_focus_next(Client *c)
{ {
Client *c_next = NULL; Client *c_next = SLIST_FIRST(&clients);
for(c_next = clients; for(; c_next && c_next->tag != c->tag && c_next->screen != c->screen;
c_next && c_next != c->prev c_next = SLIST_NEXT(c_next, next));
&& c_next->tag != c->tag
&& c_next->screen != c->screen;
c_next = c_next->next);
if(c_next && c_next->tag == (uint)seltag[selscreen] if(c_next && c_next->tag == seltag[selscreen]
&& c_next->screen == selscreen) && c_next->screen == selscreen)
client_focus(c_next); client_focus(c_next);
return; return;
@@ -1204,7 +1204,7 @@ client_unmanage(Client *c)
{ {
/* Arrange */ /* Arrange */
for(i = 0; i < screen_count() && !b; ++i) for(i = 0; i < screen_count() && !b; ++i)
if(c->tag == (uint)seltag[i]) if(c->tag == seltag[i])
{ {
b = True; b = True;
break; break;
@@ -1421,7 +1421,7 @@ uicb_client_select(uicb_t cmd)
if(clist_index[i].client->screen != selscreen) if(clist_index[i].client->screen != selscreen)
screen_set_sel(clist_index[i].client->screen); screen_set_sel(clist_index[i].client->screen);
if(clist_index[i].client->tag != (uint)seltag[clist_index[i].client->screen]) if(clist_index[i].client->tag != seltag[clist_index[i].client->screen])
tag_set(clist_index[i].client->tag); tag_set(clist_index[i].client->tag);
client_focus(clist_index[i].client); client_focus(clist_index[i].client);
@@ -1443,8 +1443,8 @@ uicb_client_select(uicb_t cmd)
void void
uicb_clientlist(uicb_t cmd) uicb_clientlist(uicb_t cmd)
{ {
int i, d, u, x, y; int d, u, x, y;
int n = 0; int n = 0, i = 0;
bool all = False; bool all = False;
Window w; Window w;
Client *c = NULL; Client *c = NULL;
@@ -1454,7 +1454,7 @@ uicb_clientlist(uicb_t cmd)
if(cmd && !strcmp(cmd, "all")) if(cmd && !strcmp(cmd, "all"))
all = True; all = True;
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(!ishide(c, selscreen) || all) if(!ishide(c, selscreen) || all)
++n; ++n;
@@ -1472,7 +1472,7 @@ uicb_clientlist(uicb_t cmd)
clientlist.align = MA_Left; clientlist.align = MA_Left;
for(i = 0, c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(!ishide(c, selscreen) || all) if(!ishide(c, selscreen) || all)
{ {
sprintf(clist_index[i].key, "%d", i); sprintf(clist_index[i].key, "%d", i);
@@ -1530,7 +1530,7 @@ uicb_client_ignore_tag(uicb_t cmd)
void void
uicb_client_set_master(uicb_t cmd) uicb_client_set_master(uicb_t cmd)
{ {
Client *c; Client *c = SLIST_FIRST(&clients);
(void)cmd; (void)cmd;
/* get the first client */ /* get the first client */
@@ -1538,7 +1538,7 @@ uicb_client_set_master(uicb_t cmd)
if(!sel || ishide(sel, selscreen)) if(!sel || ishide(sel, selscreen))
return; return;
for(c = clients; c && ishide(c, selscreen); c = c->next); for(; c && ishide(c, selscreen); c = SLIST_NEXT(c, next));
if (c && c != sel) if (c && c != sel)
{ {

View File

@@ -183,8 +183,6 @@ conf_misc_section(void)
conf.focus_fmouse = fetch_opt_first(sec, "true", "focus_follow_mouse").boolean; conf.focus_fmouse = fetch_opt_first(sec, "true", "focus_follow_mouse").boolean;
conf.focus_fmov = fetch_opt_first(sec, "false", "focus_follow_movement").boolean; conf.focus_fmov = fetch_opt_first(sec, "false", "focus_follow_movement").boolean;
conf.focus_pclick = fetch_opt_first(sec, "true", "focus_pointer_click").boolean; conf.focus_pclick = fetch_opt_first(sec, "true", "focus_pointer_click").boolean;
conf.status_timing = fetch_opt_first(sec, "1", "status_timing").num;
conf.status_path = fetch_opt_first(sec, "", "status_path").str;
conf.autostart_path = fetch_opt_first(sec, "", "autostart_path").str; conf.autostart_path = fetch_opt_first(sec, "", "autostart_path").str;
conf.autostart_command = fetch_opt_first(sec, "", "autostart_command").str; conf.autostart_command = fetch_opt_first(sec, "", "autostart_command").str;
pad = fetch_opt_first(sec, "12", "pad").num; pad = fetch_opt_first(sec, "12", "pad").num;
@@ -203,12 +201,6 @@ conf_misc_section(void)
conf.pad = pad; conf.pad = pad;
if(conf.status_timing < 0)
{
warnx("configuration : status_timing value (%d) incorrect.", conf.status_timing);
conf.status_timing = 1;
}
return; return;
} }
@@ -225,10 +217,11 @@ conf_bar_section(void)
conf.bars.height = fetch_opt_first(bar, "-1", "height").num; conf.bars.height = fetch_opt_first(bar, "-1", "height").num;
conf.colors.bar = getcolor((barbg = fetch_opt_first(bar, "#000000", "bg").str)); conf.colors.bar = getcolor((barbg = fetch_opt_first(bar, "#000000", "bg").str));
conf.colors.text = fetch_opt_first(bar, "#ffffff", "fg").str; conf.colors.text = fetch_opt_first(bar, "#ffffff", "fg").str;
conf.colors.bar_light_shade = fetch_opt_first(bar, "0.25", "light_shade").fnum; conf.colors.bar_light_shade = fetch_opt_first(bar, "0.25", "light_shade").fnum;
conf.colors.bar_dark_shade = fetch_opt_first(bar, "-0.25", "dark_shade").fnum; conf.colors.bar_dark_shade = fetch_opt_first(bar, "-0.25", "dark_shade").fnum;
conf.bars.element_order = fetch_opt_first(bar, "tls", "elements_order").str;
mouse = fetch_section(bar, "mouse"); mouse = fetch_section(bar, "mouse");
if ((conf.bars.nmouse = fetch_section_count(mouse)) > 0) if ((conf.bars.nmouse = fetch_section_count(mouse)) > 0)
@@ -450,9 +443,6 @@ conf_layout_section(void)
if((tmp = fetch_opt_first(layouts, "menu", "system").str) && !strcmp(tmp, "menu")) if((tmp = fetch_opt_first(layouts, "menu", "system").str) && !strcmp(tmp, "menu"))
conf.layout_system = True; conf.layout_system = True;
if((tmp = fetch_opt_first(layouts, "right", "placement").str) && !strcmp(tmp, "left"))
conf.layout_placement = True;
layout = fetch_section(layouts, "layout"); layout = fetch_section(layouts, "layout");
conf.nlayout = fetch_section_count(layout); conf.nlayout = fetch_section_count(layout);
@@ -686,6 +676,7 @@ conf_rule_section(void)
conf.rule[i].class = fetch_opt_first(rule[i], "", "class").str; conf.rule[i].class = fetch_opt_first(rule[i], "", "class").str;
conf.rule[i].instance = fetch_opt_first(rule[i], "", "instance").str; conf.rule[i].instance = fetch_opt_first(rule[i], "", "instance").str;
conf.rule[i].role = fetch_opt_first(rule[i], "", "role").str; conf.rule[i].role = fetch_opt_first(rule[i], "", "role").str;
conf.rule[i].name = fetch_opt_first(rule[i], "", "name").str;
conf.rule[i].screen = fetch_opt_first(rule[i], "-1", "screen").num; conf.rule[i].screen = fetch_opt_first(rule[i], "-1", "screen").num;
conf.rule[i].tag = fetch_opt_first(rule[i], "-1", "tag").num; conf.rule[i].tag = fetch_opt_first(rule[i], "-1", "tag").num;
conf.rule[i].free = fetch_opt_first(rule[i], "false", "free").boolean; conf.rule[i].free = fetch_opt_first(rule[i], "false", "free").boolean;

View File

@@ -77,21 +77,43 @@ draw_image(Drawable dr, int x, int y, int w, int h, char *name)
* --> \i[x;y;w;h;name]\ * --> \i[x;y;w;h;name]\
*\param im ImageAttr pointer, image properties *\param im ImageAttr pointer, image properties
*\param str String *\param str String
*\param m Check dynamic mouse
*\return n Lenght of i *\return n Lenght of i
*/ */
static int static void
parse_image_block(Drawable dr, char *str) parse_image_block(Drawable dr, char *str, bool m)
{ {
ImageAttr im; ImageAttr im;
char as; Geo area;
int i, j, k; char as, mouse[512] = { 0 };
int i = 0, j = 0, k = 0, n;
for(i = j = 0; i < (int)strlen(str); ++i, ++j) for(; i < (int)strlen(str); ++i, ++j)
if(sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^]]]%c", &im.x, &im.y, &im.w, &im.h, im.name, &as) == 6 if(((n = sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^];]]%c",
&im.x, &im.y, &im.w, &im.h, im.name, &as)) == 6
|| (n = sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^;];%512[^]]]%c",
&im.x, &im.y, &im.w, &im.h, im.name, mouse, &as)) == 7)
&& as == '\\') && as == '\\')
{ {
draw_image(dr, im.x - sw, im.y, im.w, im.h, im.name); draw_image(dr, im.x - sw, im.y, im.w, im.h, im.name);
/* Etablish clickable area on image (on infobar wins only (status mouse bind) */
if(n == 7 && m)
{
area.x = im.x - sw;
area.y = im.y;
area.width = im.w;
area.height = im.h;
/* Associate drawable with window; travel infobars */
for(; k < screen_count(); ++k)
if(infobar[k].bar->dr == dr)
{
statustext_mouse(mouse, area, &infobar[k]);
break;
}
}
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i); for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
} }
else if(j != i) else if(j != i)
@@ -128,7 +150,7 @@ draw_text(Drawable d, int x, int y, char* fg, char *str)
ostr = xstrdup(str); ostr = xstrdup(str);
textlen = strlen(ostr); textlen = strlen(ostr);
parse_image_block(d, str); parse_image_block(d, str, True);
} }
#endif /* HAVE_IMLIB */ #endif /* HAVE_IMLIB */
@@ -230,7 +252,7 @@ textw(char *text)
{ {
ostr = xstrdup(text); ostr = xstrdup(text);
textlen = strlen(ostr); textlen = strlen(ostr);
parse_image_block(d, text); parse_image_block(d, text, False);
} }
#endif /* HAVE_IMLIB */ #endif /* HAVE_IMLIB */

View File

@@ -33,6 +33,26 @@
#include "wmfs.h" #include "wmfs.h"
#define EVDPY (e->xany.display) #define EVDPY (e->xany.display)
#define MAX_EV 256
/** Check mouse bind condition and execute associated function
*/
static void
do_mousebind(int screen, uint button, int n, MouseBinding m[])
{
int i = 0;
for(; i < n; ++i)
{
if(m[i].screen == screen || m[i].screen < 0) /* Screen */
if(m[i].tag == seltag[i] || m[i].tag < 0) /* Tag */
if(m[i].button == button) /* Button */
if(m[i].func) /* Function */
m[i].func(m[i].cmd);
}
return;
}
/** ButtonPress handle event /** ButtonPress handle event
*/ */
@@ -40,14 +60,18 @@ static void
buttonpress(XEvent *e) buttonpress(XEvent *e)
{ {
XButtonEvent *ev = &e->xbutton; XButtonEvent *ev = &e->xbutton;
StatusMouse *sm;
InfoBar *ib;
Client *c; Client *c;
int i, j, n; int i, n;
screen_get_sel(); screen_get_sel();
ib = &infobar[selscreen];
/* If the mouse is on a not selected client and you click on it. */ /* If the mouse is on a not selected client and you click on it. */
if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window))) && c != sel if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window)))
&& (ev->button == Button1 || ev->button == Button2 || ev->button == Button3)) && c != sel && ev->button >= Button1 && ev->button <= Button3)
{ {
client_focus(c); client_focus(c);
client_raise(c); client_raise(c);
@@ -57,10 +81,7 @@ buttonpress(XEvent *e)
/* Titlebar */ /* Titlebar */
if((c = client_gb_titlebar(ev->window)) && c == sel) if((c = client_gb_titlebar(ev->window)) && c == sel)
for(i = 0; i < conf.titlebar.nmouse; ++i) do_mousebind(selscreen, ev->button, conf.titlebar.nmouse, conf.titlebar.mouse);
if(ev->button == conf.titlebar.mouse[i].button)
if(conf.titlebar.mouse[i].func)
conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd);
/* Titlebar buttons */ /* Titlebar buttons */
if((c = client_gb_button(ev->window, &n))) if((c = client_gb_button(ev->window, &n)))
@@ -78,86 +99,68 @@ buttonpress(XEvent *e)
/* Client */ /* Client */
if((c = client_gb_win(ev->window)) && c == sel) if((c = client_gb_win(ev->window)) && c == sel)
for(i = 0; i < conf.client.nmouse; ++i) do_mousebind(selscreen, ev->button, conf.client.nmouse, conf.client.mouse);
if(ev->button == conf.client.mouse[i].button)
if(conf.client.mouse[i].func)
conf.client.mouse[i].func(conf.client.mouse[i].cmd);
/* Root */ /* Root */
if(ev->window == ROOT) if(ev->window == ROOT)
for(i = 0; i < conf.root.nmouse; ++i) do_mousebind(selscreen, ev->button, conf.root.nmouse, conf.root.mouse);
if(conf.root.mouse[i].tag == seltag[conf.root.mouse[i].screen]
|| conf.root.mouse[i].tag < 0)
if(ev->button == conf.root.mouse[i].button)
if(conf.root.mouse[i].func)
conf.root.mouse[i].func(conf.root.mouse[i].cmd);
/* Infobars */ /* Infobars */
for(i = 0; i < screen_count(); ++i) for(i = 0; i < screen_count(); ++i)
if(ev->window == infobar[i].bar->win) if(ev->window == infobar[i].bar->win)
for(j = 0; j < conf.bars.nmouse; ++j) do_mousebind(i, ev->button, conf.bars.nmouse, conf.bars.mouse);
if(conf.bars.mouse[j].screen == i
|| conf.bars.mouse[j].screen < 0)
if(conf.bars.mouse[j].tag == seltag[i]
|| conf.bars.mouse[j].tag < 0)
if(ev->button == conf.bars.mouse[j].button)
if(conf.bars.mouse[j].func)
conf.bars.mouse[j].func(conf.bars.mouse[j].cmd);
/* Selbar */ /* Selbar */
if(conf.bars.selbar && ev->window == infobar[selscreen].selbar->win) if(conf.bars.selbar && ev->window == ib->bar->win)
for(i = 0; i < conf.selbar.nmouse; ++i) if(INAREA(ev->x, ev->y, ib->selbar_geo))
if(conf.selbar.mouse[i].tag == seltag[conf.selbar.mouse[i].screen] do_mousebind(selscreen, ev->button, conf.selbar.nmouse, conf.selbar.mouse);
|| conf.selbar.mouse[i].tag < 0)
if(ev->button == conf.selbar.mouse[i].button)
if(conf.selbar.mouse[i].func)
conf.selbar.mouse[i].func(conf.selbar.mouse[i].cmd);
/* Tags */ /* Tags */
for(i = 1; i < conf.ntag[selscreen] + 1; ++i) if(ib->tags_board)
if(ev->window == infobar[selscreen].tags[i]->win) {
{ for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
for(j = 0; j < tags[selscreen][i].nmouse; ++j) if(ib->tags[i] && ev->window == ib->tags[i]->win)
if(ev->button == tags[selscreen][i].mouse[j].button) {
if(tags[selscreen][i].mouse[j].func) do_mousebind(selscreen, ev->button, tags[selscreen][i].nmouse, tags[selscreen][i].mouse);
tags[selscreen][i].mouse[j].func(tags[selscreen][i].mouse[j].cmd);
/* Mouse button action on tag */ /* Mouse button action on tag */
if(ev->button == conf.mouse_tag_action[TagSel]) if(ev->button == conf.mouse_tag_action[TagSel])
tag_set(i); tag_set(i);
else if(ev->button == conf.mouse_tag_action[TagTransfert]) else if(ev->button == conf.mouse_tag_action[TagTransfert])
tag_transfert(sel, i); tag_transfert(sel, i);
else if(ev->button == conf.mouse_tag_action[TagAdd]) else if(ev->button == conf.mouse_tag_action[TagAdd])
tag_additional(selscreen, seltag[selscreen], i); tag_additional(selscreen, seltag[selscreen], i);
else if(ev->button == conf.mouse_tag_action[TagNext]) else if(ev->button == conf.mouse_tag_action[TagNext])
tag_set(seltag[selscreen] + 1); tag_set(seltag[selscreen] + 1);
else if(ev->button == conf.mouse_tag_action[TagPrev]) else if(ev->button == conf.mouse_tag_action[TagPrev])
tag_set(seltag[selscreen] - 1); tag_set(seltag[selscreen] - 1);
} }
}
/* Layout button */ /* Layout button */
if(ev->window == infobar[selscreen].layout_button->win && conf.nlayout > 1) if(ib->layout_button && ev->window == ib->layout_button->win && conf.nlayout > 1)
{ {
if(conf.layout_system && (ev->button == Button1 || ev->button == Button3)) /* True -> menu */ if(conf.layout_system && (ev->button == Button1 || ev->button == Button3)) /* True -> menu */
{ {
menulayout.y = spgeo[selscreen].y + infobar[selscreen].layout_button->geo.y + INFOBARH; menulayout.y = spgeo[selscreen].y + ib->layout_button->geo.y + INFOBARH;
menulayout.x = infobar[selscreen].layout_button->geo.x + (sgeo[selscreen].x - BORDH); menulayout.x = ib->layout_button->geo.x + (sgeo[selscreen].x - BORDH);
if(infobar[selscreen].geo.y != spgeo[selscreen].y) if(ib->geo.y != spgeo[selscreen].y)
menulayout.y = infobar[selscreen].geo.y - (INFOBARH * menulayout.nitem) - SHADH; menulayout.y = ib->geo.y - (INFOBARH * menulayout.nitem) - SHADH;
uicb_menu("menulayout"); uicb_menu("menulayout");
} }
else else
{ layoutswitch(ev->button == Button1 || ev->button == Button4);
switch(ev->button)
{
case Button1: case Button4: layoutswitch(True); break;
case Button3: case Button5: layoutswitch(False); break;
}
}
} }
/* Status mouse bindings */
SLIST_FOREACH(sm, &smhead, next)
if(sm->infobar->bar->win == ev->window && ev->button == sm->button)
if(INAREA(ev->x, ev->y, sm->area))
if(sm->func)
sm->func(sm->cmd);
return; return;
} }
@@ -168,6 +171,7 @@ clientmessageevent(XEvent *e)
{ {
XClientMessageEvent *ev = &e->xclient; XClientMessageEvent *ev = &e->xclient;
Client *c; Client *c;
InfoBar *ib;
Systray *sy; Systray *sy;
int s, mess_t = 0; int s, mess_t = 0;
Atom rt; Atom rt;
@@ -248,7 +252,10 @@ clientmessageevent(XEvent *e)
if(XGetWindowProperty(EVDPY, ROOT, net_atom[mess_t], 0, 4096, if(XGetWindowProperty(EVDPY, ROOT, net_atom[mess_t], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success) False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
{ {
statustext_handle(mess_t - wmfs_statustext, (char*)ret); ib = &infobar[mess_t - wmfs_statustext];
free(ib->statustext);
ib->statustext = xstrdup((char*)ret);
_infobar_draw(ib);
XFree(ret); XFree(ret);
} }
} }
@@ -281,10 +288,6 @@ clientmessageevent(XEvent *e)
screen_get_sel(); screen_get_sel();
} }
/* Manage _WMFS_UPDATE_STATUS */
if(mess_t == wmfs_update_status && estatus)
spawn(conf.status_path);
return; return;
} }
@@ -406,21 +409,15 @@ expose(XEvent *e)
{ {
XExposeEvent *ev = &e->xexpose; XExposeEvent *ev = &e->xexpose;
Client *c; Client *c;
int i, sc; BarWindow *bw;
/* InfoBar member */ /* BarWindows */
for(sc = 0; sc < screen_count(); ++sc) SLIST_FOREACH(bw, &bwhead, next)
{ if(ev->window == bw->win)
if(ev->window == infobar[sc].bar->win) {
barwin_refresh(infobar[sc].bar); barwin_refresh(bw);
if(ev->window == infobar[sc].layout_button->win) break;
barwin_refresh(infobar[sc].layout_button); }
if(conf.bars.selbar && ev->window == infobar[sc].selbar->win)
barwin_refresh(infobar[sc].selbar);
for(i = 1; i < conf.ntag[sc] + 1; ++i)
if(ev->window == infobar[sc].tags[i]->win)
barwin_refresh(infobar[sc].tags[i]);
}
/* Client frame */ /* Client frame */
if((c = client_gb_titlebar(ev->window))) if((c = client_gb_titlebar(ev->window)))
@@ -684,13 +681,9 @@ grabkeys(void)
void void
event_make_array(void) event_make_array(void)
{ {
int i = LASTEvent; int i = MAX_EV;
#ifdef HAVE_XRANDR event_handle = xcalloc(MAX_EV, sizeof(event_handle));
i = xrandr_event + RRScreenChangeNotify;
#endif /* HAVE_XRANDR */
event_handle = xcalloc((nevent = i + 1), sizeof(event_handle));
/* Fill array with non-used function (do nothing) */ /* Fill array with non-used function (do nothing) */
while(i--) while(i--)

View File

@@ -95,7 +95,6 @@ ewmh_init_hints(void)
/* WMFS hints */ /* WMFS hints */
net_atom[wmfs_running] = ATOM("_WMFS_RUNNING"); net_atom[wmfs_running] = ATOM("_WMFS_RUNNING");
net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS"); net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS");
net_atom[wmfs_update_status] = ATOM("_WMFS_UPDATE_STATUS");
net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN"); net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN");
net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT"); net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT");
net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG"); net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG");
@@ -251,13 +250,16 @@ ewmh_get_client_list(void)
{ {
Window *list; Window *list;
Client *c; Client *c;
int win_n; int win_n = 0;
SLIST_FOREACH(c, &clients, next)
++win_n;
for(win_n = 0, c = clients; c; c = c->next, ++win_n);
list = xcalloc(win_n, sizeof(Window)); list = xcalloc(win_n, sizeof(Window));
for(win_n = 0, c = clients; c; c = c->next, ++win_n) win_n = 0;
list[win_n] = c->win; SLIST_FOREACH(c, &clients, next)
list[win_n++] = c->win;
XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32, XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32,
PropModeReplace, (uchar *)list, win_n); PropModeReplace, (uchar *)list, win_n);

View File

@@ -34,105 +34,184 @@
#define SPLIT_IND_S (3 + conf.border.layout) #define SPLIT_IND_S (3 + conf.border.layout)
/** Init InfoBar elements
*/
static void
infobar_init_element(InfoBar *i)
{
int j = 0, k, n = 0;
InfobarElem *e, *prev = NULL;
Geo pg = { -PAD, 0, 0, 0 };
STAILQ_INIT(&i->elemhead);
for(; n < (int)strlen(i->elemorder); ++n)
{
e = zcalloc(sizeof(InfobarElem));
/* Previous element geo */
if(prev)
pg = prev->geo;
e->geo.x = pg.x + pg.width + PAD;
e->geo.y = 0;
e->geo.height = i->geo.height;
switch(i->elemorder[n])
{
/* Tags element */
case 't':
e->type = ElemTag;
e->geo.width = PAD; /* Will change */
if(!i->tags_board)
{
i->tags_board = barwin_create(i->bar->win,
e->geo.x,
e->geo.y,
e->geo.width,
e->geo.height,
conf.colors.bar, conf.colors.text,
False, False, False);
/* Create tags window */
for(k = 1; k < conf.ntag[i->screen] + 1; ++k)
{
i->tags[k] = barwin_create(i->tags_board->win,
j, 0,
textw(tags[i->screen][k].name) + PAD,
i->geo.height,
conf.colors.bar, conf.colors.text,
False, False, conf.border.tag);
j += textw(tags[i->screen][k].name) + PAD;
barwin_map_subwin(i->tags[k]);
}
}
barwin_resize(i->tags_board, (e->geo.width = j), i->geo.height);
barwin_map(i->tags_board);
barwin_map_subwin(i->tags_board);
break;
/* Layout button element */
case 'l':
e->type = ElemLayout;
e->geo.width = (conf.layout_button_width > 0
? (uint)conf.layout_button_width
: textw(tags[i->screen][seltag[i->screen]].layout.symbol) + PAD);
if(!i->layout_button)
i->layout_button = barwin_create(i->bar->win,
e->geo.x,
e->geo.y,
e->geo.width,
e->geo.height,
conf.colors.layout_bg, conf.colors.layout_fg,
False, False, conf.border.layout);
barwin_map(i->layout_button);
if(conf.border.layout)
barwin_map_subwin(i->layout_button);
break;
/* Selbar element */
case 's':
e->type = ElemSelbar;
i->selbar_geo = e->geo;
break;
}
STAILQ_INSERT_TAIL(&i->elemhead, e, next);
prev = e;
e = NULL;
}
return;
}
/** Init the InfoBar /** Init the InfoBar
*/ */
void void
infobar_init(void) infobar_init(void)
{ {
int s, sc, i, j = 0; InfoBar *i;
int s = screen_count(), sc = 0;
s = screen_count();
if(!infobar) if(!infobar)
infobar = xcalloc(s, sizeof(InfoBar)); infobar = xcalloc(s, sizeof(InfoBar));
for(sc = 0; sc < s; ++sc) for(; sc < s; ++sc)
{ {
j = 0; i = &infobar[sc];
infobar[sc].geo.height = INFOBARH; i->geo.height = INFOBARH;
infobar[sc].screen = sc; i->screen = sc;
i->elemorder = conf.bars.element_order;
switch(tags[sc][seltag[sc]].barpos) switch(tags[sc][seltag[sc]].barpos)
{ {
case IB_Hide: case IB_Hide:
sgeo[sc].y = spgeo[sc].y + TBARH; sgeo[sc].y = spgeo[sc].y + TBARH;
sgeo[sc].height += INFOBARH; sgeo[sc].height += INFOBARH;
infobar[sc].geo.y = (-(infobar[sc].geo.height) << 2); i->geo.y = (-(i->geo.height) << 2);
break; break;
case IB_Bottom: case IB_Bottom:
sgeo[sc].y = TBARH; sgeo[sc].y = TBARH;
infobar[sc].geo.y = spgeo[sc].y + sgeo[sc].height + TBARH; i->geo.y = spgeo[sc].y + sgeo[sc].height + TBARH;
break; break;
default: default:
case IB_Top: case IB_Top:
sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH; sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH;
infobar[sc].geo.y = spgeo[sc].y; i->geo.y = spgeo[sc].y;
break; break;
} }
/* Create infobar barwindow */ /* Create infobar barwindow */
infobar[sc].bar = barwin_create(ROOT, sgeo[sc].x - BORDH, infobar[sc].geo.y, i->bar = barwin_create(ROOT,
sgeo[sc].width, infobar[sc].geo.height, sgeo[sc].x - BORDH,
conf.colors.bar, conf.colors.text, False, False, conf.border.bar); i->geo.y,
sgeo[sc].width,
i->geo.height,
conf.colors.bar, conf.colors.text,
False, False, conf.border.bar);
infobar[sc].tags_board = barwin_create(infobar[sc].bar->win, barwin_map(i->bar);
((conf.layout_placement) ? textw(tags[sc][seltag[sc]].layout.symbol) + PAD * 1.5: 0), 0, barwin_map_subwin(i->bar);
textw(tags[sc][0].name) + PAD, /* Base size, will change */ barwin_refresh_color(i->bar);
infobar[sc].geo.height, barwin_refresh(i->bar);
conf.colors.bar, conf.colors.text, False, False, False);
/* Create tags window */ /* Init elements */
for(i = 1; i < conf.ntag[sc] + 1; ++i) infobar_init_element(i);
{
infobar[sc].tags[i] = barwin_create(infobar[sc].tags_board->win, j, 0,
textw(tags[sc][i].name) + PAD,
infobar[sc].geo.height,
conf.colors.bar, conf.colors.text, False, False, conf.border.tag);
j += textw(tags[sc][i].name) + PAD;
barwin_resize(infobar[sc].tags_board, j, infobar[sc].geo.height);
barwin_map_subwin(infobar[sc].tags[i]);
}
/* Create layout switch barwindow */
infobar[sc].layout_button = barwin_create(infobar[sc].bar->win,
((conf.layout_placement) ? 0 : (j + (PAD >> 1))), 0,
((conf.layout_button_width > 0) ? (uint)conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)),
infobar[sc].geo.height,
conf.colors.layout_bg, conf.colors.layout_fg,
False, False, conf.border.layout);
/* Selbar */
if(conf.bars.selbar)
infobar[sc].selbar = barwin_create(infobar[sc].bar->win,
((conf.layout_placement)
? (j + (PAD >> 1))
: infobar[sc].layout_button->geo.x + infobar[sc].layout_button->geo.width + (PAD >> 1)), 1,
(sel) ? textw(sel->title) + PAD : 1,
infobar[sc].geo.height - 2,
conf.selbar.bg, conf.selbar.fg, False, False, False);
/* Map/Refresh all */
barwin_map(infobar[sc].bar);
barwin_map_subwin(infobar[sc].bar);
barwin_map(infobar[sc].tags_board);
barwin_map_subwin(infobar[sc].tags_board);
if(conf.border.layout)
barwin_map_subwin(infobar[sc].layout_button);
if(conf.bars.selbar)
barwin_map(infobar[sc].selbar);
barwin_refresh_color(infobar[sc].bar);
barwin_refresh(infobar[sc].bar);
/* Default statustext is set here */ /* Default statustext is set here */
infobar[sc].statustext = xstrdup("wmfs"WMFS_VERSION); i->statustext = xstrdup("wmfs"WMFS_VERSION);
infobar_draw(&infobar[sc]); infobar_draw(i);
}
return;
}
static void
infobar_arrange_element(InfoBar *i)
{
Geo pg = { -PAD, 0, 0, 0 };
InfobarElem *e, *pe = NULL;
STAILQ_FOREACH(e, &i->elemhead, next)
{
if(pe)
pg = pe->geo;
e->geo.x = pg.x + pg.width + PAD;
e->geo.y = 0;
if(e->type != ElemSelbar)
barwin_move((e->type == ElemTag ? i->tags_board : i->layout_button), e->geo.x, e->geo.y);
pe = e;
} }
return; return;
@@ -144,28 +223,52 @@ infobar_init(void)
void void
infobar_draw_layout(InfoBar *i) infobar_draw_layout(InfoBar *i)
{ {
int w, sc = i->screen; InfobarElem *e;
int s = i->screen;
if(!conf.layout_placement) /* Check if there is element in string element list */
barwin_move(i->layout_button, i->tags_board->geo.width + (PAD >> 1), 0); if(!strchr(i->elemorder, 'l'))
return;
w = (conf.layout_button_width > 0) STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemLayout)
break;
e->geo.width = (conf.layout_button_width >= 1)
? conf.layout_button_width ? conf.layout_button_width
: textw(tags[sc][seltag[sc]].layout.symbol) + PAD; : (int)(textw(tags[s][seltag[s]].layout.symbol) + PAD);
barwin_resize(i->layout_button, w, i->geo.height); barwin_resize(i->layout_button, e->geo.width, e->geo.height);
barwin_refresh_color(i->layout_button); barwin_refresh_color(i->layout_button);
/* Split mode indicator; little rectangle at bottom-right */ /* Split mode indicator; little rectangle at bottom-right */
if(tags[sc][seltag[sc]].flags & SplitFlag) if(tags[s][seltag[s]].flags & SplitFlag)
draw_rectangle(i->layout_button->dr, draw_rectangle(i->layout_button->dr,
w - SPLIT_IND_S, e->geo.width - SPLIT_IND_S,
i->geo.height - SPLIT_IND_S, e->geo.height - SPLIT_IND_S,
SPLIT_IND_S, SPLIT_IND_S, SPLIT_IND_S, SPLIT_IND_S,
getcolor(i->layout_button->fg)); getcolor(i->layout_button->fg));
if(tags[sc][seltag[sc]].layout.symbol) if(tags[s][seltag[s]].layout.symbol)
barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[sc][seltag[sc]].layout.symbol); barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[s][seltag[s]].layout.symbol);
return;
}
/** Draw Infobar barwin (selbar / statustext)
*\param i Infobar pointer
*/
void
_infobar_draw(InfoBar *i)
{
barwin_refresh_color(i->bar);
infobar_draw_selbar(i);
statustext_handle(i);
barwin_refresh(i->bar);
infobar_arrange_element(i);
return; return;
} }
@@ -178,9 +281,8 @@ infobar_draw(InfoBar *i)
{ {
infobar_draw_taglist(i); infobar_draw_taglist(i);
infobar_draw_layout(i); infobar_draw_layout(i);
infobar_draw_selbar(i);
barwin_refresh_color(i->bar); _infobar_draw(i);
statustext_handle(i->screen, i->statustext);
return; return;
} }
@@ -191,44 +293,51 @@ infobar_draw(InfoBar *i)
void void
infobar_draw_selbar(InfoBar *i) infobar_draw_selbar(InfoBar *i)
{ {
InfobarElem *e;
char *str = NULL; char *str = NULL;
int s, sc = i->screen; int sc = i->screen;
bool f = False;
if(!conf.bars.selbar) if(!conf.bars.selbar)
return; return;
if(!sel || (sel && sel->screen != sc)) if(!strchr(i->elemorder, 's'))
{
barwin_unmap(i->selbar);
return; return;
}
else if(sel) if(!sel || (sel && sel->screen != sc))
barwin_map(i->selbar); return;
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemSelbar)
break;
str = sel->title;
/* Truncate string if too long */ /* Truncate string if too long */
if(conf.selbar.maxlength >= 0 && sel && sel->title) if(conf.selbar.maxlength >= 0 && sel && sel->title)
{ {
str = NULL;
str = xcalloc(conf.selbar.maxlength + 4, sizeof(char)); str = xcalloc(conf.selbar.maxlength + 4, sizeof(char));
strncpy(str, sel->title, conf.selbar.maxlength); strncpy(str, sel->title, conf.selbar.maxlength);
if(strlen(sel->title) > (size_t)conf.selbar.maxlength) if(strlen(sel->title) > (size_t)conf.selbar.maxlength)
strcat(str, "..."); strcat(str, "...");
f = True;
} }
if((s = (textw(str ? str : sel->title) + PAD)) > i->selbar->geo.width) XSetForeground(dpy, gc, conf.selbar.bg);
barwin_resize(i->selbar, s, i->geo.height - 2); XFillRectangle(dpy, i->bar->dr, gc,
e->geo.x,
e->geo.y,
(e->geo.width = textw(str) + PAD),
e->geo.height);
draw_text(i->bar->dr, e->geo.x, FHINFOBAR, conf.selbar.fg, str);
barwin_move(i->selbar, if(f)
((conf.layout_placement) free(str);
? (i->tags_board->geo.x + i->tags_board->geo.width + (PAD >> 1))
: (i->layout_button->geo.x + i->layout_button->geo.width + (PAD >> 1))), 1);
barwin_refresh_color(i->selbar); i->selbar_geo = e->geo;
barwin_draw_text(i->selbar, (PAD >> 1), FHINFOBAR - 1, ((str) ? str : sel->title));
barwin_refresh(i->selbar);
free(str);
return; return;
} }
@@ -239,21 +348,23 @@ infobar_draw_selbar(InfoBar *i)
void void
infobar_draw_taglist(InfoBar *i) infobar_draw_taglist(InfoBar *i)
{ {
int j, x, sc = i->screen; InfobarElem *e;
Client *c = NULL; Client *c;
int j = 1, x = 0, sc = i->screen;
uint occupied = 0; uint occupied = 0;
if(conf.layout_placement) if(!strchr(i->elemorder, 't'))
barwin_move(i->tags_board, return;
((conf.layout_button_width > 0)
? (uint)conf.layout_button_width
: (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)) + (PAD >> 1), 0);
for(c = clients; c; c = c->next) STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemTag)
break;
SLIST_FOREACH(c, &clients, next)
if(c->screen == sc) if(c->screen == sc)
occupied |= TagFlag(c->tag); occupied |= TagFlag(c->tag);
for(j = 1, x = 0; j < conf.ntag[sc] + 1; ++j) for(; j < conf.ntag[sc] + 1; ++j)
{ {
/* Autohide tag feature */ /* Autohide tag feature */
if(conf.tagautohide) if(conf.tagautohide)
@@ -266,7 +377,7 @@ infobar_draw_taglist(InfoBar *i)
barwin_map(i->tags[j]); barwin_map(i->tags[j]);
barwin_move(i->tags[j], x, 0); barwin_move(i->tags[j], x, 0);
barwin_resize(i->tags_board, (x += i->tags[j]->geo.width), i->geo.height); barwin_resize(i->tags_board, (e->geo.width = (x += i->tags[j]->geo.width)), e->geo.height);
} }
if(tags[sc][j].flags & TagUrgentFlag) if(tags[sc][j].flags & TagUrgentFlag)
@@ -335,6 +446,7 @@ infobar_update_taglist(InfoBar *i)
void void
infobar_destroy(void) infobar_destroy(void)
{ {
InfobarElem *e;
int sc, i; int sc, i;
for(sc = 0; sc < screen_count(); ++sc) for(sc = 0; sc < screen_count(); ++sc)
@@ -350,9 +462,17 @@ infobar_destroy(void)
barwin_delete_subwin(infobar[sc].tags_board); barwin_delete_subwin(infobar[sc].tags_board);
barwin_delete(infobar[sc].tags_board); barwin_delete(infobar[sc].tags_board);
barwin_delete(infobar[sc].selbar);
barwin_delete_subwin(infobar[sc].bar); barwin_delete_subwin(infobar[sc].bar);
barwin_delete(infobar[sc].bar); barwin_delete(infobar[sc].bar);
/* Free elements */
while(!STAILQ_EMPTY(&infobar[sc].elemhead))
{
e = STAILQ_FIRST(&infobar[sc].elemhead);
STAILQ_REMOVE_HEAD(&infobar[sc].elemhead, next);
free(e);
}
} }
return; return;
@@ -368,28 +488,27 @@ infobar_set_position(int pos)
switch(pos) switch(pos)
{ {
case IB_Hide: case IB_Hide:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH; sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - TBARH; sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
infobar[selscreen].geo.y = (-(infobar[selscreen].geo.height) << 1); infobar[selscreen].geo.y = (-(infobar[selscreen].geo.height) << 1);
break; break;
case IB_Bottom: case IB_Bottom:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH; sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH; sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH; infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH;
break; break;
default: default:
case IB_Top: case IB_Top:
sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH; sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH; sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y; infobar[selscreen].geo.y = spgeo[selscreen].y;
break; break;
} }
tags[selscreen][seltag[selscreen]].barpos = pos; tags[selscreen][seltag[selscreen]].barpos = pos;
barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y); barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y);
infobar_draw(&infobar[selscreen]);
arrange(selscreen, True); arrange(selscreen, True);
return; return;

View File

@@ -196,48 +196,17 @@ init_root(void)
return; return;
} }
/** Init statustext shell script
*/
static void
init_status(void)
{
struct stat st;
char *home;
conf.status_pid = -1;
estatus = False;
if(!conf.status_path)
{
if(!(home = getenv("HOME")))
{
warnx("HOME not set, can't launch status.sh");
return;
}
conf.status_path = zmalloc(strlen(home) + strlen(DEF_STATUS) + 2);
sprintf(conf.status_path, "%s/"DEF_STATUS, home);
}
if (stat(patht(conf.status_path), &st) == -1)
{
warn("%s", patht(conf.status_path));
return;
}
if(st.st_size && st.st_mode & S_IXUSR)
estatus = True;
else
warnx("status file specified in configuratin (status_path) or present in wmfs directory can't be executed, try 'chmod +x %s'.", patht(conf.status_path));
return;
}
/** Init WMFS /** Init WMFS
*/ */
void void
init(void) init(void)
{ {
/* Init lists heads */
SLIST_INIT(&bwhead);
SLIST_INIT(&smhead);
SLIST_INIT(&clients);
SLIST_INIT(&trayicons);
/* First init */ /* First init */
ewmh_init_hints(); ewmh_init_hints();
init_conf(); init_conf();
@@ -250,7 +219,6 @@ init(void)
event_make_array(); event_make_array();
infobar_init(); infobar_init();
systray_acquire(); systray_acquire();
init_status();
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
grabkeys(); grabkeys();

View File

@@ -189,16 +189,17 @@ launcher_execute(Launcher *launcher)
char buf[512] = { 0 }; char buf[512] = { 0 };
char tmpbuf[512] = { 0 }; char tmpbuf[512] = { 0 };
char *complete; char *complete;
int i, pos = 0, histpos = 0, x, w; int i, pos = 0, histpos = 0, w, x = 0;
int tabhits = 0; int tabhits = 0;
KeySym ks; KeySym ks;
XEvent ev; XEvent ev;
InfobarElem *e;
screen_get_sel(); screen_get_sel();
x = (conf.layout_placement) STAILQ_FOREACH(e, &infobar[selscreen].elemhead, next)
? (infobar[selscreen].tags_board->geo.x + infobar[selscreen].tags_board->geo.width) if(x < (e->geo.x + e->geo.width))
: (infobar[selscreen].layout_button->geo.x + infobar[selscreen].layout_button->geo.width); x = e->geo.x + e->geo.width + PAD;
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);

View File

@@ -42,7 +42,7 @@ arrange(int screen, bool update_layout)
if(screen < 0 || screen > screen_count() - 1) if(screen < 0 || screen > screen_count() - 1)
screen = screen_get_sel(); screen = screen_get_sel();
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->screen == screen) if(c->screen == screen)
{ {
if(!ishide(c, screen)) if(!ishide(c, screen))
@@ -87,7 +87,7 @@ freelayout(int screen)
Client *c; Client *c;
(void)screen; (void)screen;
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(!ishide(c, selscreen) if(!ishide(c, selscreen)
&& c->screen == screen && c->screen == screen
&& !(c->flags & MaxFlag)) && !(c->flags & MaxFlag))
@@ -108,12 +108,12 @@ void
layoutswitch(bool b) layoutswitch(bool b)
{ {
int i; int i;
Client *c; Client *c = SLIST_FIRST(&clients);
screen_get_sel(); screen_get_sel();
if(tags[selscreen][seltag[selscreen]].layout.func == freelayout) if(tags[selscreen][seltag[selscreen]].layout.func == freelayout)
for(c = clients; c && (c->tag != (uint)seltag[selscreen] && c->screen != selscreen); c = c->next) for(; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = SLIST_NEXT(c, next))
{ {
c->ogeo = c->geo; c->ogeo = c->geo;
c->free_geo = c->geo; c->free_geo = c->geo;
@@ -133,10 +133,12 @@ layoutswitch(bool b)
} }
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag; tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
layout_func(selscreen, seltag[selscreen]); layout_func(selscreen, seltag[selscreen]);
infobar_draw_layout(&infobar[selscreen]); infobar_draw(&infobar[selscreen]);
return; return;
} }
@@ -173,9 +175,9 @@ uicb_layout_prev(uicb_t cmd)
Client* Client*
tiled_client(int screen, Client *c) tiled_client(int screen, Client *c)
{ {
for(;c && (c->flags & (MaxFlag | FreeFlag | FSSFlag | AboveFlag) for(; c && (c->flags & (MaxFlag | FreeFlag | FSSFlag | AboveFlag)
|| c->screen != screen || c->screen != screen
|| ishide(c, screen)); c = c->next); || ishide(c, screen)); c = SLIST_NEXT(c, next));
if(c) if(c)
c->flags |= FLayFlag; c->flags |= FLayFlag;
@@ -188,10 +190,10 @@ tiled_client(int screen, Client *c)
void void
maxlayout(int screen) maxlayout(int screen)
{ {
Client *c; Client *c = tiled_client(screen, SLIST_FIRST(&clients));
int i; int i = 0;
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{ {
c->flags &= ~TileFlag; c->flags &= ~TileFlag;
c->flags |= LMaxFlag; c->flags |= LMaxFlag;
@@ -233,12 +235,12 @@ uicb_set_mwfact(uicb_t cmd)
void void
uicb_set_nmaster(uicb_t cmd) uicb_set_nmaster(uicb_t cmd)
{ {
int nc, n = atoi(cmd); int nc = 0, n = atoi(cmd);
Client *c; Client *c = tiled_client(selscreen, SLIST_FIRST(&clients));
screen_get_sel(); screen_get_sel();
for(nc = 0, c = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next), ++nc); for(; c; c = tiled_client(selscreen, SLIST_NEXT(c, next)), ++nc);
if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0 if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0
|| tags[selscreen][seltag[selscreen]].nmaster + n > nc) || tags[selscreen][seltag[selscreen]].nmaster + n > nc)
@@ -258,12 +260,12 @@ uicb_set_nmaster(uicb_t cmd)
static void static void
grid(int screen, bool horizontal) grid(int screen, bool horizontal)
{ {
Client *c; Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen]; Geo sg = sgeo[screen];
Geo cgeo = {sg.x, sg.y, 0, 0}; Geo cgeo = {sg.x, sg.y, 0, 0};
unsigned int i, n, temp, cols, rows, cpcols = 0; unsigned int i = 0, n = 0, temp, cols, rows, cpcols = 0;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n)); CHECK((tags[screen][seltag[screen]].nclients = n));
for(rows = 0; rows <= (n >> 1); ++rows) for(rows = 0; rows <= (n >> 1); ++rows)
@@ -281,7 +283,7 @@ grid(int screen, bool horizontal)
rows = temp; rows = temp;
} }
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{ {
/* Set client property */ /* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag); c->flags &= ~(MaxFlag | LMaxFlag);
@@ -327,13 +329,13 @@ grid(int screen, bool horizontal)
static void static void
multi_tile(int screen, Position type) multi_tile(int screen, Position type)
{ {
Client *c; Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen]; Geo sg = sgeo[screen];
Geo mastergeo = {sg.x, sg.y, 0, 0}; Geo mastergeo = {sg.x, sg.y, 0, 0};
Geo cgeo = {sg.x, sg.y, 0, 0}; Geo cgeo = {sg.x, sg.y, 0, 0};
uint i, n, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster; int i = 0, n = 0, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n)); CHECK((tags[screen][seltag[screen]].nclients = n));
/* FIX NMASTER */ /* FIX NMASTER */
@@ -348,16 +350,16 @@ multi_tile(int screen, Position type)
if(LDIR(type)) if(LDIR(type))
{ {
if(type == Left) if(type == Left)
mastergeo.x = (n <= nmaster) ? (uint)sg.x : (sg.x + sg.width) - mwfact - (BORDH << 1); mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH << 1);
mastergeo.width = (n <= nmaster) ? (uint)(sg.width - (BORDH << 1)) : mwfact; mastergeo.width = (n <= nmaster) ? (sg.width - (BORDH << 1)) : mwfact;
mastergeo.height = (sg.height / nmaster) - BORDH; mastergeo.height = (sg.height / nmaster) - BORDH;
} }
else else
{ {
if(type == Top) if(type == Top)
mastergeo.y = (n <= nmaster) ? (uint)sg.y : sg.y + (sg.height - mwfact) - BORDH; mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH;
mastergeo.width = (sg.width / nmaster) - (BORDH << 2); mastergeo.width = (sg.width / nmaster) - (BORDH << 2);
mastergeo.height = (n <= nmaster) ? (uint)(sg.height - BORDH) : mwfact; mastergeo.height = (n <= nmaster) ? (sg.height - BORDH) : mwfact;
} }
/* TILED SIZE */ /* TILED SIZE */
if(n > nmaster) if(n > nmaster)
@@ -369,7 +371,7 @@ multi_tile(int screen, Position type)
} }
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{ {
/* Set client property */ /* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag); c->flags &= ~(MaxFlag | LMaxFlag);
@@ -459,19 +461,19 @@ multi_tile(int screen, Position type)
static void static void
mirror(int screen, bool horizontal) mirror(int screen, bool horizontal)
{ {
Client *c; Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen]; Geo sg = sgeo[screen];
Geo mastergeo = {sg.x, sg.y, sg.width, sg.height}; Geo mastergeo = {sg.x, sg.y, sg.width, sg.height};
Geo cgeo = {sg.x, sg.y , sg.width, sg.height}; Geo cgeo = {sg.x, sg.y , sg.width, sg.height};
Geo nextg[2]; Geo nextg[2];
uint i, n, tilesize = 0, mwfact; int i = 0, n = 0, tilesize = 0, mwfact;
uint nmaster = tags[screen][seltag[screen]].nmaster; int nmaster = tags[screen][seltag[screen]].nmaster;
int pa, imp; int pa, imp;
bool isp = False; bool isp = False;
memset(nextg, 0, sizeof(nextg)); memset(nextg, 0, sizeof(nextg));
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n)); CHECK((tags[screen][seltag[screen]].nclients = n));
/* Fix nmaster */ /* Fix nmaster */
@@ -527,7 +529,7 @@ mirror(int screen, bool horizontal)
} }
} }
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{ {
/* Set client property */ /* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag); c->flags &= ~(MaxFlag | LMaxFlag);
@@ -794,14 +796,14 @@ uicb_togglemax(uicb_t cmd)
void void
uicb_toggle_resizehint(uicb_t cmd) uicb_toggle_resizehint(uicb_t cmd)
{ {
Client *c; Client *c = tiled_client(selscreen, SLIST_FIRST(&clients));
screen_get_sel(); screen_get_sel();
(void)cmd; (void)cmd;
tags[selscreen][seltag[selscreen]].flags ^= ResizeHintFlag; tags[selscreen][seltag[selscreen]].flags ^= ResizeHintFlag;
for(c = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next)) for(; c; c = tiled_client(selscreen, SLIST_NEXT(c, next)))
client_moveresize(c, c->geo, (tags[selscreen][seltag[selscreen]].flags & ResizeHintFlag)); client_moveresize(c, c->geo, (tags[selscreen][seltag[selscreen]].flags & ResizeHintFlag));
return; return;
@@ -822,10 +824,10 @@ uicb_toggle_abovefc(uicb_t cmd)
if(!(tags[selscreen][seltag[selscreen]].flags & AboveFCFlag)) if(!(tags[selscreen][seltag[selscreen]].flags & AboveFCFlag))
{ {
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->flags & AboveFlag if(c->flags & AboveFlag
&& c->screen == selscreen && c->screen == selscreen
&& c->tag == (uint)seltag[selscreen]) && c->tag == seltag[selscreen])
{ {
c->flags &= ~AboveFlag; c->flags &= ~AboveFlag;
break; break;
@@ -877,8 +879,8 @@ layout_set_client_master(Client *c)
if(!c || (c->flags & (HintFlag | FSSFlag)) || !(c->flags & TileFlag)) if(!c || (c->flags & (HintFlag | FSSFlag)) || !(c->flags & TileFlag))
return; return;
if(c == tiled_client(selscreen, clients)) if(c == tiled_client(selscreen, SLIST_FIRST(&clients)))
CHECK((c = tiled_client(selscreen, c->next))); CHECK((c = tiled_client(selscreen, SLIST_NEXT(c, next))));
client_detach(c); client_detach(c);
client_attach(c); client_attach(c);

View File

@@ -332,21 +332,21 @@ mouse_resize(Client *c)
void void
mouse_grabbuttons(Client *c, bool focused) mouse_grabbuttons(Client *c, bool focused)
{ {
size_t i; size_t i = 0;
uint but[] = {Button1, Button2, Button3, Button4, Button5}; uint but[] = {Button1, Button2, Button3, Button4, Button5};
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused) if(focused)
for(i = 0; i < LEN(but); ++i) for(; i < LEN(but); ++i)
{ {
XGrabButton(dpy, but[i], conf.client.mod, c->win, False, XGrabButton(dpy, but[i], conf.client.mod, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None); ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask, c->win, False, XGrabButton(dpy, but[i], conf.client.mod | LockMask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None); ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|numlockmask, c->win, False, XGrabButton(dpy, but[i], conf.client.mod | numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None); ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask|numlockmask, c->win, False, XGrabButton(dpy, but[i], conf.client.mod | LockMask | numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None); ButtonMask, GrabModeAsync, GrabModeSync, None, None);
} }
else else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,

View File

@@ -165,7 +165,7 @@ parse_keywords(const char *filename)
bool error = False; bool error = False;
if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) { if (stat(filename, &st) == -1 || (fd = open(filename, O_RDONLY)) == -1) {
warn("%s", filename); warn("%s", filename);
return NULL; return NULL;
} }

View File

@@ -18,7 +18,6 @@
#define PARSE_H #define PARSE_H
#include "wmfs.h" #include "wmfs.h"
#include <sys/queue.h>
#define INCLUDE_CMD "@include" #define INCLUDE_CMD "@include"
#define PARSE_MAX_LIST 32 #define PARSE_MAX_LIST 32

View File

@@ -38,9 +38,7 @@
int int
screen_count(void) screen_count(void)
{ {
int n = 0; int n = ScreenCount(dpy);
n = ScreenCount(dpy);
#ifdef HAVE_XINERAMA #ifdef HAVE_XINERAMA
if(XineramaIsActive(dpy)) if(XineramaIsActive(dpy))
@@ -106,11 +104,10 @@ screen_get_geo(int s)
int int
screen_get_with_geo(int x, int y) screen_get_with_geo(int x, int y)
{ {
int i; int i = 0;
for(i = 0; i < screen_count(); ++i) for(; i < screen_count(); ++i)
if((x >= spgeo[i].x && x < spgeo[i].x + spgeo[i].width) if(INAREA(x, y, spgeo[i]))
&& y >= spgeo[i].y && y < spgeo[i].y + spgeo[i].height)
return i; return i;
return 0; return 0;

View File

@@ -41,6 +41,7 @@
void \ void \
uicb_split_move_##d(uicb_t cmd) \ uicb_split_move_##d(uicb_t cmd) \
{ \ { \
(void)cmd; \
CHECK(sel); \ CHECK(sel); \
split_move_dir(sel, d); \ split_move_dir(sel, d); \
} }
@@ -121,14 +122,13 @@ split_apply_current(int screen, int tag)
static bool static bool
_split_check_row_dir(Client *c, Client *g, Position p) _split_check_row_dir(Client *c, Client *g, Position p)
{ {
int s, cs; int s = 0, cs;
Geo cgeo; Geo cgeo = c->frame_geo;
Client *cc; Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
cs = (LDIR(p) ? g->frame_geo.height : g->frame_geo.width); cs = (LDIR(p) ? g->frame_geo.height : g->frame_geo.width);
for(s = 0, cgeo = c->frame_geo, cc = tiled_client(c->screen, clients); for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
cc; cc = tiled_client(c->screen, cc->next))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p)) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p))
&& SPLIT_CHECK_ROW(cc->frame_geo, g->frame_geo, p)) && SPLIT_CHECK_ROW(cc->frame_geo, g->frame_geo, p))
{ {
@@ -197,8 +197,8 @@ split_arrange_closed(Client *ghost)
for(p = Right; p < Center && !b; ++p) for(p = Right; p < Center && !b; ++p)
if((c = client_get_next_with_direction(ghost, p)) && _split_check_row_dir(c, ghost, p)) if((c = client_get_next_with_direction(ghost, p)) && _split_check_row_dir(c, ghost, p))
{ {
for(cgeo = c->frame_geo, cc = tiled_client(c->screen, clients); for(cgeo = c->frame_geo, cc = tiled_client(c->screen, SLIST_FIRST(&clients));
cc; cc = tiled_client(c->screen, cc->next)) cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p)) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p))
&& SPLIT_CHECK_ROW(cc->frame_geo, ghost->frame_geo, p)) && SPLIT_CHECK_ROW(cc->frame_geo, ghost->frame_geo, p))
{ {
@@ -296,7 +296,8 @@ split_client_integrate(Client *c, Client *sc, int screen, int tag)
|| sc->screen != screen || sc->tag != tag) || sc->screen != screen || sc->tag != tag)
{ {
/* Looking for first client on wanted tag */ /* Looking for first client on wanted tag */
for(b = False, sc = clients; sc; sc = sc->next) b = False;
SLIST_FOREACH(sc, &clients, next)
if(sc != c && sc->screen == screen && sc->tag == tag if(sc != c && sc->screen == screen && sc->tag == tag
&& (sc->flags & TileFlag)) && (sc->flags & TileFlag))
{ {

View File

@@ -35,6 +35,39 @@
/* Systray width */ /* Systray width */
static int sw = 0; static int sw = 0;
/** Parse dynamic mouse binds in str and insert it in linked list
* --> \<block>[;;;;(button;func;cmd)]\ add a mouse bind on the block object
*\param str String
*\param area Area of clicking
*\param infobar Infobar pointer
*/
void
statustext_mouse(char *str, Geo area, InfoBar *infobar)
{
StatusMouse *sm = NULL;
int i = 0, button = 1, n;
char cmd[256] = { 0 };
char func[64] = { 0 };
for(; i < (int)strlen(str); ++i, sm = NULL)
if((n = sscanf(&str[i], "(%d;%64[^;];%256[^)])", &button, func, cmd) >= 2) && n < 4)
{
sm = zcalloc(sizeof(StatusMouse));
sm->button = button;
sm->func = name_to_func((char*)func, func_list);
sm->cmd = xstrdup(cmd);
sm->area = area;
sm->infobar = infobar;
SLIST_INSERT_HEAD(&smhead, sm, next);
/* Jump to the end of the sequence */
while(str[++i + 1] != ')');
}
return;
}
/** Check rectangles blocks in str and draw it /** Check rectangles blocks in str and draw it
* --> \b[x;y;width;height;#color]\ * --> \b[x;y;width;height;#color]\
*\param ib Infobar pointer *\param ib Infobar pointer
@@ -44,14 +77,20 @@ static void
statustext_rectangle(InfoBar *ib, char *str) statustext_rectangle(InfoBar *ib, char *str)
{ {
StatusRec r; StatusRec r;
char as; char as, mouse[512] = { 0 };
int i, j, k; int i = 0, j = 0, k, n;
for(i = j = 0; i < (int)strlen(str); ++i, ++j) for(; i < (int)strlen(str); ++i, ++j)
if(sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x]%c", &r.x, &r.y, &r.w, &r.h, &r.color, &as) == 6 if(((n = sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x]%c",
&r.g.x, &r.g.y, &r.g.width, &r.g.height, &r.color, &as)) == 6
|| (n = sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x;%512[^]]]%c",
&r.g.x, &r.g.y, &r.g.width, &r.g.height, &r.color, mouse, &as)) == 7)
&& as == '\\') && as == '\\')
{ {
draw_rectangle(ib->bar->dr, r.x - sw, r.y, r.w, r.h, r.color); draw_rectangle(ib->bar->dr, r.g.x - sw, r.g.y, r.g.width, r.g.height, r.color);
if(n == 7)
statustext_mouse(mouse, r.g, ib);
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i); for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
} }
@@ -121,15 +160,30 @@ static void
statustext_text(InfoBar *ib, char *str) statustext_text(InfoBar *ib, char *str)
{ {
StatusText s; StatusText s;
char as; Geo area;
int i, j, k; char as, mouse[512] = { 0 };
int i = 0, j = 0, k, n;
for(i = j = 0; i < (int)strlen(str); ++i, ++j) for(; i < (int)strlen(str); ++i, ++j)
if(sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^]]]%c", &s.x, &s.y, s.color, s.text, &as) == 5 if(((n = sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^];]]%c",
&s.x, &s.y, s.color, s.text, &as)) == 5
|| (n = sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^;];%512[^]]]%c",
&s.x, &s.y, s.color, s.text, mouse, &as)) == 6)
&& as == '\\') && as == '\\')
{ {
draw_text(ib->bar->dr, s.x - sw, s.y, s.color, s.text); draw_text(ib->bar->dr, s.x - sw, s.y, s.color, s.text);
/* Etablish clickable area on text */
if(n == 6)
{
area.height = font.height;
area.width = textw(s.text);
area.x = s.x - sw;
area.y = s.y - area.height;
statustext_mouse(mouse, area, ib);
}
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i); for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
} }
else if(j != i) else if(j != i)
@@ -147,7 +201,7 @@ statustext_text(InfoBar *ib, char *str)
*\param str String *\param str String
*/ */
static void static void
statustext_normal(int sc, InfoBar *ib, char *str) statustext_normal(InfoBar *ib, char *str)
{ {
char strwc[MAXSTATUS] = { 0 }; char strwc[MAXSTATUS] = { 0 };
char buf[MAXSTATUS] = { 0 }; char buf[MAXSTATUS] = { 0 };
@@ -165,7 +219,7 @@ statustext_normal(int sc, InfoBar *ib, char *str)
strwc[j] = str[i]; strwc[j] = str[i];
/* Draw normal text without any blocks */ /* Draw normal text without any blocks */
draw_text(ib->bar->dr, (sgeo[sc].width - SHADH) - (textw(strwc) + sw), FHINFOBAR, ib->bar->fg, strwc); draw_text(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (textw(strwc) + sw), FHINFOBAR, ib->bar->fg, strwc);
if(n) if(n)
{ {
@@ -180,12 +234,12 @@ statustext_normal(int sc, InfoBar *ib, char *str)
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]); for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
/* Draw a rectangle with the bar color to draw the text properly */ /* Draw a rectangle with the bar color to draw the text properly */
draw_rectangle(ib->bar->dr, (sgeo[sc].width - SHADH) - (tw + sw), draw_rectangle(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (tw + sw),
0, INFOBARH - (sgeo[sc].width - SHADH) - tw, 0, INFOBARH - (sgeo[ib->screen].width - SHADH) - tw,
INFOBARH, conf.colors.bar); INFOBARH, conf.colors.bar);
/* Draw text with its color */ /* Draw text with its color */
draw_text(ib->bar->dr, (sgeo[sc].width - SHADH) - (tw + sw), FHINFOBAR, col, &buf[k]); draw_text(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (tw + sw), FHINFOBAR, col, &buf[k]);
strncpy(buf, strwc, sizeof(buf)); strncpy(buf, strwc, sizeof(buf));
++i; ++i;
@@ -200,25 +254,25 @@ statustext_normal(int sc, InfoBar *ib, char *str)
*\param str String *\param str String
*/ */
void void
statustext_handle(int sc, char *str) statustext_handle(InfoBar *ib)
{ {
InfoBar *ib = &infobar[sc]; char *str;
char *lastst; StatusMouse *sm;
int i;
/* If the str == the current statustext, return (not needed) */ /* Free previous linked list of mouse bind */
if(!str) if(!ib->screen)
return; while(!SLIST_EMPTY(&smhead))
{
sm = SLIST_FIRST(&smhead);
SLIST_REMOVE_HEAD(&smhead, next);
free((void*)sm->cmd);
free(sm);
}
if(sc == conf.systray.screen) if(ib->screen == conf.systray.screen)
sw = systray_get_width(); sw = systray_get_width();
barwin_refresh_color(ib->bar); str = xstrdup(ib->statustext);
/* save last status text address (for free at the end) */
lastst = ib->statustext;
ib->statustext = xstrdup(str);
/* Store rectangles, located text & images properties. */ /* Store rectangles, located text & images properties. */
statustext_rectangle(ib, str); statustext_rectangle(ib, str);
@@ -226,12 +280,11 @@ statustext_handle(int sc, char *str)
statustext_text(ib, str); statustext_text(ib, str);
/* Draw normal text (and possibly colored with \#color\ blocks) */ /* Draw normal text (and possibly colored with \#color\ blocks) */
statustext_normal(sc, ib, str); statustext_normal(ib, str);
sw = 0; sw = 0;
barwin_refresh(ib->bar);
free(lastst); free(str);
return; return;
} }

View File

@@ -112,10 +112,10 @@ enum { TagSel, TagTransfert, TagAdd, TagNext, TagPrev, TagActionLast };
/* Menu align */ /* Menu align */
enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 }; enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 };
/* Infobar position */ /* Infobar position / elements */
enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 }; enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 };
typedef enum { Right = 0, Left, Top, Bottom, Center, PositionLast } Position; typedef enum { Right = 0, Left, Top, Bottom, Center, PositionLast } Position;
typedef enum { ElemTag, ElemLayout, ElemSelbar } IbElemType;
/* Ewmh hints list */ /* Ewmh hints list */
enum enum
@@ -158,7 +158,6 @@ enum
/* WMFS HINTS */ /* WMFS HINTS */
wmfs_running, wmfs_running,
wmfs_update_hints, wmfs_update_hints,
wmfs_update_status,
wmfs_current_tag, wmfs_current_tag,
wmfs_current_screen, wmfs_current_screen,
wmfs_current_layout, wmfs_current_layout,
@@ -185,7 +184,7 @@ typedef struct
* BarWindow Structure * BarWindow Structure
* (titlebar, infobar..) * (titlebar, infobar..)
*/ */
typedef struct typedef struct BarWindow
{ {
Window win; Window win;
Drawable dr; Drawable dr;
@@ -202,16 +201,16 @@ typedef struct
uint stipple_color; uint stipple_color;
Geo geo; Geo geo;
uint flags; uint flags;
SLIST_ENTRY(BarWindow) next;
} BarWindow; } BarWindow;
/* Client Structure. */ /* Client Structure. */
typedef struct Client Client; typedef struct Client
struct Client
{ {
/* Client title */ /* Client title */
char *title; char *title;
/* Tag num */ /* Tag num */
uint tag; int tag;
int focusontag; int focusontag;
/* Screen */ /* Screen */
int screen; int screen;
@@ -245,10 +244,9 @@ struct Client
} colors; } colors;
/* Client Information by flags */ /* Client Information by flags */
uint flags; uint flags;
/* Struct in chains */ /* Simply-linked list */
Client *next; SLIST_ENTRY(Client) next;
Client *prev; } Client;
};
/* Keybind Structure */ /* Keybind Structure */
typedef struct typedef struct
@@ -269,13 +267,23 @@ typedef struct
uicb_t cmd; uicb_t cmd;
} MouseBinding; } MouseBinding;
/* InfoBar elements */
typedef struct InfobarElem
{
IbElemType type;
Geo geo;
STAILQ_ENTRY(InfobarElem) next;
} InfobarElem;
/* InfoBar Struct */ /* InfoBar Struct */
typedef struct typedef struct
{ {
BarWindow *bar, *selbar;
BarWindow *layout_button;
BarWindow *tags_board, *tags[MAXTAG]; BarWindow *tags_board, *tags[MAXTAG];
Geo geo; BarWindow *layout_button;
BarWindow *bar;
STAILQ_HEAD(, InfobarElem) elemhead;
char *elemorder;
Geo geo, selbar_geo;
int screen, position; int screen, position;
char *statustext; char *statustext;
bool need_update; bool need_update;
@@ -293,13 +301,12 @@ typedef struct
} Layout; } Layout;
/* Systray Structure */ /* Systray Structure */
typedef struct Systray Systray; typedef struct Systray
struct Systray
{ {
Window win; Window win;
Geo geo; Geo geo;
Systray *next, *prev; SLIST_ENTRY(Systray) next;
}; } Systray;
/* Tag Structure */ /* Tag Structure */
typedef struct typedef struct
@@ -386,6 +393,7 @@ typedef struct
char *class; char *class;
char *instance; char *instance;
char *role; char *role;
char *name;
int screen; int screen;
int tag; int tag;
bool free; bool free;
@@ -413,9 +421,6 @@ typedef struct
bool tagnamecount; bool tagnamecount;
Tag default_tag; Tag default_tag;
uint pad; uint pad;
int status_timing;
char *status_path;
pid_t status_pid;
char *autostart_path; char *autostart_path;
char *autostart_command; char *autostart_command;
struct struct
@@ -446,6 +451,7 @@ typedef struct
MouseBinding *mouse; MouseBinding *mouse;
int nmouse; int nmouse;
bool selbar; bool selbar;
char *element_order;
} bars; } bars;
struct struct
{ {
@@ -521,7 +527,6 @@ typedef struct
bool client_auto_center; bool client_auto_center;
bool client_tile_raise; bool client_tile_raise;
bool layout_system; /* Switch: False, Menu: True. */ bool layout_system; /* Switch: False, Menu: True. */
bool layout_placement; /* Right (normal): False, Left: True. */
bool keep_layout_geo; bool keep_layout_geo;
bool cfactor_enable_split; bool cfactor_enable_split;
char *tag_expose_name; char *tag_expose_name;
@@ -547,7 +552,7 @@ typedef struct
/* status.c util struct */ /* status.c util struct */
typedef struct typedef struct
{ {
int x, y, w, h; Geo g;
uint color; uint color;
} StatusRec; } StatusRec;
@@ -565,6 +570,16 @@ typedef struct
char text[512]; char text[512];
} StatusText; } StatusText;
typedef struct StatusMouse
{
Geo area;
InfoBar *infobar;
uint button;
void (*func)(uicb_t);
uicb_t cmd;
SLIST_ENTRY(StatusMouse) next;
} StatusMouse;
typedef struct typedef struct
{ {
int x, y, w, h; int x, y, w, h;

View File

@@ -98,11 +98,7 @@ systray_add(Window win)
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, traywin, 0); ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, traywin, 0);
/* Attach */ /* Attach */
if(trayicons) SLIST_INSERT_HEAD(&trayicons, s, next);
trayicons->prev = s;
s->next = trayicons;
trayicons = s;
return; return;
} }
@@ -110,14 +106,10 @@ systray_add(Window win)
void void
systray_del(Systray *s) systray_del(Systray *s)
{ {
Systray **ss;
if(!conf.systray.active) if(!conf.systray.active)
return; return;
for(ss = &trayicons; *ss && *ss != s; ss = &(*ss)->next); SLIST_REMOVE(&trayicons, s, Systray, next);
*ss = s->next;
free(s); free(s);
return; return;
@@ -158,10 +150,13 @@ systray_freeicons(void)
if(!conf.systray.active) if(!conf.systray.active)
return; return;
for(i = trayicons; i; i = i->next) while(!SLIST_EMPTY(&trayicons))
{ {
i = SLIST_FIRST(&trayicons);
SLIST_REMOVE_HEAD(&trayicons, next);
XUnmapWindow(dpy, i->win); XUnmapWindow(dpy, i->win);
XReparentWindow(dpy, i->win, ROOT, 0, 0); XReparentWindow(dpy, i->win, ROOT, 0, 0);
free(i); free(i);
} }
@@ -181,7 +176,7 @@ systray_find(Window win)
if(!conf.systray.active) if(!conf.systray.active)
return NULL; return NULL;
for(i = trayicons; i; i = i->next) SLIST_FOREACH(i, &trayicons, next)
if(i->win == win) if(i->win == win)
return i; return i;
@@ -197,7 +192,7 @@ systray_get_width(void)
if(!conf.systray.active) if(!conf.systray.active)
return 0; return 0;
for(i = trayicons; i; i = i->next) SLIST_FOREACH(i, &trayicons, next)
w += i->geo.width + conf.systray.spacing + 1; w += i->geo.width + conf.systray.spacing + 1;
return w; return w;
@@ -212,13 +207,13 @@ systray_update(void)
if(!conf.systray.active) if(!conf.systray.active)
return; return;
if(!trayicons) if(!SLIST_FIRST(&trayicons))
{ {
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1); XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1);
return; return;
} }
for(i = trayicons; i; i = i->next) SLIST_FOREACH(i, &trayicons, next)
{ {
XMapWindow(dpy, i->win); XMapWindow(dpy, i->win);

View File

@@ -95,13 +95,18 @@ tag_set(int tag)
} }
/* Check for ignore_tag clients */ /* Check for ignore_tag clients */
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->tag == MAXTAG + 1 && c->screen == selscreen) if(c->tag == MAXTAG + 1 && c->screen == selscreen)
{ {
al = True; al = True;
break; break;
} }
/* To focus selected client of the via focusontag option */
SLIST_FOREACH(c, &clients, next)
if(c->focusontag == tag && c->screen == selscreen)
break;
arrange(selscreen, al); arrange(selscreen, al);
if(tags[selscreen][tag].flags & RequestUpdateFlag) if(tags[selscreen][tag].flags & RequestUpdateFlag)
@@ -110,15 +115,10 @@ tag_set(int tag)
tags[selscreen][tag].flags &= ~RequestUpdateFlag; tags[selscreen][tag].flags &= ~RequestUpdateFlag;
} }
/* To focus selected client of the via focusontag option */
for(c = clients; c; c = c->next)
if(c->focusontag == tag && c->screen == selscreen)
break;
/* No focusontag option found on any client, try to find the first of the tag */ /* No focusontag option found on any client, try to find the first of the tag */
if(!c) if(!c)
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->tag == (uint)seltag[selscreen] && c->screen == selscreen) if(c->tag == seltag[selscreen] && c->screen == selscreen)
break; break;
client_focus((c) ? c : NULL); client_focus((c) ? c : NULL);
@@ -237,7 +237,7 @@ uicb_tag_next_visible(uicb_t cmd)
return; return;
} }
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->screen == selscreen) if(c->screen == selscreen)
occupied |= TagFlag(c->tag); occupied |= TagFlag(c->tag);
@@ -278,7 +278,7 @@ uicb_tag_prev_visible(uicb_t cmd)
return; return;
} }
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->screen == selscreen) if(c->screen == selscreen)
occupied |= TagFlag(c->tag); occupied |= TagFlag(c->tag);
@@ -351,11 +351,11 @@ tag_swap(int s, int t1, int t2)
tags[s][t1] = tags[s][t2]; tags[s][t1] = tags[s][t2];
tags[s][t2] = t; tags[s][t2] = t;
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
{ {
if(c->screen == s && c->tag == (uint)t1) if(c->screen == s && c->tag == t1)
c->tag = t2; c->tag = t2;
else if(c->screen == s && c->tag == (uint)t2) else if(c->screen == s && c->tag == t2)
c->tag = t1; c->tag = t1;
} }
@@ -477,7 +477,7 @@ uicb_tag_urgent(uicb_t cmd)
(void)cmd; (void)cmd;
/* Check if there is a urgent client */ /* Check if there is a urgent client */
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->flags & UrgentFlag) if(c->flags & UrgentFlag)
{ {
screen_set_sel(c->screen); screen_set_sel(c->screen);
@@ -651,15 +651,15 @@ tag_delete(int s, int tag)
{ {
Tag t; Tag t;
Client *c; Client *c;
size_t i; int i;
memset(&t, 0, sizeof(t)); memset(&t, 0, sizeof(t));
if(tag < 0 || tag > conf.ntag[s] || conf.ntag[s] == 1) if(tag < 0 || tag > conf.ntag[s] || conf.ntag[s] == 1)
return; return;
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->screen == s && c->tag == (uint)tag) if(c->screen == s && c->tag ==tag)
{ {
warnx("Client(s) present in this tag, can't delete it"); warnx("Client(s) present in this tag, can't delete it");
@@ -671,10 +671,10 @@ tag_delete(int s, int tag)
tags[s][tag] = t; tags[s][tag] = t;
infobar[s].tags[tag] = NULL; infobar[s].tags[tag] = NULL;
for(i = tag; i < (size_t)conf.ntag[s] + 1; ++i) for(i = tag; i < conf.ntag[s] + 1; ++i)
{ {
/* Set clients tag because of shift */ /* Set clients tag because of shift */
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
if(c->screen == s && c->tag == i + 1) if(c->screen == s && c->tag == i + 1)
c->tag = i; c->tag = i;
@@ -751,7 +751,7 @@ uicb_tag_toggle_expose(uicb_t cmd)
{ {
if(strcmp(tags[selscreen][i].name, conf.tag_expose_name) == 0) if(strcmp(tags[selscreen][i].name, conf.tag_expose_name) == 0)
{ {
if(clients && sel->tag) if(SLIST_FIRST(&clients) && sel->tag)
tag_set(sel->tag); tag_set(sel->tag);
tag_delete(selscreen, i); tag_delete(selscreen, i);

View File

@@ -279,29 +279,6 @@ uicb_spawn(uicb_t cmd)
return; return;
} }
char*
clean_value(char *str)
{
int i;
char c, *p;
if(!str || !(p = xstrdup(str)))
return NULL;
/* Remove useless spaces */
for(; *p == ' '; ++p);
for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0');
/* For string delimiter (" or ') */
if(((c = *p) == '"' || (c = *p) == '\'') && strchr(p + 1, c))
{
for(++p, i = 0; p[i] && p[i] != c; ++i);
p[i] = '\0';
}
return p;
}
/* To use ~/ shortcut.. */ /* To use ~/ shortcut.. */
char* char*
patht(char *path) patht(char *path)

View File

@@ -33,7 +33,6 @@
#include "wmfs.h" #include "wmfs.h"
static volatile bool exiting = False, sig_chld = False; static volatile bool exiting = False, sig_chld = False;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
int int
errorhandler(Display *d, XErrorEvent *event) errorhandler(Display *d, XErrorEvent *event)
@@ -80,17 +79,19 @@ errorhandlerdummy(Display *d, XErrorEvent *event)
void void
quit(void) quit(void)
{ {
Client *c;
size_t i, len; size_t i, len;
/* Set the silent error handler */ /* Set the silent error handler */
XSetErrorHandler(errorhandlerdummy); XSetErrorHandler(errorhandlerdummy);
/* Unmanage all clients */ /* Unmanage all clients */
for(c = clients; c; c = c->next) while(!SLIST_EMPTY(&clients))
{ {
Client *c = SLIST_FIRST(&clients);
client_unhide(c); client_unhide(c);
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y); XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
free(c);
SLIST_REMOVE_HEAD(&clients, next);
} }
free(tags); free(tags);
@@ -110,6 +111,10 @@ quit(void)
XFreeGC(dpy, gc_stipple); XFreeGC(dpy, gc_stipple);
infobar_destroy(); infobar_destroy();
/* BarWindows */
while(!SLIST_EMPTY(&bwhead))
SLIST_REMOVE_HEAD(&bwhead, next);
free(sgeo); free(sgeo);
free(spgeo); free(spgeo);
free(infobar); free(infobar);
@@ -143,78 +148,24 @@ quit(void)
free(event_handle); free(event_handle);
/* kill status script */
if (conf.status_pid != (pid_t)-1)
kill(conf.status_pid, SIGTERM);
return; return;
} }
static void
wait_childs_and_status(void)
{
int pid;
pthread_mutex_lock(&mtx);
if (sig_chld) {
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
if (pid == conf.status_pid)
conf.status_pid = -1;
sig_chld = False;
}
pthread_mutex_unlock(&mtx);
}
static void *
thread_status(void *arg)
{
(void)arg;
int left = conf.status_timing;
pthread_detach(pthread_self());
do
{
wait_childs_and_status();
pthread_mutex_lock(&mtx);
if (conf.status_pid == -1)
conf.status_pid = spawn(conf.status_path);
pthread_mutex_unlock(&mtx);
while ((left = sleep(left)) > 0);
left = conf.status_timing;
} while (!exiting);
pthread_exit(NULL);
}
/** WMFS main loop. /** WMFS main loop.
*/ */
static void static void
mainloop(void) mainloop(void)
{ {
XEvent ev; XEvent ev;
pthread_t th_status;
if(estatus && !conf.status_timing) while(!exiting && !XNextEvent(dpy, &ev)) {
conf.status_pid = spawn(conf.status_path); if (sig_chld) {
else if(estatus && pthread_create(&th_status, NULL, thread_status, NULL) != 0) while(waitpid(-1, NULL, WNOHANG) > 0);
{ sig_chld = False;
warnx("pthread_create"); }
estatus = False;
}
while(!exiting && !XNextEvent(dpy, &ev))
{
HANDLE_EVENT(&ev); HANDLE_EVENT(&ev);
wait_childs_and_status();
} }
if(estatus)
pthread_join(th_status, NULL);
return; return;
} }
@@ -290,9 +241,9 @@ scan(void)
} }
/* Set update layout request */ /* Set update layout request */
for(c = clients; c; c = c->next) SLIST_FOREACH(c, &clients, next)
{ {
if(c->tag > (uint)conf.ntag[c->screen]) if(c->tag > conf.ntag[c->screen])
c->tag = conf.ntag[c->screen]; c->tag = conf.ntag[c->screen];
tags[c->screen][c->tag].flags |= RequestUpdateFlag; tags[c->screen][c->tag].flags |= RequestUpdateFlag;
} }
@@ -415,19 +366,6 @@ set_statustext(int s, char *str)
return; return;
} }
/** Update status script by ewmh hint
*/
static void
update_status(void)
{
if(!check_wmfs_running())
return;
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_STATUS", 0, 0, 0, 0, True);
return;
}
/** Signal handle function /** Signal handle function
*/ */
static void static void
@@ -456,7 +394,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int i; int i;
char *ol = "csS"; char *ol = "cs";
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
struct sigaction sa; struct sigaction sa;
@@ -465,7 +403,7 @@ main(int argc, char **argv)
all_argv = argv; all_argv = argv;
sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME")); sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME"));
while((i = getopt(argc, argv, "hviSc:s:C:")) != -1) while((i = getopt(argc, argv, "hvic:s:C:")) != -1)
{ {
/* For options who need WMFS running */ /* For options who need WMFS running */
@@ -476,11 +414,10 @@ main(int argc, char **argv)
{ {
case 'h': case 'h':
default: default:
printf("usage: %s [-ihvS] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>] [-V <viwmfs cmd]\n" printf("usage: %s [-ihv] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>]\n"
" -C <file> Load a configuration file\n" " -C <file> Load a configuration file\n"
" -c <uicb_function> <cmd> Execute an uicb function to control WMFS\n" " -c <uicb_function> <cmd> Execute an uicb function to control WMFS\n"
" -s <screen_num> <string> Set the bar(s) statustext\n" " -s <screen_num> <string> Set the bar(s) statustext\n"
" -S Update status script\n"
" -h Show this page\n" " -h Show this page\n"
" -i Show informations\n" " -i Show informations\n"
" -v Show WMFS version\n", argv[0]); " -v Show WMFS version\n", argv[0]);
@@ -497,12 +434,6 @@ main(int argc, char **argv)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'S':
update_status();
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'C': case 'C':
strncpy(conf.confpath, optarg, sizeof(conf.confpath)); strncpy(conf.confpath, optarg, sizeof(conf.confpath));
break; break;

View File

@@ -51,6 +51,7 @@
#include <err.h> #include <err.h>
#include <pthread.h> #include <pthread.h>
#include <locale.h> #include <locale.h>
#include <sys/queue.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@@ -58,6 +59,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
/* Optional dependencies */ /* Optional dependencies */
@@ -112,13 +114,13 @@
#define ATOM(a) XInternAtom(dpy, (a), False) #define ATOM(a) XInternAtom(dpy, (a), False)
#define FRAMEW(w) ((w) + (BORDH << 1)) #define FRAMEW(w) ((w) + (BORDH << 1))
#define FRAMEH(h) ((h) + (BORDH + TBARH)) #define FRAMEH(h) ((h) + (BORDH + TBARH))
#define ROUND(x) (float)((x > 0) ? x + (float)0.5 : x - (float)0.5)
#define CHECK(x) if(!(x)) return #define CHECK(x) if(!(x)) return
#define LEN(x) (sizeof(x) / sizeof((x)[0])) #define LEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAXCLIST (64) #define MAXCLIST (64)
#define RPOS(x) (x & 1 ? x - 1 : x + 1) #define RPOS(x) (x & 1 ? x - 1 : x + 1)
#define LDIR(x) (x < Top) #define LDIR(x) (x < Top)
#define FLAGAPPLY(v, b, f) ((b) ? (v |= (f)) : (v &= ~(f))) #define FLAGAPPLY(v, b, f) ((b) ? (v |= (f)) : (v &= ~(f)))
#define INAREA(i, j, a) ((i) >= (a).x && (i) <= (a).x + (a).width && (j) >= (a).y && (j) <= (a).y + (a).height)
/* Cfactor define */ /* Cfactor define */
#define CFACTOR_CHECK2(g1, g2, p) (LDIR(p) ? (g1.height == g2.height) : (g1.width == g2.width)) #define CFACTOR_CHECK2(g1, g2, p) (LDIR(p) ? (g1.height == g2.height) : (g1.width == g2.width))
@@ -127,6 +129,22 @@
? (p == Left ? (g1.x == g2.x) : (g1.x + g1.width == g2.x + g2.width)) \ ? (p == Left ? (g1.x == g2.x) : (g1.x + g1.width == g2.x + g2.width)) \
: (p == Top ? (g1.y == g2.y) : (g1.y + g1.height == g2.y + g2.height))) \ : (p == Top ? (g1.y == g2.y) : (g1.y + g1.height == g2.y + g2.height))) \
/* Barwin define, wrappers for simple function */
#define barwin_delete_subwin(bw) XDestroySubwindows(dpy, bw->win)
#define barwin_map_subwin(bw) XMapSubwindows(dpy, bw->win)
#define barwin_unmap_subwin(bw) XUnmapSubwindows(dpy, bw->win)
#define barwin_refresh(bw) XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0)
#define barwin_map(bw) \
do { \
XMapWindow(dpy, bw->win); \
bw->flags |= MappedFlag; \
} while(/* CONSTCOND */ 0)
#define barwin_unmap(bw) \
do { \
XUnmapWindow(dpy, bw->win); \
bw->flags &= ~MappedFlag; \
} while(/* CONSTCOND */ 0)
/* barwin.c */ /* barwin.c */
BarWindow *barwin_create(Window parent, BarWindow *barwin_create(Window parent,
int x, int y, int x, int y,
@@ -138,15 +156,9 @@ BarWindow *barwin_create(Window parent,
void barwin_draw_text(BarWindow *bw, int x, int y, char *text); void barwin_draw_text(BarWindow *bw, int x, int y, char *text);
void barwin_color_set(BarWindow *bw, uint bg, char *fg); void barwin_color_set(BarWindow *bw, uint bg, char *fg);
void barwin_delete(BarWindow *bw); void barwin_delete(BarWindow *bw);
void barwin_delete_subwin(BarWindow *bw);
void barwin_map(BarWindow *bw);
void barwin_map_subwin(BarWindow *bw);
void barwin_unmap(BarWindow *bw);
void barwin_unmap_subwin(BarWindow *bw);
void barwin_move(BarWindow *bw, int x, int y); void barwin_move(BarWindow *bw, int x, int y);
void barwin_resize(BarWindow *bw, int w, int h); void barwin_resize(BarWindow *bw, int w, int h);
void barwin_refresh_color(BarWindow *bw); void barwin_refresh_color(BarWindow *bw);
void barwin_refresh(BarWindow *bw);
/* draw.c */ /* draw.c */
void draw_text(Drawable d, int x, int y, char* fg, char *str); void draw_text(Drawable d, int x, int y, char* fg, char *str);
@@ -158,6 +170,7 @@ ushort textw(char *text);
/* infobar.c */ /* infobar.c */
void infobar_init(void); void infobar_init(void);
void infobar_draw_layout(InfoBar *i); void infobar_draw_layout(InfoBar *i);
void _infobar_draw(InfoBar *i);
void infobar_draw(InfoBar *i); void infobar_draw(InfoBar *i);
void infobar_draw_selbar(InfoBar *i); void infobar_draw_selbar(InfoBar *i);
void infobar_draw_taglist(InfoBar *i); void infobar_draw_taglist(InfoBar *i);
@@ -312,7 +325,6 @@ char *char_to_str(const char c);
pid_t spawn(const char *str, ...); pid_t spawn(const char *str, ...);
void swap_ptr(void **x, void **y); void swap_ptr(void **x, void **y);
void uicb_spawn(uicb_t); void uicb_spawn(uicb_t);
char *clean_value(char *str);
char* patht(char *path); char* patht(char *path);
int qsort_string_compare (const void * a, const void * b); int qsort_string_compare (const void * a, const void * b);
@@ -354,7 +366,8 @@ void uicb_screen_prev(uicb_t);
void uicb_screen_prev_sel(uicb_t); void uicb_screen_prev_sel(uicb_t);
/* status.c */ /* status.c */
void statustext_handle(int sc, char *str); void statustext_mouse(char *str, Geo area, InfoBar *infobar);
void statustext_handle(InfoBar *ib);
/* systray.c */ /* systray.c */
bool systray_acquire(void); bool systray_acquire(void);
@@ -435,14 +448,13 @@ void uicb_reload(uicb_t);
/* Variables */ /* Variables */
/* Principal */ /* Main */
Display *dpy; Display *dpy;
GC gc, gc_stipple; GC gc, gc_stipple;
int selscreen; int selscreen;
int prevselscreen; int prevselscreen;
Conf conf; Conf conf;
Key *keys; Key *keys;
bool estatus;
Geo *sgeo; Geo *sgeo;
Geo *spgeo; Geo *spgeo;
Cursor cursor[CurLast]; Cursor cursor[CurLast];
@@ -472,20 +484,28 @@ struct clndx {
Client *client; Client *client;
} clist_index[MAXCLIST]; } clist_index[MAXCLIST];
/* Important Client */ /* Client */
Client *clients; SLIST_HEAD(, Client) clients;
Client *sel; Client *sel;
/* Other */ /* Event */
int nevent; int nevent;
void (**event_handle)(XEvent*); void (**event_handle)(XEvent*);
extern const func_name_list_t func_list[]; extern const func_name_list_t func_list[];
extern const func_name_list_t layout_list[]; extern const func_name_list_t layout_list[];
uint numlockmask; uint numlockmask;
Systray *trayicons;
/* Systray */
SLIST_HEAD(, Systray) trayicons;
Window traywin; Window traywin;
int tray_width; int tray_width;
/* BarWindow */
SLIST_HEAD(, BarWindow) bwhead;
/* Status */
SLIST_HEAD(, StatusMouse) smhead;
#endif /* WMFS_H */ #endif /* WMFS_H */

15
wmfsrc
View File

@@ -11,15 +11,13 @@
font = "dejavu-10" font = "dejavu-10"
raisefocus = true raisefocus = true
focus_follow_mouse = true focus_follow_mouse = true
focus_follow_movement = false focus_follow_movement = true
opacity = 255 opacity = 255
# focus_pointer_click: click on unfocused client area: # focus_pointer_click: click on unfocused client area:
# true -- default, set focus # true -- default, set focus
# false -- click go to client; including dockapps # false -- click go to client; including dockapps
focus_pointer_click = true focus_pointer_click = true
status_timing = 1 #seconds
# status_path = "~/.config/wmfs/status.sh"
[/misc] [/misc]
[bar] [bar]
@@ -31,6 +29,12 @@
light_shade = 0.10 light_shade = 0.10
dark_shade = -0.10 dark_shade = -0.10
# Order of infobar elements:
# t = Tag list
# l = Layout button
# s = Selbar
elements_order = "tls"
[systray] [systray]
# Enable/disable systray # Enable/disable systray
active = true active = true
@@ -67,9 +71,6 @@
# Value menu or switch. # Value menu or switch.
system = "menu" system = "menu"
# Value left or right.
placement = "right"
# Keep layout geo for free layout # Keep layout geo for free layout
keep_layout_geo = false keep_layout_geo = false
@@ -311,6 +312,8 @@
prompt = "Exec: " prompt = "Exec: "
command = "exec" command = "exec"
[/set_launcher] [/set_launcher]
[/launcher]
[keys] [keys]
# Reload the configuration of wmfs. # Reload the configuration of wmfs.
[key] mod = {"Alt", "Control"} key = "r" func = "reload" [/key] [key] mod = {"Alt", "Control"} key = "r" func = "reload" [/key]