Compare commits

..

68 Commits
5.1 ... 5.4.1

Author SHA1 Message Date
90687482ad fixed an issue reported by Nibble, also fixed s/2008/2009/ 2009-02-08 12:11:22 +00:00
5ab627c06c Added tag 5.4 for changeset 8b7836a471f8 2009-02-08 09:47:02 +00:00
76d7e80fc4 avoid reverting the border if it's not necessary (avoids some flashing on view()) 2009-02-08 09:46:23 +00:00
af8049bce8 spotted missing spaces 2008-12-20 12:02:14 +00:00
2bb51b3246 reverting some border patches 2008-12-20 00:02:56 +00:00
b16d8282be changed adjustborder to be a macro 2008-12-19 23:56:00 +00:00
fef4614772 applied yiyus applyrules() patch 2008-12-19 23:41:31 +00:00
be39dddcc5 implemented noborder for 1 client in the view 2008-12-17 21:25:32 +00:00
6d209b9b29 made status script example of .xinitrc more useful 2008-12-13 20:20:26 +00:00
57a0788bd8 ok, using signal.h for portability reasons 2008-12-13 17:44:29 +00:00
3ad906eede removed unnecessary closure of stdin reported by Frederic Chardon, thx 2008-12-13 17:27:48 +00:00
0be9fb8797 added sys/signal.h inclusion for BSD compliance 2008-12-13 16:35:34 +00:00
62a491e36d re-applied Neale's spawn patch, credited Neale in LICENSE 2008-12-12 19:55:03 +00:00
0b5dcf229f applied Neale Pickett's xprop status reading patch, updated README and dwm.1 accordingly 2008-12-12 19:49:06 +00:00
fda92f46aa applied yiyus fix 2008-12-06 16:20:14 +00:00
a62ea4062f fix 2008-12-06 11:22:30 +00:00
7dc28d130f Added tag 5.3.1 for changeset 335301ed102f 2008-12-06 09:33:58 +00:00
fbce733532 integrated yiyus clearurgent refactoring 2008-12-06 09:32:32 +00:00
e7572804fa reverted spawn 2008-12-06 09:16:48 +00:00
ed1bef1241 Added tag 5.3 for changeset 4004d6116035 2008-12-04 20:23:08 +00:00
2b047e460b added Neale Pickett's spawn patch, thanks Neale 2008-12-04 20:15:00 +00:00
5f74dc5e78 applied Gottox' comment fix (thanks) 2008-11-16 13:22:24 +00:00
ea8a4ca46a several changes towards 5.3, XINERAMA is disabled by default, introduced usegrab Bool for grabbing the server during mouse-based resizals/movements (disabled by default), continued debugging tile() with resizehints == True and a lot of terminals supporting resizehints, still no optimal solution, I need to think about it, considering recursive algorithm for the space optimization 2008-10-19 12:59:18 +01:00
4883a06221 removed NOBORDER(broken and badly used), introduce WIDTH/HEIGHT macros for computing client size with border added, fixes bug announced by sergey_m 2008-10-15 18:08:24 +02:00
4dea5324c0 Added tag 5.2 for changeset e4bcaca8e6ef 2008-09-09 20:47:01 +01:00
53cac17692 using malloc() instead of calloc() and sticking to static initializer and struct assignment, not using *c = (Client){}; right now to avoid some ugly gcc warning, possibly a gcc bug since we are using -std=c99 2008-09-08 22:24:05 +01:00
83abfc05eb applied XGetWMNormalHints fix 2008-09-07 09:53:59 +01:00
862b0d541d I prefer doing the check in showhide 2008-09-06 09:34:49 +01:00
c1c6fdc5d8 applied Donald Chai's showhide patch in slightly modified ways 2008-09-06 09:21:32 +01:00
9a4d07d9de applied Martin Hurton's checkotherwm simplification 2008-09-06 08:59:51 +01:00
30410108eb applied Peter Hartlichs aspect revert fix 2008-09-02 22:36:06 +01:00
753e0e048e applied Gottox' grabkey patch 2008-09-02 18:47:01 +01:00
d15d4ba45a applied yiyus tagbar patch 2008-09-01 22:18:50 +01:00
815f9c054d merged merge 2008-09-01 08:22:11 +00:00
addc52c948 fixed 2008-08-29 11:29:42 +01:00
26f41c9055 checking result of XGetClassHint, removed some obsolete lines in initfont() 2008-08-29 10:13:47 +01:00
73ec124ae9 merged my changes 2008-08-27 15:03:35 +01:00
ec11a3470c introduced NOBORDER macro to hide the nasty - 2 * c->bw in various calculations, moved tagset to config.def.h 2008-08-27 12:52:44 +01:00
4b3b597da3 WM_NAME is builtin atom 2008-08-25 11:43:45 +02:00
288cf78b18 grabbuttons() and grabkeys() are now independent from prior numlockmask initialization 2008-08-25 09:44:23 +01:00
6411aa921b reverted some resize() changes, reverted setlocale removal 2008-08-25 09:37:39 +01:00
db5db8806f applied Peter Hartlich's patch regarding aspect calculation with slight modifications 2008-08-23 09:54:55 +01:00
258c338030 removed artifact from wmii 2008-08-23 09:33:05 +01:00
85da537856 changed grabkeys, removed initmodmap 2008-08-23 09:31:28 +01:00
2b4157eccd applied Peter Hartlich's initmodmap patch 2008-08-23 09:26:11 +01:00
0f26de991f applied fix of toggletag by Jan Kaliszewski 2008-08-22 15:26:30 +02:00
840f937a98 Martin Hurtons typo fix 2008-08-18 19:28:57 +01:00
6975a7e31a fixed error I did when applying Martin Hurton's drawtext patch 2008-08-18 19:23:03 +01:00
47f63dce55 applied Martin Hurtons resizemouse patch 2008-08-18 19:19:15 +01:00
02a8ca95cf applied Martin Hurton's movemouse() patch 2008-08-18 18:23:39 +01:00
2ce50a9cad using None instead of 0 for trans 2008-08-18 10:22:46 +01:00
bfa5869da1 abc... 2008-08-18 10:21:24 +01:00
087a55f8d3 removed the i = textnw... as remarked by Martin Hurton 2008-08-18 10:16:36 +01:00
6d7285fd6e applied Martin Hurton's scan() patch with slight modifications 2008-08-18 10:14:51 +01:00
69c7b4b0ba changed order of variables in drawtext 2008-08-18 10:00:10 +01:00
97699e5b1b applied Martin Hurton's drawtext() patch 2008-08-18 09:55:36 +01:00
2dc7f42fd7 applied Martin Hurton's view() simplification, not checking arg 2008-08-18 09:49:44 +01:00
9f3a5cb754 making a comment more explicit 2008-08-18 09:39:52 +01:00
b48fa3f101 removed setlocale() stuff, not necessary if Xmb in use 2008-08-18 09:31:55 +01:00
051a404b66 added a comment about FAQ regarding mfact meaning 2008-08-18 09:11:15 +01:00
d8d733c34f added some comments regarding FAQ about s{x,y,w,h}, w{x,y,w,h}, b{y,h,lw} 2008-08-18 09:10:21 +01:00
bb01e5a16f initialize trans with 0 2008-08-18 08:57:34 +01:00
06f7eed103 fix of XGetTransientForHint in manage() 2008-08-14 22:35:52 +02:00
0ffa6d1393 applied cleanup from M. Hurton and S. Nagy 2008-08-14 12:36:49 +02:00
15ce143620 fixes using arg->i instead of arg->ui 2008-08-12 21:24:40 +02:00
63d7190231 applied Johannes Hofmann's patch, please test 2008-08-04 17:39:36 +01:00
b279cef670 made readin a config.h variable 2008-08-02 19:12:15 +01:00
6254ef9dc7 Added tag 5.1 for changeset ce355cea9bb8 2008-07-29 19:19:00 +01:00
7 changed files with 269 additions and 272 deletions

View File

@ -54,3 +54,8 @@ d6d3085307d8d98b8b012b669e858fd787befeb1 4.7
607015ddb091d49cbd3457af41713691aa69f4d6 4.8 607015ddb091d49cbd3457af41713691aa69f4d6 4.8
22c669b2dd3673785c3476b9976da21e8783f745 4.9 22c669b2dd3673785c3476b9976da21e8783f745 4.9
06eb9644e2dad7667d97495eb7d7bc62aa0429e8 5.0 06eb9644e2dad7667d97495eb7d7bc62aa0429e8 5.0
ce355cea9bb89e162f61913737a46908cdfa7e45 5.1
e4bcaca8e6ef13d2c3b81f1218ad15e5da4d68bd 5.2
4004d61160355d869a7d2672561caad440751ba0 5.3
335301ed102fec9b1a15d06bfa0184d53b38fa54 5.3.1
8b7836a471f8f9ee61bec980df00971888d76343 5.4

View File

@ -1,12 +1,15 @@
MIT/X Consortium License MIT/X Consortium License
© 2006-2008 Anselm R Garbe <garbeam at gmail dot com> © 2006-2009 Anselm R Garbe <garbeam at gmail dot com>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com> © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2006-2007 Jukka Salmi <jukka at salmi dot ch> © 2006-2007 Jukka Salmi <jukka at salmi dot ch>
© 2007 Premysl Hruby <dfenze at gmail dot com> © 2007 Premysl Hruby <dfenze at gmail dot com>
© 2007 Szabolcs Nagy <nszabolcs at gmail dot com> © 2007 Szabolcs Nagy <nszabolcs at gmail dot com>
© 2007 Christof Musik <christof at sendfax dot de> © 2007 Christof Musik <christof at sendfax dot de>
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de> © 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
© 2007-2008 Peter Hartlich <sgkkr at hartlich dot com>
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
© 2008 Neale Pickett <neale dot woozle dot org>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

5
README
View File

@ -40,9 +40,10 @@ like this in your .xinitrc:
while true while true
do do
echo `date` `uptime | sed 's/.*,//'` xsetroot -name "`date` `uptime | sed 's/.*,//'`"
sleep 1 sleep 1
done | dwm done &
exec dwm
Configuration Configuration

View File

@ -12,9 +12,12 @@ static unsigned int borderpx = 1; /* border pixel of windows */
static unsigned int snap = 32; /* snap pixel */ static unsigned int snap = 32; /* snap pixel */
static Bool showbar = True; /* False means no bar */ static Bool showbar = True; /* False means no bar */
static Bool topbar = True; /* False means bottom bar */ static Bool topbar = True; /* False means bottom bar */
static Bool usegrab = False; /* True means grabbing the X server
during mouse-based resizals */
/* tagging */ /* tagging */
static const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
static Rule rules[] = { static Rule rules[] = {
/* class instance title tags mask isfloating */ /* class instance title tags mask isfloating */
@ -23,7 +26,7 @@ static Rule rules[] = {
}; };
/* layout(s) */ /* layout(s) */
static float mfact = 0.55; static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static Bool resizehints = True; /* False means respect size hints in tiled resizals */ static Bool resizehints = True; /* False means respect size hints in tiled resizals */
static Layout layouts[] = { static Layout layouts[] = {

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 5.1 VERSION = 5.4.1
# Customize below to fit your system # Customize below to fit your system
@ -10,9 +10,9 @@ MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
# Xinerama, comment if you don't want it # Xinerama, un-comment if you want it
XINERAMALIBS = -L${X11LIB} -lXinerama #XINERAMALIBS = -L${X11LIB} -lXinerama
XINERAMAFLAGS = -DXINERAMA #XINERAMAFLAGS = -DXINERAMA
# includes and libs # includes and libs
INCS = -I. -I/usr/include -I${X11INC} INCS = -I. -I/usr/include -I${X11INC}

14
dwm.1
View File

@ -20,13 +20,13 @@ Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting certain tags displays all windows with these tags. tags. Selecting certain tags displays all windows with these tags.
.P .P
dwm contains a small status bar which displays all available tags, the layout, dwm contains a small status bar which displays all available tags, the layout,
the title of the focused window, and the text read from standard input. A the title of the focused window, and the text read from the root window name
floating window is indicated with an empty square and a maximised property. A floating window is indicated with an empty square and a maximised
floating window is indicated with a filled square before the windows floating window is indicated with a filled square before the windows title.
title. The selected tags are indicated with a different color. The tags of The selected tags are indicated with a different color. The tags of the focused
the focused window are indicated with a filled square in the top left window are indicated with a filled square in the top left corner. The tags
corner. The tags which are applied to one or more windows are indicated which are applied to one or more windows are indicated with an empty square in
with an empty square in the top left corner. the top left corner.
.P .P
dwm draws a small border around windows to indicate the focus state. dwm draws a small border around windows to indicate the focus state.
.SH OPTIONS .SH OPTIONS

499
dwm.c
View File

@ -6,16 +6,13 @@
* events about window (dis-)appearance. Only one X connection at a time is * events about window (dis-)appearance. Only one X connection at a time is
* allowed to select for this event mask. * allowed to select for this event mask.
* *
* Calls to fetch an X event from the event queue are blocking. Due reading * The event handlers of dwm are organized in an array which is accessed
* status text from standard input, a select()-driven main loop has been * whenever a new event has been fetched. This allows event dispatching
* implemented which selects for reads on the X connection and STDIN_FILENO to * in O(1) time.
* handle all data smoothly. The event handlers of dwm are organized in an
* array which is accessed whenever a new event has been fetched. This allows
* event dispatching in O(1) time.
* *
* Each child of the root window is called a client, except windows which have * Each child of the root window is called a client, except windows which have
* set the override_redirect flag. Clients are organized in a global * set the override_redirect flag. Clients are organized in a global
* doubly-linked client list, the focus history is remembered through a global * linked client list, the focus history is remembered through a global
* stack list. Each client contains a bit array to indicate the tags of a * stack list. Each client contains a bit array to indicate the tags of a
* client. * client.
* *
@ -26,11 +23,11 @@
#include <errno.h> #include <errno.h>
#include <locale.h> #include <locale.h>
#include <stdarg.h> #include <stdarg.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/select.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
@ -53,6 +50,8 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAXTAGLEN 16 #define MAXTAGLEN 16
#define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(x) ((x)->w + 2 * (x)->bw)
#define HEIGHT(x) ((x)->h + 2 * (x)->bw)
#define TAGMASK ((int)((1LL << LENGTH(tags)) - 1)) #define TAGMASK ((int)((1LL << LENGTH(tags)) - 1))
#define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height) #define TEXTW(x) (textnw(x, strlen(x)) + dc.font.height)
@ -60,7 +59,7 @@
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@ -129,6 +128,7 @@ typedef struct {
} Rule; } Rule;
/* function declarations */ /* function declarations */
static void adjustborder(Client *c, unsigned int bw);
static void applyrules(Client *c); static void applyrules(Client *c);
static void arrange(void); static void arrange(void);
static void attach(Client *c); static void attach(Client *c);
@ -136,7 +136,7 @@ static void attachstack(Client *c);
static void buttonpress(XEvent *e); static void buttonpress(XEvent *e);
static void checkotherwm(void); static void checkotherwm(void);
static void cleanup(void); static void cleanup(void);
static void clearurgent(void); static void clearurgent(Client *c);
static void configure(Client *c); static void configure(Client *c);
static void configurenotify(XEvent *e); static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e); static void configurerequest(XEvent *e);
@ -159,9 +159,7 @@ static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, Bool focused); static void grabbuttons(Client *c, Bool focused);
static void grabkeys(void); static void grabkeys(void);
static void initfont(const char *fontstr); static void initfont(const char *fontstr);
static Bool isoccupied(unsigned int t);
static Bool isprotodel(Client *c); static Bool isprotodel(Client *c);
static Bool isurgent(unsigned int t);
static void keypress(XEvent *e); static void keypress(XEvent *e);
static void killclient(const Arg *arg); static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa); static void manage(Window w, XWindowAttributes *wa);
@ -181,6 +179,8 @@ static void setclientstate(Client *c, long state);
static void setlayout(const Arg *arg); static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg); static void setmfact(const Arg *arg);
static void setup(void); static void setup(void);
static void showhide(Client *c, unsigned int ntiled);
static void sigchld(int signal);
static void spawn(const Arg *arg); static void spawn(const Arg *arg);
static void tag(const Arg *arg); static void tag(const Arg *arg);
static int textnw(const char *text, unsigned int len); static int textnw(const char *text, unsigned int len);
@ -193,7 +193,9 @@ static void unmanage(Client *c);
static void unmapnotify(XEvent *e); static void unmapnotify(XEvent *e);
static void updatebar(void); static void updatebar(void);
static void updategeom(void); static void updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c); static void updatesizehints(Client *c);
static void updatestatus(void);
static void updatetitle(Client *c); static void updatetitle(Client *c);
static void updatewmhints(Client *c); static void updatewmhints(Client *c);
static void view(const Arg *arg); static void view(const Arg *arg);
@ -204,8 +206,10 @@ static void zoom(const Arg *arg);
/* variables */ /* variables */
static char stext[256]; static char stext[256];
static int screen, sx, sy, sw, sh; static int screen;
static int by, bh, blw, wx, wy, ww, wh; static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */
static int by, bh, blw; /* bar geometry y, height and layout symbol width */
static int wx, wy, ww, wh; /* window area geometry x, y, width, height, bar excluded */
static unsigned int seltags = 0, sellt = 0; static unsigned int seltags = 0, sellt = 0;
static int (*xerrorxlib)(Display *, XErrorEvent *); static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0; static unsigned int numlockmask = 0;
@ -224,15 +228,14 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[UnmapNotify] = unmapnotify [UnmapNotify] = unmapnotify
}; };
static Atom wmatom[WMLast], netatom[NetLast]; static Atom wmatom[WMLast], netatom[NetLast];
static Bool otherwm, readin; static Bool otherwm;
static Bool running = True; static Bool running = True;
static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
static Client *clients = NULL; static Client *clients = NULL;
static Client *sel = NULL; static Client *sel = NULL;
static Client *stack = NULL; static Client *stack = NULL;
static Cursor cursor[CurLast]; static Cursor cursor[CurLast];
static Display *dpy; static Display *dpy;
static DC dc = {0}; static DC dc;
static Layout *lt[] = { NULL, NULL }; static Layout *lt[] = { NULL, NULL };
static Window root, barwin; static Window root, barwin;
/* configuration, allows nested code to access above variables */ /* configuration, allows nested code to access above variables */
@ -242,6 +245,16 @@ static Window root, barwin;
struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; }; struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; };
/* function implementations */ /* function implementations */
void
adjustborder(Client *c, unsigned int bw) {
XWindowChanges wc;
if(c->bw != bw) {
c->bw = wc.border_width = bw;
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc);
}
}
void void
applyrules(Client *c) { applyrules(Client *c) {
unsigned int i; unsigned int i;
@ -249,38 +262,32 @@ applyrules(Client *c) {
XClassHint ch = { 0 }; XClassHint ch = { 0 };
/* rule matching */ /* rule matching */
XGetClassHint(dpy, c->win, &ch); if(XGetClassHint(dpy, c->win, &ch)) {
for(i = 0; i < LENGTH(rules); i++) { for(i = 0; i < LENGTH(rules); i++) {
r = &rules[i]; r = &rules[i];
if((!r->title || strstr(c->name, r->title)) if((!r->title || strstr(c->name, r->title))
&& (!r->class || (ch.res_class && strstr(ch.res_class, r->class))) && (!r->class || (ch.res_class && strstr(ch.res_class, r->class)))
&& (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) { && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) {
c->isfloating = r->isfloating; c->isfloating = r->isfloating;
c->tags |= r->tags & TAGMASK; c->tags |= r->tags & TAGMASK ? r->tags & TAGMASK : tagset[seltags];
}
} }
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
} }
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
if(!c->tags) if(!c->tags)
c->tags = tagset[seltags]; c->tags = tagset[seltags];
} }
void void
arrange(void) { arrange(void) {
unsigned int nt;
Client *c; Client *c;
for(c = clients; c; c = c->next) for(nt = 0, c = nexttiled(clients); c; c = nexttiled(c->next), nt++);
if(ISVISIBLE(c)) { showhide(stack, nt);
XMoveWindow(dpy, c->win, c->x, c->y);
if(!lt[sellt]->arrange || c->isfloating)
resize(c, c->x, c->y, c->w, c->h, True);
}
else {
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
}
focus(NULL); focus(NULL);
if(lt[sellt]->arrange) if(lt[sellt]->arrange)
lt[sellt]->arrange(); lt[sellt]->arrange();
@ -329,30 +336,28 @@ buttonpress(XEvent *e) {
for(i = 0; i < LENGTH(buttons); i++) for(i = 0; i < LENGTH(buttons); i++)
if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
buttons[i].func(click == ClkTagBar ? &arg : &buttons[i].arg); buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
} }
void void
checkotherwm(void) { checkotherwm(void) {
otherwm = False; otherwm = False;
XSetErrorHandler(xerrorstart); xerrorxlib = XSetErrorHandler(xerrorstart);
/* this causes an error if some other window manager is running */ /* this causes an error if some other window manager is running */
XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
XSync(dpy, False); XSync(dpy, False);
if(otherwm) if(otherwm)
die("dwm: another window manager is already running\n"); die("dwm: another window manager is already running\n");
XSetErrorHandler(NULL); XSetErrorHandler(xerror);
xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False); XSync(dpy, False);
} }
void void
cleanup(void) { cleanup(void) {
Arg a = {.i = ~0}; Arg a = {.ui = ~0};
Layout foo = { "", NULL }; Layout foo = { "", NULL };
close(STDIN_FILENO);
view(&a); view(&a);
lt[sellt] = &foo; lt[sellt] = &foo;
while(stack) while(stack)
@ -373,20 +378,15 @@ cleanup(void) {
} }
void void
clearurgent(void) { clearurgent(Client *c) {
XWMHints *wmh; XWMHints *wmh;
Client *c;
for(c = clients; c; c = c->next) c->isurgent = False;
if(ISVISIBLE(c) && c->isurgent) { if(!(wmh = XGetWMHints(dpy, c->win)))
c->isurgent = False; return;
if (!(wmh = XGetWMHints(dpy, c->win))) wmh->flags &= ~XUrgencyHint;
continue; XSetWMHints(dpy, c->win, wmh);
XFree(wmh);
wmh->flags &= ~XUrgencyHint;
XSetWMHints(dpy, c->win, wmh);
XFree(wmh);
}
} }
void void
@ -500,19 +500,23 @@ die(const char *errstr, ...) {
void void
drawbar(void) { drawbar(void) {
int i, x; int x;
unsigned int i, occ = 0, urg = 0;
unsigned long *col;
Client *c;
for(c = clients; c; c = c->next) {
occ |= c->tags;
if(c->isurgent)
urg |= c->tags;
}
dc.x = 0; dc.x = 0;
for(i = 0; i < LENGTH(tags); i++) { for(i = 0; i < LENGTH(tags); i++) {
dc.w = TEXTW(tags[i]); dc.w = TEXTW(tags[i]);
if(tagset[seltags] & 1 << i) { col = tagset[seltags] & 1 << i ? dc.sel : dc.norm;
drawtext(tags[i], dc.sel, isurgent(i)); drawtext(tags[i], col, urg & 1 << i);
drawsquare(sel && sel->tags & 1 << i, isoccupied(i), isurgent(i), dc.sel); drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col);
}
else {
drawtext(tags[i], dc.norm, isurgent(i));
drawsquare(sel && sel->tags & 1 << i, isoccupied(i), isurgent(i), dc.norm);
}
dc.x += dc.w; dc.x += dc.w;
} }
if(blw > 0) { if(blw > 0) {
@ -565,24 +569,23 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
void void
drawtext(const char *text, unsigned long col[ColLast], Bool invert) { drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
char buf[256];
int i, x, y, h, len, olen; int i, x, y, h, len, olen;
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; XRectangle r = { dc.x, dc.y, dc.w, dc.h };
char buf[256];
XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text) if(!text)
return; return;
olen = strlen(text); olen = strlen(text);
len = MIN(olen, sizeof buf);
memcpy(buf, text, len);
h = dc.font.ascent + dc.font.descent; h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2); x = dc.x + (h / 2);
/* shorten text if necessary */ /* shorten text if necessary */
for(; len && (i = textnw(buf, len)) > dc.w - h; len--); for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
if(!len) if(!len)
return; return;
memcpy(buf, text, len);
if(len < olen) if(len < olen)
for(i = len; i && i > len - 3; buf[--i] = '.'); for(i = len; i && i > len - 3; buf[--i] = '.');
XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
@ -622,6 +625,8 @@ focus(Client *c) {
XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
} }
if(c) { if(c) {
if(c->isurgent)
clearurgent(c);
detachstack(c); detachstack(c);
attachstack(c); attachstack(c);
grabbuttons(c, True); grabbuttons(c, True);
@ -732,46 +737,37 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
void void
grabbuttons(Client *c, Bool focused) { grabbuttons(Client *c, Bool focused) {
unsigned int i, j; updatenumlockmask();
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; {
unsigned int i, j;
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
if(focused) { XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
for(i = 0; i < LENGTH(buttons); i++) if(focused) {
if(buttons[i].click == ClkClientWin) for(i = 0; i < LENGTH(buttons); i++)
for(j = 0; j < LENGTH(modifiers); j++) if(buttons[i].click == ClkClientWin)
XGrabButton(dpy, buttons[i].button, buttons[i].mask | modifiers[j], c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); for(j = 0; j < LENGTH(modifiers); j++)
} else XGrabButton(dpy, buttons[i].button, buttons[i].mask | modifiers[j], c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, } else
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
}
} }
void void
grabkeys(void) { grabkeys(void) {
unsigned int i, j; updatenumlockmask();
KeyCode code; { /* grab keys */
XModifierKeymap *modmap; unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
KeyCode code;
/* init modifier map */ XUngrabKey(dpy, AnyKey, AnyModifier, root);
modmap = XGetModifierMapping(dpy); for(i = 0; i < LENGTH(keys); i++) {
for(i = 0; i < 8; i++) if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
for(j = 0; j < modmap->max_keypermod; j++) { for(j = 0; j < LENGTH(modifiers); j++)
if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
numlockmask = (1 << i); True, GrabModeAsync, GrabModeAsync);
} }
XFreeModifiermap(modmap);
XUngrabKey(dpy, AnyKey, AnyModifier, root);
for(i = 0; i < LENGTH(keys); i++) {
code = XKeysymToKeycode(dpy, keys[i].keysym);
XGrabKey(dpy, code, keys[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|LockMask, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|numlockmask|LockMask, root, True,
GrabModeAsync, GrabModeAsync);
} }
} }
@ -781,8 +777,6 @@ initfont(const char *fontstr) {
int i, n; int i, n;
missing = NULL; missing = NULL;
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing) { if(missing) {
while(n--) while(n--)
@ -803,9 +797,6 @@ initfont(const char *fontstr) {
} }
} }
else { else {
if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL;
if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
die("error, cannot load font: '%s'\n", fontstr); die("error, cannot load font: '%s'\n", fontstr);
@ -815,16 +806,6 @@ initfont(const char *fontstr) {
dc.font.height = dc.font.ascent + dc.font.descent; dc.font.height = dc.font.ascent + dc.font.descent;
} }
Bool
isoccupied(unsigned int t) {
Client *c;
for(c = clients; c; c = c->next)
if(c->tags & 1 << t)
return True;
return False;
}
Bool Bool
isprotodel(Client *c) { isprotodel(Client *c) {
int i, n; int i, n;
@ -840,16 +821,6 @@ isprotodel(Client *c) {
return ret; return ret;
} }
Bool
isurgent(unsigned int t) {
Client *c;
for(c = clients; c; c = c->next)
if(c->isurgent && c->tags & 1 << t)
return True;
return False;
}
void void
keypress(XEvent *e) { keypress(XEvent *e) {
unsigned int i; unsigned int i;
@ -886,13 +857,14 @@ killclient(const Arg *arg) {
void void
manage(Window w, XWindowAttributes *wa) { manage(Window w, XWindowAttributes *wa) {
static Client cz;
Client *c, *t = NULL; Client *c, *t = NULL;
Status rettrans; Window trans = None;
Window trans;
XWindowChanges wc; XWindowChanges wc;
if(!(c = calloc(1, sizeof(Client)))) if(!(c = malloc(sizeof(Client))))
die("fatal: could not calloc() %u bytes\n", sizeof(Client)); die("fatal: could not malloc() %u bytes\n", sizeof(Client));
*c = cz;
c->win = w; c->win = w;
/* geometry */ /* geometry */
@ -907,10 +879,10 @@ manage(Window w, XWindowAttributes *wa) {
c->bw = 0; c->bw = 0;
} }
else { else {
if(c->x + c->w + 2 * c->bw > sx + sw) if(c->x + WIDTH(c) > sx + sw)
c->x = sx + sw - c->w - 2 * c->bw; c->x = sx + sw - WIDTH(c);
if(c->y + c->h + 2 * c->bw > sy + sh) if(c->y + HEIGHT(c) > sy + sh)
c->y = sy + sh - c->h - 2 * c->bw; c->y = sy + sh - HEIGHT(c);
c->x = MAX(c->x, sx); c->x = MAX(c->x, sx);
/* only fix client y-offset, if the client center might cover the bar */ /* only fix client y-offset, if the client center might cover the bar */
c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= wx) && (c->x + (c->w / 2) < wx + ww)) ? bh : sy); c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= wx) && (c->x + (c->w / 2) < wx + ww)) ? bh : sy);
@ -925,14 +897,14 @@ manage(Window w, XWindowAttributes *wa) {
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
grabbuttons(c, False); grabbuttons(c, False);
updatetitle(c); updatetitle(c);
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) if(XGetTransientForHint(dpy, w, &trans))
for(t = clients; t && t->win != trans; t = t->next); t = getclient(trans);
if(t) if(t)
c->tags = t->tags; c->tags = t->tags;
else else
applyrules(c); applyrules(c);
if(!c->isfloating) if(!c->isfloating)
c->isfloating = (rettrans == Success) || c->isfixed; c->isfloating = trans != None || c->isfixed;
if(c->isfloating) if(c->isfloating)
XRaiseWindow(dpy, c->win); XRaiseWindow(dpy, c->win);
attach(c); attach(c);
@ -967,10 +939,14 @@ maprequest(XEvent *e) {
void void
monocle(void) { monocle(void) {
unsigned int n;
Client *c; Client *c;
for(c = nexttiled(clients); c; c = nexttiled(c->next)) for(n = 0, c = nexttiled(clients); c && n < 2; c = nexttiled(c->next), n++);
for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
adjustborder(c, n == 1 ? 0 : borderpx);
resize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw, resizehints); resize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw, resizehints);
}
} }
void void
@ -984,37 +960,35 @@ movemouse(const Arg *arg) {
if(!(c = sel)) if(!(c = sel))
return; return;
restack(); restack();
ocx = nx = c->x; ocx = c->x;
ocy = ny = c->y; ocy = c->y;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess) None, cursor[CurMove], CurrentTime) != GrabSuccess)
return; return;
XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui); XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
for(;;) { if(usegrab)
XGrabServer(dpy);
do {
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
switch (ev.type) { switch (ev.type) {
case ButtonRelease:
XUngrabPointer(dpy, CurrentTime);
return;
case ConfigureRequest: case ConfigureRequest:
case Expose: case Expose:
case MapRequest: case MapRequest:
handler[ev.type](&ev); handler[ev.type](&ev);
break; break;
case MotionNotify: case MotionNotify:
XSync(dpy, False);
nx = ocx + (ev.xmotion.x - x); nx = ocx + (ev.xmotion.x - x);
ny = ocy + (ev.xmotion.y - y); ny = ocy + (ev.xmotion.y - y);
if(snap && nx >= wx && nx <= wx + ww if(snap && nx >= wx && nx <= wx + ww
&& ny >= wy && ny <= wy + wh) { && ny >= wy && ny <= wy + wh) {
if(abs(wx - nx) < snap) if(abs(wx - nx) < snap)
nx = wx; nx = wx;
else if(abs((wx + ww) - (nx + c->w + 2 * c->bw)) < snap) else if(abs((wx + ww) - (nx + WIDTH(c))) < snap)
nx = wx + ww - c->w - 2 * c->bw; nx = wx + ww - WIDTH(c);
if(abs(wy - ny) < snap) if(abs(wy - ny) < snap)
ny = wy; ny = wy;
else if(abs((wy + wh) - (ny + c->h + 2 * c->bw)) < snap) else if(abs((wy + wh) - (ny + HEIGHT(c))) < snap)
ny = wy + wh - c->h - 2 * c->bw; ny = wy + wh - HEIGHT(c);
if(!c->isfloating && lt[sellt]->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) if(!c->isfloating && lt[sellt]->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
togglefloating(NULL); togglefloating(NULL);
} }
@ -1023,6 +997,10 @@ movemouse(const Arg *arg) {
break; break;
} }
} }
while(ev.type != ButtonRelease);
if(usegrab)
XUngrabServer(dpy);
XUngrabPointer(dpy, CurrentTime);
} }
Client * Client *
@ -1037,9 +1015,11 @@ propertynotify(XEvent *e) {
Window trans; Window trans;
XPropertyEvent *ev = &e->xproperty; XPropertyEvent *ev = &e->xproperty;
if(ev->state == PropertyDelete) if((ev->window == root) && (ev->atom = XA_WM_NAME))
updatestatus();
else if(ev->state == PropertyDelete)
return; /* ignore */ return; /* ignore */
if((c = getclient(ev->window))) { else if((c = getclient(ev->window))) {
switch (ev->atom) { switch (ev->atom) {
default: break; default: break;
case XA_WM_TRANSIENT_FOR: case XA_WM_TRANSIENT_FOR:
@ -1065,7 +1045,7 @@ propertynotify(XEvent *e) {
void void
quit(const Arg *arg) { quit(const Arg *arg) {
readin = running = False; running = False;
} }
void void
@ -1073,22 +1053,31 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
XWindowChanges wc; XWindowChanges wc;
if(sizehints) { if(sizehints) {
/* see last two sentences in ICCCM 4.1.2.3 */
Bool baseismin = c->basew == c->minw && c->baseh == c->minh;
/* set minimum possible */ /* set minimum possible */
w = MAX(1, w); w = MAX(1, w);
h = MAX(1, h); h = MAX(1, h);
/* temporarily remove base dimensions */ if(!baseismin) { /* temporarily remove base dimensions */
w -= c->basew; w -= c->basew;
h -= c->baseh; h -= c->baseh;
}
/* adjust for aspect limits */ /* adjust for aspect limits */
if(c->mina > 0 && c->maxa > 0) { if(c->mina > 0 && c->maxa > 0) {
if(c->maxa < (float) w/h) if(c->maxa < (float)w / h)
w = h * c->maxa; w = h * c->maxa;
else if(c->mina > (float) h/w) else if(c->mina < (float)h / w)
h = w * c->mina; h = w * c->mina;
} }
if(baseismin) { /* increment calculation requires this */
w -= c->basew;
h -= c->baseh;
}
/* adjust for increment value */ /* adjust for increment value */
if(c->incw) if(c->incw)
w -= w % c->incw; w -= w % c->incw;
@ -1111,9 +1100,9 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
if(w <= 0 || h <= 0) if(w <= 0 || h <= 0)
return; return;
if(x > sx + sw) if(x > sx + sw)
x = sw - w - 2 * c->bw; x = sw - WIDTH(c);
if(y > sy + sh) if(y > sy + sh)
y = sh - h - 2 * c->bw; y = sh - HEIGHT(c);
if(x + w + 2 * c->bw < sx) if(x + w + 2 * c->bw < sx)
x = sx; x = sx;
if(y + h + 2 * c->bw < sy) if(y + h + 2 * c->bw < sy)
@ -1151,22 +1140,17 @@ resizemouse(const Arg *arg) {
None, cursor[CurResize], CurrentTime) != GrabSuccess) None, cursor[CurResize], CurrentTime) != GrabSuccess)
return; return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
for(;;) { if(usegrab)
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask , &ev); XGrabServer(dpy);
do {
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
switch(ev.type) { switch(ev.type) {
case ButtonRelease:
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
c->w + c->bw - 1, c->h + c->bw - 1);
XUngrabPointer(dpy, CurrentTime);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
return;
case ConfigureRequest: case ConfigureRequest:
case Expose: case Expose:
case MapRequest: case MapRequest:
handler[ev.type](&ev); handler[ev.type](&ev);
break; break;
case MotionNotify: case MotionNotify:
XSync(dpy, False);
nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
@ -1181,6 +1165,12 @@ resizemouse(const Arg *arg) {
break; break;
} }
} }
while(ev.type != ButtonRelease);
if(usegrab)
XUngrabServer(dpy);
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
XUngrabPointer(dpy, CurrentTime);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
} }
void void
@ -1209,71 +1199,22 @@ restack(void) {
void void
run(void) { run(void) {
char *p;
char sbuf[sizeof stext];
fd_set rd;
int r, xfd;
unsigned int len, offset;
XEvent ev; XEvent ev;
/* main event loop, also reads status text from stdin */ /* main event loop */
XSync(dpy, False); XSync(dpy, False);
xfd = ConnectionNumber(dpy); while(running && !XNextEvent(dpy, &ev)) {
readin = True; if(handler[ev.type])
offset = 0; (handler[ev.type])(&ev); /* call handler */
len = sizeof stext - 1;
sbuf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
while(running) {
FD_ZERO(&rd);
if(readin)
FD_SET(STDIN_FILENO, &rd);
FD_SET(xfd, &rd);
if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
if(errno == EINTR)
continue;
die("select failed\n");
}
if(FD_ISSET(STDIN_FILENO, &rd)) {
switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) {
case -1:
strncpy(stext, strerror(errno), len);
readin = False;
break;
case 0:
strncpy(stext, "EOF", 4);
readin = False;
break;
default:
for(p = sbuf + offset; r > 0; p++, r--, offset++)
if(*p == '\n' || *p == '\0') {
*p = '\0';
strncpy(stext, sbuf, len);
p += r - 1; /* p is sbuf + offset + r - 1 */
for(r = 0; *(p - r) && *(p - r) != '\n'; r++);
offset = r;
if(r)
memmove(sbuf, p - r + 1, r);
break;
}
break;
}
drawbar();
}
while(XPending(dpy)) {
XNextEvent(dpy, &ev);
if(handler[ev.type])
(handler[ev.type])(&ev); /* call handler */
}
} }
} }
void void
scan(void) { scan(void) {
unsigned int i, num; unsigned int i, num;
Window *wins, d1, d2; Window d1, d2, *wins = NULL;
XWindowAttributes wa; XWindowAttributes wa;
wins = NULL;
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
for(i = 0; i < num; i++) { for(i = 0; i < num; i++) {
if(!XGetWindowAttributes(dpy, wins[i], &wa) if(!XGetWindowAttributes(dpy, wins[i], &wa)
@ -1289,9 +1230,9 @@ scan(void) {
&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
manage(wins[i], &wa); manage(wins[i], &wa);
} }
if(wins)
XFree(wins);
} }
if(wins)
XFree(wins);
} }
void void
@ -1350,7 +1291,6 @@ setup(void) {
/* init atoms */ /* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
@ -1388,8 +1328,7 @@ setup(void) {
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, barwin, cursor[CurNormal]); XDefineCursor(dpy, barwin, cursor[CurNormal]);
XMapRaised(dpy, barwin); XMapRaised(dpy, barwin);
strcpy(stext, "dwm-"VERSION); updatestatus();
drawbar();
/* EWMH support per view */ /* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
@ -1397,31 +1336,50 @@ setup(void) {
/* select for events */ /* select for events */
wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
|EnterWindowMask|LeaveWindowMask|StructureNotifyMask; |EnterWindowMask|LeaveWindowMask|StructureNotifyMask
|PropertyChangeMask;
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask); XSelectInput(dpy, root, wa.event_mask);
/* grab keys */
grabkeys(); grabkeys();
} }
void
showhide(Client *c, unsigned int ntiled) {
if(!c)
return;
if(ISVISIBLE(c)) { /* show clients top down */
if(c->isfloating || ntiled > 1) /* avoid unnecessary border reverts */
adjustborder(c, borderpx);
XMoveWindow(dpy, c->win, c->x, c->y);
if(!lt[sellt]->arrange || c->isfloating)
resize(c, c->x, c->y, c->w, c->h, True);
showhide(c->snext, ntiled);
}
else { /* hide clients bottom up */
showhide(c->snext, ntiled);
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
}
}
void
sigchld(int signal) {
while(0 < waitpid(-1, NULL, WNOHANG));
}
void void
spawn(const Arg *arg) { spawn(const Arg *arg) {
/* The double-fork construct avoids zombie processes and keeps the code signal(SIGCHLD, sigchld);
* clean from stupid signal handlers. */
if(fork() == 0) { if(fork() == 0) {
if(fork() == 0) { if(dpy)
if(dpy) close(ConnectionNumber(dpy));
close(ConnectionNumber(dpy)); setsid();
setsid(); execvp(((char **)arg->v)[0], (char **)arg->v);
execvp(((char **)arg->v)[0], (char **)arg->v); fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); perror(" failed");
perror(" failed");
}
exit(0); exit(0);
} }
wait(0);
} }
void void
@ -1456,6 +1414,7 @@ tile(void) {
/* master */ /* master */
c = nexttiled(clients); c = nexttiled(clients);
mw = mfact * ww; mw = mfact * ww;
adjustborder(c, n == 1 ? 0 : borderpx);
resize(c, wx, wy, (n == 1 ? ww : mw) - 2 * c->bw, wh - 2 * c->bw, resizehints); resize(c, wx, wy, (n == 1 ? ww : mw) - 2 * c->bw, wh - 2 * c->bw, resizehints);
if(--n == 0) if(--n == 0)
@ -1470,10 +1429,11 @@ tile(void) {
h = wh; h = wh;
for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
adjustborder(c, borderpx);
resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
? (wy + wh) - y : h) - 2 * c->bw, resizehints); ? wy + wh - y - 2 * c->bw : h - 2 * c->bw), resizehints);
if(h != wh) if(h != wh)
y = c->y + c->h + 2 * c->bw; y = c->y + HEIGHT(c);
} }
} }
@ -1497,8 +1457,12 @@ togglefloating(const Arg *arg) {
void void
toggletag(const Arg *arg) { toggletag(const Arg *arg) {
unsigned int mask = sel->tags ^ (arg->ui & TAGMASK); unsigned int mask;
if (!sel)
return;
mask = sel->tags ^ (arg->ui & TAGMASK);
if(sel && mask) { if(sel && mask) {
sel->tags = mask; sel->tags = mask;
arrange(); arrange();
@ -1511,7 +1475,6 @@ toggleview(const Arg *arg) {
if(mask) { if(mask) {
tagset[seltags] = mask; tagset[seltags] = mask;
clearurgent();
arrange(); arrange();
} }
} }
@ -1591,12 +1554,28 @@ updategeom(void) {
by = showbar ? (topbar ? wy - bh : wy + wh) : -bh; by = showbar ? (topbar ? wy - bh : wy + wh) : -bh;
} }
void
updatenumlockmask(void) {
unsigned int i, j;
XModifierKeymap *modmap;
numlockmask = 0;
modmap = XGetModifierMapping(dpy);
for(i = 0; i < 8; i++)
for(j = 0; j < modmap->max_keypermod; j++)
if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
XFreeModifiermap(modmap);
}
void void
updatesizehints(Client *c) { updatesizehints(Client *c) {
long msize; long msize;
XSizeHints size; XSizeHints size;
XGetWMNormalHints(dpy, c->win, &size, &msize); if(!XGetWMNormalHints(dpy, c->win, &size, &msize))
/* size is uninitialized, ensure that size.flags aren't used */
size.flags = PSize;
if(size.flags & PBaseSize) { if(size.flags & PBaseSize) {
c->basew = size.base_width; c->basew = size.base_width;
c->baseh = size.base_height; c->baseh = size.base_height;
@ -1636,13 +1615,20 @@ updatesizehints(Client *c) {
else else
c->maxa = c->mina = 0.0; c->maxa = c->mina = 0.0;
c->isfixed = (c->maxw && c->minw && c->maxh && c->minh c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
&& c->maxw == c->minw && c->maxh == c->minh); && c->maxw == c->minw && c->maxh == c->minh);
} }
void void
updatetitle(Client *c) { updatetitle(Client *c) {
if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name); gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
}
void
updatestatus() {
if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
drawbar();
} }
void void
@ -1650,7 +1636,7 @@ updatewmhints(Client *c) {
XWMHints *wmh; XWMHints *wmh;
if((wmh = XGetWMHints(dpy, c->win))) { if((wmh = XGetWMHints(dpy, c->win))) {
if(ISVISIBLE(c) && wmh->flags & XUrgencyHint) { if(c == sel && wmh->flags & XUrgencyHint) {
wmh->flags &= ~XUrgencyHint; wmh->flags &= ~XUrgencyHint;
XSetWMHints(dpy, c->win, wmh); XSetWMHints(dpy, c->win, wmh);
} }
@ -1663,12 +1649,11 @@ updatewmhints(Client *c) {
void void
view(const Arg *arg) { view(const Arg *arg) {
if(arg && (arg->i & TAGMASK) == tagset[seltags]) if((arg->ui & TAGMASK) == tagset[seltags])
return; return;
seltags ^= 1; /* toggle sel tagset */ seltags ^= 1; /* toggle sel tagset */
if(arg && (arg->ui & TAGMASK)) if(arg->ui & TAGMASK)
tagset[seltags] = arg->i & TAGMASK; tagset[seltags] = arg->ui & TAGMASK;
clearurgent();
arrange(); arrange();
} }
@ -1723,7 +1708,7 @@ zoom(const Arg *arg) {
int int
main(int argc, char *argv[]) { main(int argc, char *argv[]) {
if(argc == 2 && !strcmp("-v", argv[1])) if(argc == 2 && !strcmp("-v", argv[1]))
die("dwm-"VERSION", © 2006-2008 dwm engineers, see LICENSE for details\n"); die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n");
else if(argc != 1) else if(argc != 1)
die("usage: dwm [-v]\n"); die("usage: dwm [-v]\n");