You are not logged in.

#351 2011-07-28 12:14:45

0mark
Member
From: earth
Registered: 2010-06-09
Posts: 162
Website

Re: Show off your Dwm configuration!

null wrote:

but (false) transparent bar for dwm would be fancy! looking forward to anyone who submit a patch tongue

You are right. Here:
preview
(Bar with 80% opacity)
Depends on transpareny Patch for dwm.
Just add these two line to the for loop in function updatebars:

unsigned long real_opacity[] = { 0.8 * 0xffffffff };
XChangeProperty(dpy, m->barwin, netatom[NetWMWindowOpacity], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)real_opacity, 1);

(Change 0.8 (80%) to whatever you like)


Ceterum autem censeo Systemdinem esse delendam

Offline

#352 2011-07-30 17:02:31

iTwenty
Member
From: India
Registered: 2010-10-24
Posts: 63
Website

Re: Show off your Dwm configuration!

New dwm convert here. One look at the statusbar and I knew I just had to apply the pango patch tongue

tOW93bgtOW93cA


“Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore. Dream. Discover.” - Mark Twain

Offline

#353 2011-07-30 18:03:05

null
Member
Registered: 2009-05-06
Posts: 398

Re: Show off your Dwm configuration!

one question: why do you use a wallpaper about wm's/de's which doesn't contain the one you're actually using?

just curious tongue


and @0mark:
Thanks a lot, next time I feel like patching dwm again I'll try it. But I would prefer a solution without true transparency/xcompmgr. Isn't it too much just for the panel?

Last edited by null (2011-07-30 18:05:54)

Offline

#354 2011-07-31 18:33:07

iTwenty
Member
From: India
Registered: 2010-10-24
Posts: 63
Website

Re: Show off your Dwm configuration!

null wrote:

one question: why do you use a wallpaper about wm's/de's which doesn't contain the one you're actually using?

just curious tongue

I use a script to randomly select an image from a folder on each start of dwm and set it as wallpaper. This image happens to exist in that folder. tongue


“Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore. Dream. Discover.” - Mark Twain

Offline

#355 2011-07-31 18:37:27

null
Member
Registered: 2009-05-06
Posts: 398

Re: Show off your Dwm configuration!

fair enough smile

Offline

#356 2011-08-01 12:06:43

0mark
Member
From: earth
Registered: 2010-06-09
Posts: 162
Website

Re: Show off your Dwm configuration!

null wrote:

and @0mark:
Thanks a lot, next time I feel like patching dwm again I'll try it. But I would prefer a solution without true transparency/xcompmgr. Isn't it too much just for the panel?

I dont think so. Using true transparency should be faster and more power efficient, since its (normally) done by the gpu. On my Notebook it is even better to have compositing running, even if not used for anything. Untrue transparency need to grab the underlying background every now and then, or at least when the wallpaper changes.


Ceterum autem censeo Systemdinem esse delendam

Offline

#357 2011-08-10 21:36:15

nixfag
Member
From: Romania
Registered: 2011-03-03
Posts: 73

Re: Show off your Dwm configuration!

dwm211310082011thumb.png
I've been a dwm devotee for a while but I'm thinking to give a try to stumpwm.

Last edited by nixfag (2011-08-10 22:24:53)

Offline

#358 2011-08-11 01:47:35

mjheagle8
Member
From: /home/mjheagle8
Registered: 2009-07-12
Posts: 186

Re: Show off your Dwm configuration!

havent posted in a while. tried out wmfs recently, but came back after a few days and wrote a default tag layouts patch for dwm. smile



-- mod edit: read the rules and only post thumbnails https://bbs.archlinux.org/viewtopic.php?id=61754  [jwr] --


Desktop/Laptop - DWM :: VM - screen
Registered Linux User Number 483137 :: Victory! :: GitHub

Offline

#359 2011-08-11 17:42:51

x33a
Forum Fellow
Registered: 2009-08-15
Posts: 4,587

Re: Show off your Dwm configuration!

mjheagle8 wrote:

https://github.com/mjheagle8/dwm/raw/master/screenshot-small.png

havent posted in a while. tried out wmfs recently, but came back after a few days and wrote a default tag layouts patch for dwm. smile

Really nice color scheme, can you post your .Xresources/.Xdefaults.

Offline

#360 2011-08-12 01:17:52

mjheagle8
Member
From: /home/mjheagle8
Registered: 2009-07-12
Posts: 186

Re: Show off your Dwm configuration!

thanks! its a modified version of thayers colors. dwm colors are set to match.

*background:  rgba:0000/0000/0000/dddd
*foreground:  #aaaaaa
! Black
*color0:      #222222
*color8:      #555753
! Red
*color1:      #ff6565
*color9:      #ff8d8d
! Green
*color2:      #93d44f
*color10:     #c8e7a8
! Yellow
*color3:      #eab93d
*color11:     #ffc123
! Blue
*color4:      #0055ff
*color12:     #3465a4
! Magenta
*color5:      #ce5c00
*color13:     #f57900
! Cyan 
*color6:      #89b6e2
*color14:     #46a4ff
! White
*color7:      #cccccc
*color15:     #ffffff

Desktop/Laptop - DWM :: VM - screen
Registered Linux User Number 483137 :: Victory! :: GitHub

Offline

#361 2011-08-16 14:59:22

ibrunton
Member
From: Canada
Registered: 2011-05-05
Posts: 270

Re: Show off your Dwm configuration!

This is my DWM setup for my new notebook for school this September.

201108161138-thumb.png 201108161157-thumb.png

Same .Xdefaults as on my desktop because I haven't fiddled with it yet on the laptop to suit the colour scheme. Also, I haven't yet put any effort into dealing with the WM-hints artefacts in urxvt (have resizehints = False in my config.h already).

DWM 5.9 + attachaside patch + jokerboy's pertag2, gaps, and focusonclick patches.

Offline

#362 2011-08-16 16:48:53

OK100
Member
From: [U==]
Registered: 2010-04-26
Posts: 455

Re: Show off your Dwm configuration!

ibrunton wrote:

Also, I haven't yet put any effort into dealing with the WM-hints artefacts in urxvt (have resizehints = False in my config.h already).

Use rxvt-unicode-patched from AUR.

Offline

#363 2011-08-16 17:57:14

nXqd
Member
Registered: 2010-07-01
Posts: 173

Re: Show off your Dwm configuration!

[wrong section]

Last edited by nXqd (2011-08-20 05:13:04)


When you live for a strong purpose, then hard work isn't an option. It's a necessity. - Steve Pavlina
dotFiles

Offline

#364 2011-08-16 18:53:02

ibrunton
Member
From: Canada
Registered: 2011-05-05
Posts: 270

Re: Show off your Dwm configuration!

OK100 wrote:

Use rxvt-unicode-patched from AUR.

Nice! Thanks!

Offline

#365 2011-08-17 14:28:46

nXqd
Member
Registered: 2010-07-01
Posts: 173

Re: Show off your Dwm configuration!

bump big_smile


When you live for a strong purpose, then hard work isn't an option. It's a necessity. - Steve Pavlina
dotFiles

Offline

#366 2011-08-17 14:43:01

mjheagle8
Member
From: /home/mjheagle8
Registered: 2009-07-12
Posts: 186

Re: Show off your Dwm configuration!

nXqd wrote:

I have something to ask you guys :

1. i want to map [Windows key] which is Mod4Mask to open dmenu, I think it's quite simple but maybe i'm stupid ...  Things I've tried :

{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } }, // < this works flawlessly

{ 0,                                    Mod4Mask,         spawn,          {.v = dmenucmd } }, // don't work
{ Mod4Mask,                                    0,         spawn,          {.v = dmenucmd } }, // neither

Whenever I starts urxvt, there is a small gap bottom and left of screen it. How to get rid of it ?
image

try
{ Mod4Mask,                           NULL,            spawn,          { .v = dmenucmd }  }

the gap thing is common, look through this thread for solutions. or try the dwm patch thread.

ps this isn't a help thread. tongue

Last edited by mjheagle8 (2011-08-17 14:47:38)


Desktop/Laptop - DWM :: VM - screen
Registered Linux User Number 483137 :: Victory! :: GitHub

Offline

#367 2011-08-18 03:20:27

nXqd
Member
Registered: 2010-07-01
Posts: 173

Re: Show off your Dwm configuration!

It doesn't work, sorry for repost my help here.  I just create new thread but the mod has closed it neutral


When you live for a strong purpose, then hard work isn't an option. It's a necessity. - Steve Pavlina
dotFiles

Offline

#368 2011-08-18 06:22:09

bernarcher
Forum Fellow
From: Germany
Registered: 2009-02-17
Posts: 2,281

Re: Show off your Dwm configuration!

nXqd wrote:

It doesn't work, sorry for repost my help here.  I just create new thread but the mod has closed it neutral

I did close this new thread of yours because it appeared to be some simple literal cross post.

Of course you may open another thread, just noting the fact that this is meant for help, possibly linking back to this one if necessary.

Sorry for the misinterpretation.
-- bernarcher


To know or not to know ...
... the questions remain forever.

Offline

#369 2011-08-19 11:33:30

c0r73x
Member
From: Sweden
Registered: 2011-05-06
Posts: 14

Re: Show off your Dwm configuration!

Edit: Sorry I was searching for dwm threads and found this one, i will move my post to the correct thread.

Edit2: And here is a screenshot of my configuration instead smile
dwm20110820095721.th.png

Last edited by c0r73x (2011-08-20 08:08:43)

Offline

#370 2011-08-19 19:40:16

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: Show off your Dwm configuration!

Nice work c0r73x: but this is the screenshot thread - you want this in https://bbs.archlinux.org/viewtopic.php?id=92895


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#371 2011-08-23 13:41:01

Meyithi
Member
From: Wirral, UK
Registered: 2009-06-21
Posts: 550
Website

Re: Show off your Dwm configuration!

ss2_thumb.png

Haven't posted in a few months, lost the magenta.  5.9 Using statuscolor and uselessgap patches.

config.h - startdwm - .Xresources


The mind roams more freely in empty rooms.
dwm - colours - ncmpcpp - system
irc://irc.freenode.net:meyithi

Offline

#372 2011-08-23 14:51:46

Cloudef
Member
Registered: 2010-10-12
Posts: 636

Re: Show off your Dwm configuration!

Quite heavily modified dwm.. Looks like dwm on outside, but acts different inside.
tYTBxdQ

/*
 * config.h
 */

/* appearance */
static const char font[] = "erusfont 7";

#define NUMCOLORS 8

/*   border,   foreground ,background */
static const char colors[NUMCOLORS][ColLast][8] = {
   { "#010101", "#ffffff", "#121212" }, // 0 = normal
   { "#212121", "#010101", "#cc6600" }, // 1 = selected
   { "#ff6600", "#ffffff", "#ff6600" }, // 2 =
   { "#ffffff", "#00BFFF", "#dddddd" }, // 3 =
   { "#ffffff", "#0000ff", "#dddddd" }, // 4 =
   { "#ffffff", "#000000", "#ffff00" }, // 5 =
   { "#ffffff", "#cc3300", "#dddddd" }, // 6 =
   { "#ffffff", "#cccccc", "#313131" }, // 7 = Status area
};

static const unsigned int borderpx  = 1;        /* border pixel of windows */
static const Bool showbar           = True;     /* False means no bar */
static const Bool topbar            = True;     /* False means bottom bar */
static const Bool clicktofocus      = True;     /* Click to focus windows */
static const Bool autofocusmonitor  = True;     /* Auto focus monitors */

static const Bool systray_enable = True;
static const int systray_spacing = 2;
static const int status_height   = 0;

/* which monitor systray appears */
#define PRIMARY_MONITOR 0

/* display edges, similar to margins expect
 * everything gets affected */
static const Edge edges[] = {
   /* X   Y   W   H */
   {  0,  0,  0, 0 }, // 1
   {  0,  0,  0, 0 }, // 2
};

/* window area margins */
static const Edge margins[] = {
   /* X   Y   W   H */
   {  0,  0,  0, 10 }, // 1 NOTE: This adds the bottom bar cap
   {  0,  0,  0,  0 }, // 2 NOTE: Second monitor has no bar
};

/* tagging */
static const char *tags[] = { "東", "方", "P", "R", "O", "J", "E", "C", "T" };
Bool autohide             = False;

/* floating = floating window
 * widget   = window without border and statusbar
 * below    = always below
 * above    = always above
 * zombie   = do not take input
 * sticky   = stay on all tags
 */
/*           floating,widget,  below.   above,   zombie,  sticky */
#define NORMAL False,   False,   False,   False,   False,   False
#define FLOAT  True,    False,   False,   False,   False,   False
#define WIDGET True,    True,    False,   True,    False,   True
#define CONKY  True,    True,    True,    False,   True,    True
#define URXVTQ True,    False,   False,   True,    False,   True

static const Rule rules[] = {
    /* class      instance    title       tags mask     type           monitor */
   { "Gimp",     NULL,       NULL,       0,            FLOAT,         -1 },
   { "URxvt",    "URxvtq",   NULL,       0,            URXVTQ,         0 },
   { "Oblogout", NULL,       NULL,       0,            URXVTQ,         0 },
   { "MaCoPiX",  NULL,       NULL,       0,            WIDGET,         1 },
   { "Kupfer.py",NULL,       NULL,       0,            WIDGET,        -1 },
   { "dzen",     NULL,       NULL,       0,            CONKY,        -1 },
   { "Conky",    NULL,       NULL,       0,            CONKY,         1 },
   { "URxvt",    NULL,       "rTorrent", 1 << 4,       NORMAL,         1 },
   { "URxvt",    NULL,       "SnowNews", 1 << 3,       NORMAL,         1 },
   { "URxvt",    NULL,       "MSN",      1 << 2,       NORMAL,         1 },
   { "URxvt",    NULL,       "IRSSI",    1 << 1,       NORMAL,         1 },
   { "OperaNext", NULL,      NULL,       0,            NORMAL,        -1 },
};

/* layout(s) */
static const float mfact      = 0.55; /* factor of master area size [0.05..0.95] */
static const Bool resizehints = True; /* True means respect size hints in tiled resizals */

/* num of masters */
static const int nmaster = 2;

/* layouts */
static const Layout layouts[]  = {
    /* symbol     arrange function */
    { "[]=",      tile },
    { "[=]",      bstackhoriz },
    { "[#]" ,     grid },
    { "[||]" ,    bstack },
    { "><>",      NULL },
    { "[M]",      monocle },
    { .symbol = NULL, .arrange = NULL },
};

/* key definitions */
#define MODKEY Mod4Mask
#define ALTKEY Mod1Mask
#define TAGKEYS(KEY,TAG) \
	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \
	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \
	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \
	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} },

/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }

/* commands */
static const char *dmenucmd[] = { "dmenu_run" , "-p" , "Run:" , "-fn", font, "-nb", colors[0][ColBG], "-nf", colors[0][ColFG], "-sb", colors[1][ColBG], "-sf", colors[1][ColFG], NULL };
static const char *termcmd[]  = { "urxvt", NULL };
static const char *dvolminus[] = { "dvol", "-d", "1", NULL };
static const char *dvolplus[] = { "dvol", "-i", "1", NULL };
static const char *dvolmute[] = { "dvol", "-t", NULL };
static const char *kupfer[] = { "kupfer", NULL };
static const char *oblogout[] = { "oblogout", NULL };

static Key keys[] = {
                 /* modifier                     key        function        argument */
                { 0,                            0x1008ff11,spawn,          {.v = dvolminus } },
                { 0,                            0x1008ff13,spawn,          {.v = dvolplus  } },
                { 0,                            0x1008ff12,spawn,          {.v = dvolmute  } },
                { 0,                            0x1008ff30,spawn,          {.v = termcmd   } },
                { 0,                            XK_section,spawn,         SHCMD("$HOME/.config/dwm/urxvtq") },
	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
	{ MODKEY,                       XK_b,      togglebar,      {.i = -1} },
	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
	{ MODKEY,                       XK_Return, zoom,           {0} },
	{ MODKEY,                       XK_q,      killclient,     {0} },
                { ALTKEY,                       XK_s,      resizemouse,    {0} },
                { MODKEY,                       XK_s,      togglesticky,   {0} },
                { ALTKEY,                       XK_F2,     spawn,          {.v = kupfer} },
	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } },
	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
                { MODKEY,                       XK_KP_End,   nextlayout,     {0} },
                { MODKEY,                       XK_KP_Down,  prevlayout,     {0} },
 	{ MODKEY,                       XK_KP_Insert,cyclezoom,      {0} },
  	{ MODKEY,                       XK_KP_Delete,togglefloating,{0} },
	{ MODKEY,                       XK_KP_Home,  setmfact,     {.f = -0.05} },
	{ MODKEY,                       XK_KP_Up,    setmfact,     {.f = +0.05} },
 	{ MODKEY,                       XK_KP_Right, focusstack,   {.i = +1 } },
	{ MODKEY,                       XK_KP_5,     focusstack,   { .i = -1 } },
                { MODKEY,                       XK_F12,    togglelayout,   {.v = &layouts[5]} },
	TAGKEYS(                        XK_1,                      0)
	TAGKEYS(                        XK_2,                      1)
	TAGKEYS(                        XK_3,                      2)
	TAGKEYS(                        XK_4,                      3)
	TAGKEYS(                        XK_5,                      4)
	TAGKEYS(                        XK_6,                      5)
	TAGKEYS(                        XK_7,                      6)
	TAGKEYS(                        XK_8,                      7)
	TAGKEYS(                        XK_9,                      8)
	{ MODKEY,                       XK_Escape, spawn,          {.v = oblogout} },
                { MODKEY|ShiftMask,             XK_q,      restart,         {0} }
};

/* button definitions */
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
	/* click                event mask      button          function        argument */
	{ ClkLtSymbol,          0,              Button1,        nextlayout,      {0} },
	{ ClkLtSymbol,          0,              Button3,        prevlayout,      {0} },
	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
               { ClkWinTitle,          0,              Button1,        focusonclick,   {0} },
               { ClkWinTitle,          0,              Button3,        closeonclick,   {0} },
	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
	{ ClkClientWin,         ALTKEY,         Button1,        movemouse,      {0} },
	{ ClkClientWin,         ALTKEY,         Button2,        zoom,           {0} },
 	{ ClkClientWin,         MODKEY,         Button2,        zoom,           {0} },
	{ ClkTagBar,            0,              Button1,        view,           {0} },
	{ ClkTagBar,            0,              Button3,        toggleview,     {0} },
	{ ClkTagBar,            ALTKEY,         Button1,        tag,            {0} },
	{ ClkTagBar,            ALTKEY,         Button3,        toggletag,      {0} },
};

Github Page

Offline

#373 2011-09-01 08:54:08

xzakox
Member
Registered: 2011-09-01
Posts: 10

Re: Show off your Dwm configuration!

c0r73x wrote:

Edit: Sorry I was searching for dwm threads and found this one, i will move my post to the correct thread.

Edit2: And here is a screenshot of my configuration instead smile
http://img163.imageshack.us/img163/6715/dwm20110820095721.th.png


Can you show your dwm/.Xresources/vim/weechat configs?
Thx.

Offline

#374 2011-09-02 08:11:47

cirnOS
Member
Registered: 2010-03-01
Posts: 107

Re: Show off your Dwm configuration!

Cloudef wrote:

Quite heavily modified dwm.. Looks like dwm on outside, but acts different inside.
http://ompldr.org/tYTBxdQ

/*
 * config.h
 */

/* appearance */
static const char font[] = "erusfont 7";

#define NUMCOLORS 8

/*   border,   foreground ,background */
static const char colors[NUMCOLORS][ColLast][8] = {
   { "#010101", "#ffffff", "#121212" }, // 0 = normal
   { "#212121", "#010101", "#cc6600" }, // 1 = selected
   { "#ff6600", "#ffffff", "#ff6600" }, // 2 =
   { "#ffffff", "#00BFFF", "#dddddd" }, // 3 =
   { "#ffffff", "#0000ff", "#dddddd" }, // 4 =
   { "#ffffff", "#000000", "#ffff00" }, // 5 =
   { "#ffffff", "#cc3300", "#dddddd" }, // 6 =
   { "#ffffff", "#cccccc", "#313131" }, // 7 = Status area
};

static const unsigned int borderpx  = 1;        /* border pixel of windows */
static const Bool showbar           = True;     /* False means no bar */
static const Bool topbar            = True;     /* False means bottom bar */
static const Bool clicktofocus      = True;     /* Click to focus windows */
static const Bool autofocusmonitor  = True;     /* Auto focus monitors */

static const Bool systray_enable = True;
static const int systray_spacing = 2;
static const int status_height   = 0;

/* which monitor systray appears */
#define PRIMARY_MONITOR 0

/* display edges, similar to margins expect
 * everything gets affected */
static const Edge edges[] = {
   /* X   Y   W   H */
   {  0,  0,  0, 0 }, // 1
   {  0,  0,  0, 0 }, // 2
};

/* window area margins */
static const Edge margins[] = {
   /* X   Y   W   H */
   {  0,  0,  0, 10 }, // 1 NOTE: This adds the bottom bar cap
   {  0,  0,  0,  0 }, // 2 NOTE: Second monitor has no bar
};

/* tagging */
static const char *tags[] = { "東", "方", "P", "R", "O", "J", "E", "C", "T" };
Bool autohide             = False;

/* floating = floating window
 * widget   = window without border and statusbar
 * below    = always below
 * above    = always above
 * zombie   = do not take input
 * sticky   = stay on all tags
 */
/*           floating,widget,  below.   above,   zombie,  sticky */
#define NORMAL False,   False,   False,   False,   False,   False
#define FLOAT  True,    False,   False,   False,   False,   False
#define WIDGET True,    True,    False,   True,    False,   True
#define CONKY  True,    True,    True,    False,   True,    True
#define URXVTQ True,    False,   False,   True,    False,   True

static const Rule rules[] = {
    /* class      instance    title       tags mask     type           monitor */
   { "Gimp",     NULL,       NULL,       0,            FLOAT,         -1 },
   { "URxvt",    "URxvtq",   NULL,       0,            URXVTQ,         0 },
   { "Oblogout", NULL,       NULL,       0,            URXVTQ,         0 },
   { "MaCoPiX",  NULL,       NULL,       0,            WIDGET,         1 },
   { "Kupfer.py",NULL,       NULL,       0,            WIDGET,        -1 },
   { "dzen",     NULL,       NULL,       0,            CONKY,        -1 },
   { "Conky",    NULL,       NULL,       0,            CONKY,         1 },
   { "URxvt",    NULL,       "rTorrent", 1 << 4,       NORMAL,         1 },
   { "URxvt",    NULL,       "SnowNews", 1 << 3,       NORMAL,         1 },
   { "URxvt",    NULL,       "MSN",      1 << 2,       NORMAL,         1 },
   { "URxvt",    NULL,       "IRSSI",    1 << 1,       NORMAL,         1 },
   { "OperaNext", NULL,      NULL,       0,            NORMAL,        -1 },
};

/* layout(s) */
static const float mfact      = 0.55; /* factor of master area size [0.05..0.95] */
static const Bool resizehints = True; /* True means respect size hints in tiled resizals */

/* num of masters */
static const int nmaster = 2;

/* layouts */
static const Layout layouts[]  = {
    /* symbol     arrange function */
    { "[]=",      tile },
    { "[=]",      bstackhoriz },
    { "[#]" ,     grid },
    { "[||]" ,    bstack },
    { "><>",      NULL },
    { "[M]",      monocle },
    { .symbol = NULL, .arrange = NULL },
};

/* key definitions */
#define MODKEY Mod4Mask
#define ALTKEY Mod1Mask
#define TAGKEYS(KEY,TAG) \
	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \
	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \
	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \
	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} },

/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }

/* commands */
static const char *dmenucmd[] = { "dmenu_run" , "-p" , "Run:" , "-fn", font, "-nb", colors[0][ColBG], "-nf", colors[0][ColFG], "-sb", colors[1][ColBG], "-sf", colors[1][ColFG], NULL };
static const char *termcmd[]  = { "urxvt", NULL };
static const char *dvolminus[] = { "dvol", "-d", "1", NULL };
static const char *dvolplus[] = { "dvol", "-i", "1", NULL };
static const char *dvolmute[] = { "dvol", "-t", NULL };
static const char *kupfer[] = { "kupfer", NULL };
static const char *oblogout[] = { "oblogout", NULL };

static Key keys[] = {
                 /* modifier                     key        function        argument */
                { 0,                            0x1008ff11,spawn,          {.v = dvolminus } },
                { 0,                            0x1008ff13,spawn,          {.v = dvolplus  } },
                { 0,                            0x1008ff12,spawn,          {.v = dvolmute  } },
                { 0,                            0x1008ff30,spawn,          {.v = termcmd   } },
                { 0,                            XK_section,spawn,         SHCMD("$HOME/.config/dwm/urxvtq") },
	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
	{ MODKEY,                       XK_b,      togglebar,      {.i = -1} },
	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
	{ MODKEY,                       XK_Return, zoom,           {0} },
	{ MODKEY,                       XK_q,      killclient,     {0} },
                { ALTKEY,                       XK_s,      resizemouse,    {0} },
                { MODKEY,                       XK_s,      togglesticky,   {0} },
                { ALTKEY,                       XK_F2,     spawn,          {.v = kupfer} },
	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } },
	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
                { MODKEY,                       XK_KP_End,   nextlayout,     {0} },
                { MODKEY,                       XK_KP_Down,  prevlayout,     {0} },
 	{ MODKEY,                       XK_KP_Insert,cyclezoom,      {0} },
  	{ MODKEY,                       XK_KP_Delete,togglefloating,{0} },
	{ MODKEY,                       XK_KP_Home,  setmfact,     {.f = -0.05} },
	{ MODKEY,                       XK_KP_Up,    setmfact,     {.f = +0.05} },
 	{ MODKEY,                       XK_KP_Right, focusstack,   {.i = +1 } },
	{ MODKEY,                       XK_KP_5,     focusstack,   { .i = -1 } },
                { MODKEY,                       XK_F12,    togglelayout,   {.v = &layouts[5]} },
	TAGKEYS(                        XK_1,                      0)
	TAGKEYS(                        XK_2,                      1)
	TAGKEYS(                        XK_3,                      2)
	TAGKEYS(                        XK_4,                      3)
	TAGKEYS(                        XK_5,                      4)
	TAGKEYS(                        XK_6,                      5)
	TAGKEYS(                        XK_7,                      6)
	TAGKEYS(                        XK_8,                      7)
	TAGKEYS(                        XK_9,                      8)
	{ MODKEY,                       XK_Escape, spawn,          {.v = oblogout} },
                { MODKEY|ShiftMask,             XK_q,      restart,         {0} }
};

/* button definitions */
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
	/* click                event mask      button          function        argument */
	{ ClkLtSymbol,          0,              Button1,        nextlayout,      {0} },
	{ ClkLtSymbol,          0,              Button3,        prevlayout,      {0} },
	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
               { ClkWinTitle,          0,              Button1,        focusonclick,   {0} },
               { ClkWinTitle,          0,              Button3,        closeonclick,   {0} },
	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
	{ ClkClientWin,         ALTKEY,         Button1,        movemouse,      {0} },
	{ ClkClientWin,         ALTKEY,         Button2,        zoom,           {0} },
 	{ ClkClientWin,         MODKEY,         Button2,        zoom,           {0} },
	{ ClkTagBar,            0,              Button1,        view,           {0} },
	{ ClkTagBar,            0,              Button3,        toggleview,     {0} },
	{ ClkTagBar,            ALTKEY,         Button1,        tag,            {0} },
	{ ClkTagBar,            ALTKEY,         Button3,        toggletag,      {0} },
};

Github Page


May I ask how you applied the bottom stack? I'm not entirely new to dwm but never applied patches before. I saved the file as bstack.diff or whatever. Also where is this pango patch I keep hearing about?

Offline

#375 2011-09-02 09:12:15

c0r73x
Member
From: Sweden
Registered: 2011-05-06
Posts: 14

Re: Show off your Dwm configuration!

xzakox wrote:
c0r73x wrote:

Edit: Sorry I was searching for dwm threads and found this one, i will move my post to the correct thread.

Edit2: And here is a screenshot of my configuration instead smile
http://img163.imageshack.us/img163/6715/dwm20110820095721.th.png


Can you show your dwm/.Xresources/vim/weechat configs?
Thx.

I'm at work so I don't have my DWM configs here, I will post them later. Some of the stuff might not be the same as the screenshot since I'm changing stuff all the time tongue

Xdefaults

Xcursor.theme: Bluecurve

urxvt*saveLines:65535
!URxvt*borderLess:true
URxvt*internalBorder:2
URxvt*externalBorder:1
URxvt*transparent:true
URxvt*inheritPixmap:true
URxvt*tintColor:white
URxvt*shading:20
URxvt*foreground:White
URxvt*background:Black
!URxvt*depth: 32
!URxvt*background: rgba:0000/0000/0000/dddd
#URxvt*font: -*-proggyclean-*-*-*-*-*-*-*-*-*-*-*
#URxvt*boldFont: -*-proggyclean-*-*-*-*-*-*-*-*-*-*-*
URxvt*font: xft:Terminus:size=6:style:Regular
URxvt*fontBold: xft:Terminus:size=6:style:Regular
URxvt*scrollBar:false
URxvt*scrollstyle:rxvt
URxvt*perl-lib:        /usr/lib/urxvt/perl/
URxvt*perl-ext-common: default,matcher,searchable-scrollback,url-select,keyboard-select
URxvt*urlLauncher:     luakit
URxvt.matcher.button: 1
URxvt.matcher.pattern.1: \\bwww\\.[\\w-]\\.[\\w./?&@#-]*[\\w/-]
urxvt.cutchars: `()'*<>[]{|}"
URxvt.keysym.M-Escape: perl:keyboard-select:activate
urxvt.keysym.M-s: perl:keyboard-select:search
URxvt.keysym.M-u: perl:url-select:select_next

urxvt*termName: rxvt-256color

#include "/home/c0r73x/Dropbox/linux/config/xcolors/yettenet"

^ The color theme (Taking from the thread here on the arch forum so i take no credits for it)

*background: #060606
*foreground: #99916a
!black
*color0: #262729
*color8: #555544
!red
*color1: #ae2c00
*color9: #f55900
!green
*color2: #668800
*color10: #88aa22
!brown/yellow
*color3:  #B88B10
*color11: #FFC135
!blue
*color4:  #204a87
*color12: #3465a4
!magenta
*color5: #85608b
*color13: #ad7fa8
!cyan
*color6: #5485a4
*color14: #85A8C0
!white
*color7: #767779
*color15: #b6b8b9

vimrc (I'm using vimgdb, some stuff might not work without it)

set nocompatible
set autoindent
set smartindent
set tabstop=4
set shiftwidth=4
set showmatch
set nohls
set incsearch
syntax enable
set t_Co=256
colorscheme ir_black 
set number
set wrap nowrap
set mouse=a
set cul
helptags ~/.vim/doc

set backspace=indent,eol,start

autocmd BufReadPre SConstruct set filetype=python
autocmd BufReadPre SConscript set filetype=python

" GDB stuff
set previewheight=24
run macros/gdb_mappings.vim
run compiler/scons.vim
set asm=0
" set termencoding=macroman

" --- OmniCppComplete ---
" -- required --
set nocp " non vi compatible mode
filetype plugin on " enable plugins

" -- optional --
" auto close options when exiting insert mode
autocmd InsertLeave * if pumvisible() == 0|pclose|endif
set completeopt=menu,menuone

" -- configs --
let OmniCpp_MayCompleteDot = 1 " autocomplete with .
let OmniCpp_MayCompleteArrow = 1 " autocomplete with ->
let OmniCpp_MayCompleteScope = 1 " autocomplete with ::
let OmniCpp_SelectFirstItem = 2 " select first item (but don't insert)
let OmniCpp_NamespaceSearch = 2 " search namespaces in this and included files
let OmniCpp_ShowPrototypeInAbbr = 1 " show function prototype (i.e. parameters) in popup window

" -- ctags --
" map <ctrl>+F12 to generate ctags for current folder:
map <C-F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR><CR>

let g:clang_complete_copen = 1
let g:clang_complete_auto = 1

""nmap <C-w> :tabclose<CR>
""map <C-w> :tabclose<CR>
""imap <C-w> <Esc> :tabclose<CR>i

nmap <S-z> :tabprevious<CR>
nmap <S-x> :tabnext<CR>
map <S-z> :tabprevious<CR>
map <S-x> :tabnext<CR>
" imap <C-z> <Esc>:tabprevious<CR>i
" imap <C-x> <Esc>:tabnext<CR>i

nmap <C-t> :tabnew<CR>
map <C-t> :tabnew<CR>
imap <C-t> <Esc>:tabnew<CR>

nmap <F5> :Shell("scons")<CR>
imap <Esc><F5> :Shell("scons")<CR>
map <F5> :Shell("scons")<CR>

function! TabComplete()
	let col = col('.') - 2
	if !col
		return "\<tab>"
	else
		let line = getline('.')
		if line[col] !~ '\k' && line[col] !~ ' ' && line[col] != '$'
			return "\<tab>"
		else
			return "\<C-N>"
		endif
	endif
endfunction

inoremap <C-Tab> <C-R>=TabComplete()<CR>

function! s:ExecuteInShell(command, bang)
	let _ = a:bang != '' ? s:_ : a:command == '' ? '' : join(map(split(a:command), 'expand(v:val)'))

	if (_ != '')
		let s:_ = _
		let bufnr = bufnr('%')
		let winnr = bufwinnr('^' . _ . '$')
		silent! execute  winnr < 0 ? 'new ' . fnameescape(_) : winnr . 'wincmd w'
		setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
		silent! :%d
		let message = 'Execute ' . _ . '...'
		call append(0, message)
		echo message
		silent! 2d | resize 1 | redraw
		silent! execute 'silent! %!'. _
		silent! execute 'resize ' . line('$')
		silent! execute 'syntax on'
		silent! execute 'autocmd BufUnload <buffer> execute bufwinnr(' . bufnr . ') . ''wincmd w'''
		silent! execute 'autocmd BufEnter <buffer> execute ''resize '' .  line(''$'')'
		silent! execute 'nnoremap <silent> <buffer> <CR> :call <SID>ExecuteInShell(''' . _ . ''', '''')<CR>'
		silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . _ . ''', '''')<CR>'
		silent! execute 'nnoremap <silent> <buffer> <LocalLeader>g :execute bufwinnr(' . bufnr . ') . ''wincmd w''<CR>'
		nnoremap <silent> <buffer> <C-W>_ :execute 'resize ' . line('$')<CR>
		silent! syntax on
	endif
endfunction

command! -complete=shellcmd -nargs=* -bang Shell call s:ExecuteInShell(<q-args>, '<bang>')
cabbrev shell Shell

" add current directory's generated tags file to available tags
set tags+=./tags

" run plugin/autoclose.vim
autocmd FileType c,cpp source ~/.vim/syntax/opengl.vim

"  Initialize:
set nocp
if version >= 600
	filetype plugin indent on
endif

weechat.conf (I only changed some of the colors. And replaced the rightbar with http://www.weechat.org/files/scripts/buddylist.pl)

bar_more = lightmagenta
chat = default
chat_bg = default
chat_buffer = white
chat_channel = white
chat_delimiters = green
chat_highlight = yellow
chat_highlight_bg = magenta
chat_host = cyan
chat_nick = lightcyan
chat_nick_colors = "cyan,magenta,green,brown,lightblue,default,lightcyan,lightmagenta,lightgreen,blue"
chat_nick_other = cyan
chat_nick_self = white
chat_prefix_action = white
chat_prefix_buffer = brown
chat_prefix_error = yellow
chat_prefix_join = lightgreen
chat_prefix_more = lightmagenta
chat_prefix_network = magenta
chat_prefix_quit = lightred
chat_prefix_suffix = green
chat_read_marker = magenta
chat_read_marker_bg = default
chat_server = brown
chat_text_found = yellow
chat_text_found_bg = lightmagenta
chat_time = default
chat_time_delimiters = brown
chat_value = cyan
input_actions = lightgreen
input_text_not_found = red
nicklist_away = cyan
nicklist_group = green
nicklist_offline = blue
separator = blue
status_count_highlight = magenta
status_count_msg = brown
status_count_other = default
status_count_private = green
status_data_highlight = lightmagenta
status_data_msg = yellow
status_data_other = default
status_data_private = lightgreen
status_filter = green
status_more = yellow
status_name = white
status_name_ssl = lightgreen
status_number = yellow

config.h

/* See LICENSE file for copyright and license details. */

/* appearance */
#define BOTTOM_BAR_HEIGHT 12
#define TOP_BAR_HEIGHT 12

//static const char font[] 			= "-*-proggyclean-*-*-*-*-*-*-*-*-*-*-*";
static const char font[] 			= "Terminus 6";
static const char normbordercolor[] = "#000000";
static const char normbgcolor[]     = "#000000";
static const char normfgcolor[]     = "#ffffff";
static const char selbordercolor[]  = "#444444";
static const char selbgcolor[]      = "#444444";
static const char selfgcolor[]      = "#ffffff";
static const char* colors[NumColors][ColLast] = {
	// border          foreground   background
	{ normbordercolor, normfgcolor, normbgcolor },  // normal
	{ selbordercolor,  selfgcolor,  selbgcolor  },  // selected

	{ normbordercolor, selbgcolor,  selfgcolor  },  // warning
	{ normbordercolor, "#ffffff",   "#ff0000"   },  // error
	{ normbordercolor, "#7598b2",   normbgcolor },  // delim

    { normbordercolor, "#b10000",   normbgcolor },  // hot
	{ normbordercolor, "#b15c00",   normbgcolor },  // medium
	{ normbordercolor, "#6cb100",   normbgcolor },  // cool
};
static const unsigned int borderpx  = 1;        /* border pixel of windows */
static const unsigned int snap      = 32;       /* snap pixel */
static const Bool showbar           = True;     /* False means no bar */
static const Bool topbar            = True;     /* False means bottom bar */

/* tagging */
//static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };

static const Rule rules[] = {
	/* class      instance    title       tags mask     isfloating   monitor */
	{ "Gimp",     NULL,       NULL,       0,            True,        -1 },
	{ "Mplayer",  NULL,       NULL,       0,            True,        -1 },
	{ "mplayer",  NULL,       NULL,       0,            True,        -1 },
};

/* layout(s) */
static const int nmaster      = 1;    /* clients in the master area */
static const float mfact      = 0.55; /* factor of master area size [0.05..0.95] */
static const Bool resizehints = False; /* True means respect size hints in tiled resizals */
static const Bool useicons    = True;

#include "gaplessgrid.c"
static const Layout layouts[] = {
	/* icon                                         symbol     arrange function */
	{ "/home/c0r73x/.config/dwm/icons/grid.xbm",    "[G]",     gaplessgrid },    /* first entry is default */
	{ "/home/c0r73x/.config/dwm/icons/tile.xbm",    "[N]",     ntile },    /* first entry is default */
	{ "/home/c0r73x/.config/dwm/icons/float.xbm",   "[F]",     NULL },    /* no layout function means floating behavior */
	{ "/home/c0r73x/.config/dwm/icons/monocle.xbm", "[M]",     monocle },
	//{ "[T]",     tile },
};

static const Tag tags[] = {
    /* name       layout           mfact    nmaster */
    { "1",        &layouts[0],     -1,      -1 },
    { "2",        &layouts[0],     -1,      -1 },
    { "3",        &layouts[0],     -1,      -1 },
    { "4",        &layouts[0],     -1,      -1 },
    { "5",        &layouts[0],     -1,      -1 },
    { "6",        &layouts[0],     -1,      -1 },
    { "7",        &layouts[0],     -1,      -1 },
    { "8",        &layouts[0],     -1,      -1 },
    { "9",        &layouts[0],     -1,      -1 },
};

/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
	{ MODKEY,                       KEY,      comboview,      {.ui = 1 << TAG} }, \
	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \
	{ MODKEY|ShiftMask,             KEY,      combotag,       {.ui = 1 << TAG} }, \
	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} },

/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }

/* commands */
static const char *dmenucmd[] = { "dmenu_run", "-fn", "Terminus:size=6", "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
static const char *termcmd[]  = { "urxvtc", NULL };

#include <X11/XF86keysym.h>
#include "movestack.c"
static Key keys[] = {
	/* modifier                     key        function        argument */
	{ MODKEY,                       XK_r,      spawn,          {.v = dmenucmd } },
	{ MODKEY,             			XK_Return, spawn,          {.v = termcmd } },
	{ MODKEY,                       XK_b,      togglebar,      {0} },
	{ MODKEY,                       XK_j,      focusstack,     {.i = -1 } },
	{ MODKEY,                       XK_k,      focusstack,     {.i = +1 } },
    { MODKEY,                       XK_a,      incnmaster,     {.i = +1 } },
    { MODKEY,                       XK_z,      incnmaster,     {.i = -1 } },
	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
	{ MODKEY|ShiftMask,             XK_j,      movestack,      {.i = -1 } },
	{ MODKEY|ShiftMask,             XK_k,      movestack,      {.i = +1 } },
	{ MODKEY,                       XK_Return, zoom,           {0} },
	{ MODKEY,                       XK_Tab,    view,           {0} },
	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
	{ MODKEY,                       XK_g,      setlayout,      {.v = &layouts[0]} },
	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[1]} },
	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[2]} },
	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[3]} },
	{ MODKEY,                       XK_space,  setlayout,      {0} },
	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } },
	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
	{ MODKEY,                       XK_Left,   view_prev_tag,  {0} },
	{ MODKEY,                       XK_Right,  view_next_tag,  {0} },
	{ 0,                            XK_Print,                 spawn,        SHCMD("/home/c0r73x/bin/scrshot") },
	{ 0,         /*     Mute     */ XF86XK_AudioMute,         spawn,        SHCMD("amixer set Master toggle") },
	{ 0,         /* Brightness + */ XF86XK_MonBrightnessUp,   spawn,        SHCMD("xbacklight -inc 10") },
	{ 0,         /* Brightness - */ XF86XK_MonBrightnessDown, spawn,        SHCMD("xbacklight -dec 10") },
	{ 0,         /*   Volume -   */ XF86XK_AudioLowerVolume,  spawn,        SHCMD("amixer set Master 4%-") },
	{ 0,         /*   Volume +   */ XF86XK_AudioRaiseVolume,  spawn,        SHCMD("amixer set Master 4%+") },
	TAGKEYS(                        XK_1,                      0)
	TAGKEYS(                        XK_2,                      1)
	TAGKEYS(                        XK_3,                      2)
	TAGKEYS(                        XK_4,                      3)
	TAGKEYS(                        XK_5,                      4)
	TAGKEYS(                        XK_6,                      5)
	TAGKEYS(                        XK_7,                      6)
	TAGKEYS(                        XK_8,                      7)
	TAGKEYS(                        XK_9,                      8)
	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} },
};

/* button definitions */
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
#include "tilemovemouse.c"
static Button buttons[] = {
	/* click                event mask      button          function        argument */
	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} },
	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} },
	{ ClkWinTitle,          0,              Button1,        focusonclick,   {0} },
	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
	{ ClkClientWin,         MODKEY,         Button1,        tilemovemouse,      {0} },
	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} },
	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} },
/*	{ ClkTagBar,            0,              Button1,        view,           {0} },
	{ ClkTagBar,            0,              Button3,        toggleview,     {0} },
	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} },
	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },*/
};

dwm.c

/* See LICENSE file for copyright and license details.
 *
 * dynamic window manager is designed like any other X client as well. It is
 * driven through handling X events. In contrast to other X clients, a window
 * manager selects for SubstructureRedirectMask on the root window, to receive
 * events about window (dis-)appearance.  Only one X connection at a time is
 * allowed to select for this event mask.
 *
 * 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
 * set the override_redirect flag.  Clients are organized in a linked client
 * list on each monitor, the focus history is remembered through a stack list
 * on each monitor. Each client contains a bit array to indicate the tags of a
 * client.
 *
 * Keys and tagging rules are organized as arrays and defined in config.h.
 *
 * To understand everything else, start reading main().
 */
#include <errno.h>
#include <locale.h>
#include <stdarg.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
#include <X11/Xft/Xft.h>
#include <pango/pango.h>
#include <pango/pangoxft.h>
#include <pango/pango-font.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */

/* macros */
#define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
#define LENGTH(X)               (sizeof X / sizeof X[0])
#ifndef MAX
#define MAX(A, B)               ((A) > (B) ? (A) : (B))
#endif
#ifndef MIN
#define MIN(A, B)               ((A) < (B) ? (A) : (B))
#endif
#define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
#define TAGMASK                 ((1 << LENGTH(tags)) - 1)
#define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
#define drawtext(text, col, invert)         drawtext2(text, col, invert, True)

/* enums */
enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
enum { NetSupported, NetWMName, NetWMState,
       NetWMFullscreen, NetActiveWindow, NetLast };     /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
       ClkClientWin, ClkRootWin, ClkLast };             /* clicks */

typedef union {
	int i;
	unsigned int ui;
	float f;
	const void *v;
} Arg;

typedef struct {
	unsigned int click;
	unsigned int mask;
	unsigned int button;
	void (*func)(const Arg *arg);
	const Arg arg;
} Button;

typedef struct Monitor Monitor;
typedef struct Client Client;
struct Client {
	char name[256];
	float mina, maxa;
	int x, y, w, h;
	int oldx, oldy, oldw, oldh;
	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
	int bw, oldbw;
	unsigned int tags;
	Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, needresize;
	Client *next;
	Client *snext;
	Monitor *mon;
	Window win;
};

typedef struct {
	int x, y, w, h;
	unsigned long norm[ColLast];
	unsigned long sel[ColLast];
	Drawable drawable;
	GC gc;
	
	XftColor xftnorm[ColLast];
	XftColor xftsel[ColLast];
	XftDraw *xftdrawable;

	PangoContext *pgc;
	PangoLayout *plo;
	PangoFontDescription *pfd;

	struct {
		int ascent;
		int descent;
		int height;
	} font;
} DC; /* draw context */

typedef struct {
	unsigned int mod;
	KeySym keysym;
	void (*func)(const Arg *);
	const Arg arg;
} Key;

typedef struct {
	const char *icon;
	const char *symbol;
	void (*arrange)(Monitor *);
} Layout;

struct Monitor {
	char ltsymbol[16];
	int num;
	int by;               /* bar geometry */
	int mx, my, mw, mh;   /* screen size */
	int wx, wy, ww, wh;   /* window area  */
	unsigned int seltags;
	unsigned int sellt;
	unsigned int tagset[2];
	Bool showbar;
	Bool topbar;
	Client *clients;
	Client *sel;
	Client *stack;
	Monitor *next;
	Window barwin;
	const Layout *lt[2];
	int curtag;
	int prevtag;
	const Layout **lts;
	double *mfacts;
	int *nmasters;
	int titlebarbegin;
	int titlebarend;
};

typedef struct {
	const char *name;
	const Layout *layout;
	float mfact;
	int nmaster;
} Tag;

typedef struct {
	const char *class;
	const char *instance;
	const char *title;
	unsigned int tags;
	Bool isfloating;
	int monitor;
} Rule;

enum { ColNorm, ColSel, ColUrg, ColErr, ColDelim, ColHot, ColMed, ColCool, NumColors };

/* function declarations */
static void applyrules(Client *c);
static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
static void attach(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
static void cleanup(void);
static void cleanupmon(Monitor *mon);
static void clearurgent(Client *c);
static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static Monitor *createmon(void);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
static void die(const char *errstr, ...);
static Monitor *dirtomon(int dir);
static void drawbar(Monitor *m);
static void drawbars(void);
static void drawicon(const char *file, unsigned long col[ColLast]);
static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
static void drawtext2(const char *text, unsigned long col[ColLast], Bool invert, Bool pad);
static void drawvline(unsigned long col[ColLast]);
static void drawcoloredtext(Monitor *m, char *text);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
static void focusonclick(const Arg *arg);
static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
//static unsigned long getcolor(const char *colstr);
static Bool getrootptr(int *x, int *y);
static long getstate(Window w);
static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, Bool focused);
static void grabkeys(void);
static void initfont(const char *fontstr);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
static void pop(Client *);
static void propertynotify(XEvent *e);
static Monitor *ptrtomon(int x, int y);
static void quit(const Arg *arg);
static void resize(Client *c, int x, int y, int w, int h, Bool interact);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
static Bool sendevent(Client *c, Atom proto);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static int textnw(const char *text, unsigned int len);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, Bool setfocus);
static void unmanage(Client *c, Bool destroyed);
static void unmapnotify(XEvent *e);
static Bool updategeom(void);
static void updatebarpos(Monitor *m);
static void updatebars(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
static void updatetitle(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static void view_next_tag(const Arg *arg);
static void view_prev_tag(const Arg *arg);
static void view_adjacent_tag(int);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
static void incnmaster(const Arg *arg);
static void ntile(Monitor *m);
static void keyrelease(XEvent *e);
static void combotag(const Arg *arg);
static void comboview(const Arg *arg);

/* variables */
static const char broken[] = "broken";
static char stext[256];
static int screen;
static int sw, sh;           /* X display screen geometry width, height */
static int bh, blw = 0;      /* bar geometry */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
	[ButtonPress] = buttonpress,
	[ButtonRelease] = keyrelease,
	[ClientMessage] = clientmessage,
	[ConfigureRequest] = configurerequest,
	[ConfigureNotify] = configurenotify,
	[DestroyNotify] = destroynotify,
	[EnterNotify] = enternotify,
	[Expose] = expose,
	[FocusIn] = focusin,
	[KeyRelease] = keyrelease,
	[KeyPress] = keypress,
	[MappingNotify] = mappingnotify,
	[MapRequest] = maprequest,
	[PropertyNotify] = propertynotify,
	[UnmapNotify] = unmapnotify
};
static Atom wmatom[WMLast], netatom[NetLast];
static Bool running = True;
static Cursor cursor[CurLast];
static Display *dpy;
static DC dc;
static Monitor *mons = NULL, *selmon = NULL;
static Window root;
unsigned long barcolors[NumColors][ColLast];

/* configuration, allows nested code to access above variables */
#include "config.h"

/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };

/* function implementations */
static int combo = 0;

void
keyrelease(XEvent *e) {
	combo = 0;
}

void
combotag(const Arg  *arg) {
	if(selmon->sel && arg->ui & TAGMASK) {
		if (combo) {
			selmon->sel->tags |= arg->ui & TAGMASK;
		} else {
			combo             = 1;
			selmon->sel->tags = arg->ui & TAGMASK;
		}
		arrange(selmon);
	}
}

void
comboview(const Arg *arg) {
	unsigned newtags = arg->ui & TAGMASK;
	if (combo) {
		selmon->tagset[selmon->seltags] |= newtags;
	} else {
		selmon->seltags ^= 1; /* toggle tagset */
		combo = 1;
		if (newtags)
			selmon->tagset[selmon->seltags] = newtags;
	}
	arrange(selmon);
}

void
applyrules(Client *c) {
	const char *class, *instance;
	unsigned int i;
	const Rule *r;
	Monitor *m;
	XClassHint ch = { 0 };

	/* rule matching */
	c->isfloating = c->tags = 0;
	if(XGetClassHint(dpy, c->win, &ch)) {
		class = ch.res_class ? ch.res_class : broken;
		instance = ch.res_name ? ch.res_name : broken;
		for(i = 0; i < LENGTH(rules); i++) {
			r = &rules[i];
			if((!r->title || strstr(c->name, r->title))
			&& (!r->class || strstr(class, r->class))
			&& (!r->instance || strstr(instance, r->instance)))
			{
				c->isfloating = r->isfloating;
				c->tags |= r->tags;
				for(m = mons; m && m->num != r->monitor; m = m->next);
				if(m)
					c->mon = m;
			}
		}
		if(ch.res_class)
			XFree(ch.res_class);
		if(ch.res_name)
			XFree(ch.res_name);
	}
	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
}

Bool
applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact) {
	Bool baseismin;
	Monitor *m = c->mon;

	/* set minimum possible */
	*w = MAX(1, *w);
	*h = MAX(1, *h);
	if(interact) {
		if(*x > sw)
			*x = sw - WIDTH(c);
		if(*y > sh)
			*y = sh - HEIGHT(c);
		if(*x + *w + 2 * c->bw < 0)
			*x = 0;
		if(*y + *h + 2 * c->bw < 0)
			*y = 0;
	}
	else {
		if(*x > m->mx + m->mw)
			*x = m->mx + m->mw - WIDTH(c);
		if(*y > m->my + m->mh)
			*y = m->my + m->mh - HEIGHT(c);
		if(*x + *w + 2 * c->bw < m->mx)
			*x = m->mx;
		if(*y + *h + 2 * c->bw < m->my)
			*y = m->my;
	}
	if(*h < bh)
		*h = bh;
	if(*w < bh)
		*w = bh;
	if(resizehints || c->isfloating) {
		/* see last two sentences in ICCCM 4.1.2.3 */
		baseismin = c->basew == c->minw && c->baseh == c->minh;
		if(!baseismin) { /* temporarily remove base dimensions */
			*w -= c->basew;
			*h -= c->baseh;
		}
		/* adjust for aspect limits */
		if(c->mina > 0 && c->maxa > 0) {
			if(c->maxa < (float)*w / *h)
				*w = *h * c->maxa + 0.5;
			else if(c->mina < (float)*h / *w)
				*h = *w * c->mina + 0.5;
		}
		if(baseismin) { /* increment calculation requires this */
			*w -= c->basew;
			*h -= c->baseh;
		}
		/* adjust for increment value */
		if(c->incw)
			*w -= *w % c->incw;
		if(c->inch)
			*h -= *h % c->inch;
		/* restore base dimensions */
		*w = MAX(*w + c->basew, c->minw);
		*h = MAX(*h + c->baseh, c->minh);
		if(c->maxw)
			*w = MIN(*w, c->maxw);
		if(c->maxh)
			*h = MIN(*h, c->maxh);
	}
	return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
}

void
arrange(Monitor *m) {
	if(m)
		showhide(m->stack);
	else for(m = mons; m; m = m->next)
		showhide(m->stack);
	focus(NULL);
	if(m)
		arrangemon(m);
	else for(m = mons; m; m = m->next)
		arrangemon(m);
}

void
arrangemon(Monitor *m) {
	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
	if(m->lt[m->sellt]->arrange)
		m->lt[m->sellt]->arrange(m);
	restack(m);
}

void
attach(Client *c) {
	c->next = c->mon->clients;
	c->mon->clients = c;
}

void
attachstack(Client *c) {
	c->snext = c->mon->stack;
	c->mon->stack = c;
}

void
buttonpress(XEvent *e) {
	unsigned int i, x, click;
	Arg arg = {0};
	Client *c;
	Monitor *m;
	XButtonPressedEvent *ev = &e->xbutton;

	click = ClkRootWin;
	/* focus monitor if necessary */
	if((m = wintomon(ev->window)) && m != selmon) {
		unfocus(selmon->sel, True);
		selmon = m;
		focus(NULL);
	}
	if(ev->window == selmon->barwin) {
		i = x = 0;
		do {
			x += TEXTW(tags[i].name);
		} while(ev->x >= x && ++i < LENGTH(tags));
		if(i < LENGTH(tags)) {
			click = ClkTagBar;
			arg.ui = 1 << i;
		}
		else if(ev->x < x + blw)
			click = ClkLtSymbol;
		else if(ev->x > selmon->titlebarend)
			click = ClkStatusText;
		else {
			arg.ui = ev->x;
			click = ClkWinTitle;
		}
	}
	else if((c = wintoclient(ev->window))) {
		focus(c);
		click = ClkClientWin;
	}
	for(i = 0; i < LENGTH(buttons); i++)
		if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
		&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
			buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
}

void
checkotherwm(void) {
	xerrorxlib = XSetErrorHandler(xerrorstart);
	/* this causes an error if some other window manager is running */
	XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
	XSync(dpy, False);
	XSetErrorHandler(xerror);
	XSync(dpy, False);
}

void
cleanup(void) {
	Arg a = {.ui = ~0};
	Layout foo = { "", NULL };
	Monitor *m;

	view(&a);
	selmon->lt[selmon->sellt] = &foo;
	for(m = mons; m; m = m->next)
		while(m->stack)
			unmanage(m->stack, False);
	XUngrabKey(dpy, AnyKey, AnyModifier, root);
	XFreePixmap(dpy, dc.drawable);
	XFreeGC(dpy, dc.gc);
	XFreeCursor(dpy, cursor[CurNormal]);
	XFreeCursor(dpy, cursor[CurResize]);
	XFreeCursor(dpy, cursor[CurMove]);
	while(mons)
		cleanupmon(mons);
	XSync(dpy, False);
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
}

void
cleanupmon(Monitor *mon) {
	Monitor *m;

	if(mon == mons)
		mons = mons->next;
	else {
		for(m = mons; m && m->next != mon; m = m->next);
		m->next = mon->next;
	}
	XUnmapWindow(dpy, mon->barwin);
	XDestroyWindow(dpy, mon->barwin);
	free(mon->mfacts);
	free(mon->nmasters);
	free(mon->lts);
	free(mon);
}

void
clearurgent(Client *c) {
	XWMHints *wmh;

	c->isurgent = False;
	if(!(wmh = XGetWMHints(dpy, c->win)))
		return;
	wmh->flags &= ~XUrgencyHint;
	XSetWMHints(dpy, c->win, wmh);
	XFree(wmh);
}

void
clientmessage(XEvent *e) {
	XClientMessageEvent *cme = &e->xclient;
	Client *c = wintoclient(cme->window);

	if(!c)
		return;
	if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) {
		if(cme->data.l[0] && !c->isfullscreen) {
			XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
			                PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
			c->isfullscreen = True;
			c->oldstate = c->isfloating;
			c->oldbw = c->bw;
			c->bw = 0;
			c->isfloating = True;
			resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
			XRaiseWindow(dpy, c->win);
		}
		else {
			XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
			                PropModeReplace, (unsigned char*)0, 0);
			c->isfullscreen = False;
			c->isfloating = c->oldstate;
			c->bw = c->oldbw;
			c->x = c->oldx;
			c->y = c->oldy;
			c->w = c->oldw;
			c->h = c->oldh;
			resizeclient(c, c->x, c->y, c->w, c->h);
			arrange(c->mon);
		}
	}
	else if(cme->message_type == netatom[NetActiveWindow]) {
		if(!ISVISIBLE(c)) {
			c->mon->seltags ^= 1;
			c->mon->tagset[c->mon->seltags] = c->tags;
		}
		pop(c);
	}
}

void
configure(Client *c) {
	XConfigureEvent ce;

	ce.type = ConfigureNotify;
	ce.display = dpy;
	ce.event = c->win;
	ce.window = c->win;
	ce.x = c->x;
	ce.y = c->y;
	ce.width = c->w;
	ce.height = c->h;
	ce.border_width = c->bw;
	ce.above = None;
	ce.override_redirect = False;
	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
}

void
configurenotify(XEvent *e) {
	Monitor *m;
	XConfigureEvent *ev = &e->xconfigure;
	Bool dirty;

	if(ev->window == root) {
		dirty = (sw != ev->width);
		sw = ev->width;
		sh = ev->height;
		if(updategeom() || dirty) {
			if(dc.drawable != 0)
				XFreePixmap(dpy, dc.drawable);
			dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
			updatebars();
			for(m = mons; m; m = m->next)
				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
			arrange(NULL);
		}
	}
}

void
configurerequest(XEvent *e) {
	Client *c;
	Monitor *m;
	XConfigureRequestEvent *ev = &e->xconfigurerequest;
	XWindowChanges wc;

	if((c = wintoclient(ev->window))) {
		if(ev->value_mask & CWBorderWidth)
			c->bw = ev->border_width;
		else if(c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
			m = c->mon;
			if(ev->value_mask & CWX)
				c->x = m->mx + ev->x;
			if(ev->value_mask & CWY)
				c->y = m->my + ev->y;
			if(ev->value_mask & CWWidth)
				c->w = ev->width;
			if(ev->value_mask & CWHeight)
				c->h = ev->height;
			if((c->x + c->w) > m->mx + m->mw && c->isfloating)
				c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */
			if((c->y + c->h) > m->my + m->mh && c->isfloating)
				c->y = m->my + (m->mh / 2 - c->h / 2); /* center in y direction */
			if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
				configure(c);
			if(ISVISIBLE(c))
				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
			else
				c->needresize = True;
		}
		else
			configure(c);
	}
	else {
		wc.x = ev->x;
		wc.y = ev->y;
		wc.width = ev->width;
		wc.height = ev->height;
		wc.border_width = ev->border_width;
		wc.sibling = ev->above;
		wc.stack_mode = ev->detail;
		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
	}
	XSync(dpy, False);
}

Monitor *
createmon(void) {
	Monitor *m;
	int i, numtags = LENGTH(tags) +1;

	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
	if(!(m->mfacts = calloc(sizeof(double), numtags)))
		die("fatal: could not malloc() %u bytes\n", sizeof(double)*numtags);
	if(!(m->nmasters = calloc(sizeof(int), numtags)))
		die("fatal: could not malloc() %u bytes\n", sizeof(int)*numtags);
	if(!(m->lts = calloc(sizeof(Layout*), numtags)))
		die("fatal: could not malloc() %u bytes\n", sizeof(Layout*)*numtags);
	m->tagset[0] = m->tagset[1] = 1;
	m->mfacts[0] = mfact;
	m->nmasters[0] = nmaster;
	m->showbar = showbar;
	m->topbar = topbar;
	m->curtag = m->prevtag = 1;
	for(i = 1; i < numtags; i++) {
		m->mfacts[i]   = tags[i - 1].mfact < 0 ? mfact : tags[i - 1].mfact;
		m->nmasters[i] = tags[i - 1].nmaster < 0 ? nmaster : tags[i - 1].nmaster;
		m->lts[i]      = tags[i - 1].layout;
	}
	m->lt[0] = m->lts[m->curtag];
	m->lt[1] = &layouts[1 % LENGTH(layouts)];
	strncpy(m->ltsymbol, m->lt[0]->symbol, sizeof m->ltsymbol);
	return m;
}

void
destroynotify(XEvent *e) {
	Client *c;
	XDestroyWindowEvent *ev = &e->xdestroywindow;

	if((c = wintoclient(ev->window)))
		unmanage(c, True);
}

void
detach(Client *c) {
	Client **tc;

	for(tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
	*tc = c->next;
}

void
detachstack(Client *c) {
	Client **tc, *t;

	for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
	*tc = c->snext;

	if(c == c->mon->sel) {
		for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
		c->mon->sel = t;
	}
}

void
die(const char *errstr, ...) {
	va_list ap;

	va_start(ap, errstr);
	vfprintf(stderr, errstr, ap);
	va_end(ap);
	exit(EXIT_FAILURE);
}

Monitor *
dirtomon(int dir) {
	Monitor *m = NULL;

	if(dir > 0) {
		if(!(m = selmon->next))
			m = mons;
	}
	else {
		if(selmon == mons)
			for(m = mons; m->next; m = m->next);
		else
			for(m = mons; m->next != selmon; m = m->next);
	}
	return m;
}

void
drawbar(Monitor *m) {
	int x, a= 0, s= 0, mw = 0, ow;
	char posbuf[10];
	unsigned int i, n = 0, occ = 0, urg = 0;
	unsigned long *col;
	Client *c;

	for(c = m->clients; c; c = c->next) {
		if(ISVISIBLE(c))
        	n++;
		occ |= c->tags;
		if(c->isurgent)
			urg |= c->tags;
	}

	dc.x = 0;
	for(i = 0; i < LENGTH(tags); i++) {
		if (m->tagset[m->seltags] & 1 << i || occ & 1 << i) {
			dc.w = TEXTW(tags[i].name);
			col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm;
			drawtext(tags[i].name, col, urg & 1 << i);
			drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
				   occ & 1 << i, urg & 1 << i, col);
			dc.x += dc.w;
		}
	}
	blw = TEXTW(m->ltsymbol);
	if(useicons) {
		dc.w = dc.h;
		drawicon(m->lt[m->sellt]->icon, dc.norm);
	}
	else {
		dc.w = blw;
		drawtext(m->ltsymbol, dc.norm, False);
	}
	dc.x += dc.w;
	x = dc.x;
	if(m == selmon) { /* status is only drawn on selected monitor */
		if(m->lt[m->sellt]->arrange == monocle){
			  dc.x= x;
			  for(c= nexttiled(m->clients), a= 0, s= 0; c; c= nexttiled(c->next), a++)
				if(c == m->stack)
					s = a;
			  if(!s && a)
				s = a;
			  snprintf(posbuf, LENGTH(posbuf), "[%d/%d]", s, a);
			  dc.w= TEXTW(posbuf);
			  drawtext(posbuf, dc.norm, False);
			  x= dc.x + dc.w;
		}

		dc.w=0;
		char *buf = stext, *ptr = buf;
		while( *ptr ) {
			for( i = 0; *ptr < 0 || *ptr > NumColors; i++, ptr++);
			dc.w += textnw(buf,i);
			buf=++ptr;
		}
		dc.w+=dc.font.height;
		dc.x = m->ww - dc.w;
		if(dc.x < x) {
			dc.x = x;
			dc.w = m->ww - x;
		}
		m->titlebarend=dc.x;
		drawcoloredtext(m, stext);
	}
	else {
		dc.x = m->ww;
		m->titlebarbegin=dc.x;
	}

	for(c = m->clients; c && !ISVISIBLE(c); c = c->next);

	dc.w = dc.x - x;
	dc.x = x;

	if(n > 0) {
		mw = dc.w / n;
		x = dc.x;
	}
	m->titlebarbegin=dc.x;
	while(dc.w > bh) {
		if(c) {
			ow = dc.w;

			if(dc.w > mw) dc.w = mw;
			if(m->sel == c)
				col = dc.sel;
			else
				col = dc.norm;

			drawtext(c->name, col, False);
			drawsquare(c->isfixed, c->isfloating, False, col);

			dc.x += dc.w;
			dc.w = ow - dc.w;
			for(c = c->next; c && !ISVISIBLE(c); c = c->next);
		} else {
 			drawtext(NULL, dc.norm, False);
			break;
		}
	}

	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
	XSync(dpy, False);
}

void
drawbars(void) {
	Monitor *m;

	for(m = mons; m; m = m->next)
		drawbar(m);
}

void
drawicon(const char *file, unsigned long col[ColLast]) {
    Pixmap icon;
    int px, py;
    unsigned int pw, ph;
    icon = XCreatePixmap(dpy, dc.drawable, dc.h, dc.h, 1);
    XReadBitmapFile(dpy, dc.drawable, file, &pw, &ph, &icon, &px, &py);
    XSetForeground(dpy, dc.gc, col[ColBG]);
    XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, 0, dc.h, dc.h);
    XSetForeground(dpy, dc.gc, col[ColFG]);
    XSetBackground(dpy, dc.gc, col[ColBG]);
    XCopyPlane(dpy, icon, dc.drawable, dc.gc, px, py, pw, ph, dc.x, dc.h/2-ph/2+py, 1);
}

void
drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
	int x;

	XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
	x = (dc.font.ascent + dc.font.descent + 2) / 4;
	if(filled)
		XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1);
	else if(empty)
		XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x);
}

void
drawtext2(const char *text, unsigned long col[ColLast], Bool invert, Bool pad) {
	char buf[256];
	int i, x, y, h, len, olen;

	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
	XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
	if(!text)
		return;
	olen = strlen(text);
	h = dc.font.ascent + dc.font.descent;
	y = dc.y; // + (dc.h / 2) - (h / 2) + dc.font.ascent;
	x = dc.x + ((pad ? (dc.font.ascent + dc.font.descent) : 0) / 2);
	/* shorten text if necessary */
	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
	if(!len)
		return;
	memcpy(buf, text, len);
	if(len < olen)
		for(i = len; i && i > len - 3; buf[--i] = '.');
	pango_layout_set_text(dc.plo, text, len);
	pango_xft_render_layout(dc.xftdrawable, (col==dc.norm?dc.xftnorm:dc.xftsel)+(invert?ColBG:ColFG), dc.plo, x * PANGO_SCALE, y * PANGO_SCALE);
}

void
drawvline(unsigned long col[ColLast]) {
	XGCValues gcv;

	gcv.foreground = col[ColFG];
	XChangeGC(dpy, dc.gc, GCForeground, &gcv);
	XDrawLine(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.x, dc.y + (dc.font.ascent + dc.font.descent + 2));
}

void
drawcoloredtext(Monitor *m, char *text) {
	Bool first=True;
	char *buf = text, *ptr = buf, c = 1;
	unsigned long *col = barcolors[0];
	int i, ox = dc.x;

	while( *ptr ) {
		for( i = 0; *ptr < 0 || *ptr > NumColors; i++, ptr++);
		if( !*ptr ) break;
		c=*ptr;
		*ptr=0;
		if( i ) {
			dc.w = m->ww - dc.x;
			drawtext2(buf, col, False, first);
			dc.x += textnw(buf, i);// + textnw(&c,1);
			if( first ) dc.x += ( dc.font.ascent + dc.font.descent ) / 2;
			first = False;
		} else if( first ) {
			ox = dc.x += textnw(&c,1);
		}
		*ptr = c;
		col = barcolors[ c-1 ];
		buf = ++ptr;
	}
	//if( !first ) dc.x-=(dc.font.ascent+dc.font.descent)/2;
	drawtext2(buf, col, False, False);
	dc.x = ox;
}

void
enternotify(XEvent *e) {
	Client *c;
	Monitor *m;
	XCrossingEvent *ev = &e->xcrossing;

	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
		return;
	c = wintoclient(ev->window);
	m = c ? c->mon : wintomon(ev->window);
	if(m != selmon) {
		unfocus(selmon->sel, True);
		selmon = m;
	}
	else if(!c || c == selmon->sel)
		return;
	focus(c);
}

void
expose(XEvent *e) {
	Monitor *m;
	XExposeEvent *ev = &e->xexpose;

	if(ev->count == 0 && (m = wintomon(ev->window)))
		drawbar(m);
}

void
focus(Client *c) {
	if(!c || !ISVISIBLE(c))
		for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
	/* was if(selmon->sel) */
	if(selmon->sel && selmon->sel != c)
		unfocus(selmon->sel, False);
	if(c) {
		if(c->mon != selmon)
			selmon = c->mon;
		if(c->isurgent)
			clearurgent(c);
		detachstack(c);
		attachstack(c);
		grabbuttons(c, True);
		XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
		setfocus(c);
	}
	else
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
	selmon->sel = c;
	drawbars();
}

void
focusonclick(const Arg *arg) {
	int x, w, mw = 0, n = 0;
	Monitor *m = selmon;
	Client *c, *firstvis;

	for(c = m->clients; c && !ISVISIBLE(c); c = c->next);
	firstvis = c;
	
	for(c = m->clients; c; c = c->next)
		if (ISVISIBLE(c))
		    n++;
	
	if(n > 0) {
		mw = (m->titlebarend - m->titlebarbegin) / n;
		c = firstvis;
	}

	x=m->titlebarbegin;

	c = firstvis;
        while(x < m->titlebarend) {
		if(c) {
			w=mw; //MIN(TEXTW(c->name), mw);
			if (x < arg->i && x+w > arg->i) {
				focus(c);
				restack(selmon);
				break;
			} else
				x+=w;

			for(c = c->next; c && !ISVISIBLE(c); c = c->next);
		} else {
			break;
		}
        }
}

void
focusin(XEvent *e) { /* there are some broken focus acquiring clients */
	XFocusChangeEvent *ev = &e->xfocus;

	if(selmon->sel && ev->window != selmon->sel->win)
		setfocus(selmon->sel);
}

void
focusmon(const Arg *arg) {
	Monitor *m;

	if(!mons->next)
		return;
	if((m = dirtomon(arg->i)) == selmon)
		return;
	unfocus(selmon->sel, True);
	selmon = m;
	focus(NULL);
}

void
focusstack(const Arg *arg) {
	Client *c = NULL, *i;

	if(!selmon->sel)
		return;
	if(arg->i > 0) {
		for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
		if(!c)
			for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
	}
	else {
		for(i = selmon->clients; i != selmon->sel; i = i->next)
			if(ISVISIBLE(i))
				c = i;
		if(!c)
			for(; i; i = i->next)
				if(ISVISIBLE(i))
					c = i;
	}
	if(c) {
		focus(c);
		restack(selmon);
	}
}

unsigned long
getcolor(const char *colstr, XftColor *color) {
	Colormap cmap = DefaultColormap(dpy, screen);
	Visual *vis = DefaultVisual(dpy, screen);

	if(!XftColorAllocName(dpy, vis, cmap, colstr, color))
		die("error, cannot allocate color '%s'\n", colstr);
	return color->pixel;
}

Bool
getrootptr(int *x, int *y) {
	int di;
	unsigned int dui;
	Window dummy;

	return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
}

long
getstate(Window w) {
	int format;
	long result = -1;
	unsigned char *p = NULL;
	unsigned long n, extra;
	Atom real;

	if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
	                      &real, &format, &n, &extra, (unsigned char **)&p) != Success)
		return -1;
	if(n != 0)
		result = *p;
	XFree(p);
	return result;
}

Bool
gettextprop(Window w, Atom atom, char *text, unsigned int size) {
	char **list = NULL;
	int n;
	XTextProperty name;

	if(!text || size == 0)
		return False;
	text[0] = '\0';
	XGetTextProperty(dpy, w, &name, atom);
	if(!name.nitems)
		return False;
	if(name.encoding == XA_STRING)
		strncpy(text, (char *)name.value, size - 1);
	else {
		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
			strncpy(text, *list, size - 1);
			XFreeStringList(list);
		}
	}
	text[size - 1] = '\0';
	XFree(name.value);
	return True;
}

void
grabbuttons(Client *c, Bool focused) {
	updatenumlockmask();
	{
		unsigned int i, j;
		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
		XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
		if(focused) {
			for(i = 0; i < LENGTH(buttons); i++)
				if(buttons[i].click == ClkClientWin)
					for(j = 0; j < LENGTH(modifiers); j++)
						XGrabButton(dpy, buttons[i].button,
						            buttons[i].mask | modifiers[j],
						            c->win, False, BUTTONMASK,
						            GrabModeAsync, GrabModeSync, None, None);
		}
		else
			XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
			            BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
	}
}

void
grabkeys(void) {
	updatenumlockmask();
	{
		unsigned int i, j;
		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
		KeyCode code;

		XUngrabKey(dpy, AnyKey, AnyModifier, root);
		for(i = 0; i < LENGTH(keys); i++) {
			if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
				for(j = 0; j < LENGTH(modifiers); j++)
					XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
						 True, GrabModeAsync, GrabModeAsync);
		}
	}
}

void
initfont(const char *fontstr) {
	PangoFontMetrics *metrics;

	dc.pgc          = pango_xft_get_context(dpy, screen);
	dc.pfd          = pango_font_description_from_string(fontstr);

	metrics         = pango_context_get_metrics(dc.pgc, dc.pfd, pango_language_from_string(setlocale(LC_CTYPE, "")));

	dc.font.ascent  = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
	dc.font.descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;

	pango_font_metrics_unref(metrics);

	dc.plo = pango_layout_new(dc.pgc);
	pango_layout_set_font_description(dc.plo, dc.pfd);
	dc.font.height = dc.font.ascent + dc.font.descent;
}

#ifdef XINERAMA
static Bool
isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) {
	while(n--)
		if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
		&& unique[n].width == info->width && unique[n].height == info->height)
			return False;
	return True;
}
#endif /* XINERAMA */

void
keypress(XEvent *e) {
	unsigned int i;
	KeySym keysym;
	XKeyEvent *ev;

	ev = &e->xkey;
	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
	for(i = 0; i < LENGTH(keys); i++)
		if(keysym == keys[i].keysym
		&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
		&& keys[i].func)
			keys[i].func(&(keys[i].arg));
}

void
killclient(const Arg *arg) {
	if(!selmon->sel)
		return;
	if(!sendevent(selmon->sel, wmatom[WMDelete])) {
		XGrabServer(dpy);
		XSetErrorHandler(xerrordummy);
		XSetCloseDownMode(dpy, DestroyAll);
		XKillClient(dpy, selmon->sel->win);
		XSync(dpy, False);
		XSetErrorHandler(xerror);
		XUngrabServer(dpy);
	}
}

void
manage(Window w, XWindowAttributes *wa) {
	Client *c, *t = NULL;
	Window trans = None;
	XWindowChanges wc;

	if(!(c = calloc(1, sizeof(Client))))
		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
	c->win = w;
	updatetitle(c);
	if(XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
		c->mon = t->mon;
		c->tags = t->tags;
	}
	else {
		c->mon = selmon;
		applyrules(c);
	}
	/* geometry */
	c->x = c->oldx = wa->x;
	c->y = c->oldy = wa->y;
	c->w = c->oldw = wa->width;
	c->h = c->oldh = wa->height;
	c->oldbw = wa->border_width;
	if(c->w == c->mon->mw && c->h == c->mon->mh) {
		c->isfloating = True;
		c->x = c->mon->mx;
		c->y = c->mon->my;
		c->bw = 0;
	}
	else {
		if(c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
			c->x = c->mon->mx + c->mon->mw - WIDTH(c);
		if(c->y + HEIGHT(c) > c->mon->my + c->mon->mh)
			c->y = c->mon->my + c->mon->mh - HEIGHT(c);
		c->x = MAX(c->x, c->mon->mx);
		/* only fix client y-offset, if the client center might cover the bar */
		c->y = MAX(c->y, ((c->mon->by == 0) && (c->x + (c->w / 2) >= c->mon->wx)
		           && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
		c->bw = borderpx;
	}
	//wc.border_width = c->bw;
	wc.border_width = (c->mon->lt[c->mon->sellt]->arrange == monocle && !c->isfloating) ? 0 : c->bw;
	if(c->mon->lt[c->mon->sellt]->arrange == monocle && !c->isfloating) {
		c->w = wc.width += borderpx * 2;
		c->h = wc.height += borderpx * 2;
	}
	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
	XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
	configure(c); /* propagates border_width, if size doesn't change */
	updatesizehints(c);
	updatewmhints(c);
	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
	grabbuttons(c, False);
	if(!c->isfloating)
		c->isfloating = c->oldstate = trans != None || c->isfixed;
	if(c->isfloating)
		XRaiseWindow(dpy, c->win);
	attach(c);
	attachstack(c);
	XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
	XMapWindow(dpy, c->win);
	setclientstate(c, NormalState);
	arrange(c->mon);
}

void
mappingnotify(XEvent *e) {
	XMappingEvent *ev = &e->xmapping;

	XRefreshKeyboardMapping(ev);
	if(ev->request == MappingKeyboard)
		grabkeys();
}

void
maprequest(XEvent *e) {
	static XWindowAttributes wa;
	XMapRequestEvent *ev = &e->xmaprequest;

	if(!XGetWindowAttributes(dpy, ev->window, &wa))
		return;
	if(wa.override_redirect)
		return;
	if(!wintoclient(ev->window))
		manage(ev->window, &wa);
}

void
monocle(Monitor *m) {
	unsigned int n = 0;
	Client *c;

	for(c = m->clients; c; c = c->next)
		if(ISVISIBLE(c))
			n++;
	if(n > 0) /* override layout symbol */
		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
	for(c = nexttiled(m->clients); c; c = nexttiled(c->next))
		resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False);
}

void
movemouse(const Arg *arg) {
	int x, y, ocx, ocy, nx, ny;
	Client *c;
	Monitor *m;
	XEvent ev;

	if(!(c = selmon->sel))
		return;
	restack(selmon);
	ocx = c->x;
	ocy = c->y;
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
	None, cursor[CurMove], CurrentTime) != GrabSuccess)
		return;
	if(!getrootptr(&x, &y))
		return;
	do {
		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
		switch(ev.type) {
		case ConfigureRequest:
		case Expose:
		case MapRequest:
			handler[ev.type](&ev);
			break;
		case MotionNotify:
			nx = ocx + (ev.xmotion.x - x);
			ny = ocy + (ev.xmotion.y - y);
			if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww
			&& ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
				if(abs(selmon->wx - nx) < snap)
					nx = selmon->wx;
				else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
					nx = selmon->wx + selmon->ww - WIDTH(c);
				if(abs(selmon->wy - ny) < snap)
					ny = selmon->wy;
				else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
					ny = selmon->wy + selmon->wh - HEIGHT(c);
				if(!c->isfloating && selmon->lt[selmon->sellt]->arrange
				&& (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
					togglefloating(NULL);
			}
			if(!selmon->lt[selmon->sellt]->arrange || c->isfloating)
				resize(c, nx, ny, c->w, c->h, True);
			break;
		}
	} while(ev.type != ButtonRelease);
	XUngrabPointer(dpy, CurrentTime);
	if((m = ptrtomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
		sendmon(c, m);
		selmon = m;
		focus(NULL);
	}
}

Client *
nexttiled(Client *c) {
	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
	return c;
}

void
pop(Client *c) {
	detach(c);
	attach(c);
	focus(c);
	arrange(c->mon);
}

void
propertynotify(XEvent *e) {
	Client *c;
	Window trans;
	XPropertyEvent *ev = &e->xproperty;

	if((ev->window == root) && (ev->atom == XA_WM_NAME))
		updatestatus();
	else if(ev->state == PropertyDelete)
		return; /* ignore */
	else if((c = wintoclient(ev->window))) {
		switch(ev->atom) {
		default: break;
		case XA_WM_TRANSIENT_FOR:
			if(!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
			   (c->isfloating = (wintoclient(trans)) != NULL))
				arrange(c->mon);
			break;
		case XA_WM_NORMAL_HINTS:
			updatesizehints(c);
			break;
		case XA_WM_HINTS:
			updatewmhints(c);
			drawbars();
			break;
		}
		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
			updatetitle(c);
			if(c == c->mon->sel)
				drawbar(c->mon);
		}
	}
}

Monitor *
ptrtomon(int x, int y) {
	Monitor *m;

	for(m = mons; m; m = m->next)
		if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh))
			return m;
	return selmon;
}
void
quit(const Arg *arg) {
	running = False;
}

void
resize(Client *c, int x, int y, int w, int h, Bool interact) {
	if(applysizehints(c, &x, &y, &w, &h, interact))
		resizeclient(c, x, y, w, h);
}

void
resizeclient(Client *c, int x, int y, int w, int h) {
	XWindowChanges wc;

	c->oldx = c->x; c->x = wc.x = x;
	c->oldy = c->y; c->y = wc.y = y;
	c->oldw = c->w; c->w = wc.width = w;
	c->oldh = c->h; c->h = wc.height = h;
	wc.border_width = c->bw;
	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
	configure(c);
	XSync(dpy, False);
}

void
resizemouse(const Arg *arg) {
	int ocx, ocy;
	int nw, nh;
	Client *c;
	Monitor *m;
	XEvent ev;

	if(!(c = selmon->sel))
		return;
	restack(selmon);
	ocx = c->x;
	ocy = c->y;
	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
	                None, cursor[CurResize], CurrentTime) != GrabSuccess)
		return;
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
	do {
		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
		switch(ev.type) {
		case ConfigureRequest:
		case Expose:
		case MapRequest:
			handler[ev.type](&ev);
			break;
		case MotionNotify:
			nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
			nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
			if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
			&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
			{
				if(!c->isfloating && selmon->lt[selmon->sellt]->arrange
				&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
					togglefloating(NULL);
			}
			if(!selmon->lt[selmon->sellt]->arrange || c->isfloating)
				resize(c, c->x, c->y, nw, nh, True);
			break;
		}
	} while(ev.type != 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));
	if((m = ptrtomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) {
		sendmon(c, m);
		selmon = m;
		focus(NULL);
	}
}

void
restack(Monitor *m) {
	Client *c;
	XEvent ev;
	XWindowChanges wc;

	drawbar(m);
	if(!m->sel)
		return;
	if(m->sel->isfloating || !m->lt[m->sellt]->arrange)
		XRaiseWindow(dpy, m->sel->win);
	if(m->lt[m->sellt]->arrange) {
		wc.stack_mode = Below;
		wc.sibling = m->barwin;
		for(c = m->stack; c; c = c->snext)
			if(!c->isfloating && ISVISIBLE(c)) {
				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
				wc.sibling = c->win;
			}
	}
	XSync(dpy, False);
	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}

void
run(void) {
	XEvent ev;
	/* main event loop */
	XSync(dpy, False);
	while(running && !XNextEvent(dpy, &ev)) {
		if(handler[ev.type])
			handler[ev.type](&ev); /* call handler */
	}
}

void
scan(void) {
	unsigned int i, num;
	Window d1, d2, *wins = NULL;
	XWindowAttributes wa;

	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
		for(i = 0; i < num; i++) {
			if(!XGetWindowAttributes(dpy, wins[i], &wa)
			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
				continue;
			if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
				manage(wins[i], &wa);
		}
		for(i = 0; i < num; i++) { /* now the transients */
			if(!XGetWindowAttributes(dpy, wins[i], &wa))
				continue;
			if(XGetTransientForHint(dpy, wins[i], &d1)
			&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
				manage(wins[i], &wa);
		}
		if(wins)
			XFree(wins);
	}
}

void
sendmon(Client *c, Monitor *m) {
	if(c->mon == m)
		return;
	unfocus(c, True);
	detach(c);
	detachstack(c);
	c->mon = m;
	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
	attach(c);
	attachstack(c);
	focus(NULL);
	arrange(NULL);
}

void
setclientstate(Client *c, long state) {
	long data[] = { state, None };

	XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
			PropModeReplace, (unsigned char *)data, 2);
}

Bool
sendevent(Client *c, Atom proto) {
	int n;
	Atom *protocols;
	Bool exists = False;
	XEvent ev;

	if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
		while(!exists && n--)
			exists = protocols[n] == proto;
		XFree(protocols);
	}
	if(exists) {
		ev.type = ClientMessage;
		ev.xclient.window = c->win;
		ev.xclient.message_type = wmatom[WMProtocols];
		ev.xclient.format = 32;
		ev.xclient.data.l[0] = proto;
		ev.xclient.data.l[1] = CurrentTime;
		XSendEvent(dpy, c->win, False, NoEventMask, &ev);
	}
	return exists;
}

void
setfocus(Client *c) {
	if(!c->neverfocus)
		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
	sendevent(c, wmatom[WMTakeFocus]);
}

void
setlayout(const Arg *arg) {
	if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
		selmon->sellt ^= 1;
	if(arg && arg->v)
		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout*)arg->v;
	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
	if(selmon->sel)
		arrange(selmon);
	else
		drawbar(selmon);
}

/* arg > 1.0 will set mfact absolutly */
void
setmfact(const Arg *arg) {
	float f;

	if(!arg || !selmon->lt[selmon->sellt]->arrange)
		return;
	f = arg->f < 1.0 ? arg->f + selmon->mfacts[selmon->curtag] : arg->f - 1.0;
	if(f < 0.1 || f > 0.9)
		return;
	selmon->mfacts[selmon->curtag] = f;
	arrange(selmon);
}

void
setup(void) {
	XSetWindowAttributes wa;

	/* clean up any zombies immediately */
	sigchld(0);

	/* init screen */
	screen = DefaultScreen(dpy);
	root = RootWindow(dpy, screen);
	initfont(font);
	sw = DisplayWidth(dpy, screen);
	sh = DisplayHeight(dpy, screen);
#ifdef TOP_BAR_HEIGHT
	bh = dc.h = TOP_BAR_HEIGHT;
#else
	bh = dc.h = dc.font.height + 2;
#endif
	updategeom();
	/* init atoms */
	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
	wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
	netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
	netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
	netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
	/* init cursors */
	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
	/* init appearance */
	unsigned int c;
	for(c=0; c<NumColors; c++) {
		barcolors[c][ColBorder] = getcolor( colors[c][ColBorder], dc.xftnorm+ColBorder );
		barcolors[c][ColFG] = getcolor( colors[c][ColFG], dc.xftnorm+ColFG );
		barcolors[c][ColBG] = getcolor( colors[c][ColBG], dc.xftnorm+ColBG);
	}
	dc.norm[ColBorder] = getcolor(normbordercolor, dc.xftnorm+ColBorder);
	dc.norm[ColBG] = getcolor(normbgcolor, dc.xftnorm+ColBG);
	dc.norm[ColFG] = getcolor(normfgcolor, dc.xftnorm+ColFG);
	dc.sel[ColBorder] = getcolor(selbordercolor, dc.xftsel+ColBorder);
	dc.sel[ColBG] = getcolor(selbgcolor, dc.xftsel+ColBG);
	dc.sel[ColFG] = getcolor(selfgcolor, dc.xftsel+ColFG);
	dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
	dc.gc = XCreateGC(dpy, root, 0, NULL);
	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
	dc.xftdrawable = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy,screen), DefaultColormap(dpy,screen));
	if(!dc.xftdrawable)
		printf("error, cannot create drawable\n");
	/* init bars */
	updatebars();
	updatestatus();
	/* EWMH support per view */
	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
			PropModeReplace, (unsigned char *) netatom, NetLast);
	/* select for events */
	wa.cursor = cursor[CurNormal];
	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
	                |EnterWindowMask|LeaveWindowMask|StructureNotifyMask
	                |PropertyChangeMask;
	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
	XSelectInput(dpy, root, wa.event_mask);
	grabkeys();
}

void
showhide(Client *c) {
	if(!c)
		return;
	if(ISVISIBLE(c)) { /* show clients top down */
		if(c->needresize) {
			c->needresize = False;
			XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
		} else {
			XMoveWindow(dpy, c->win, c->x, c->y);
		}
		if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
			resize(c, c->x, c->y, c->w, c->h, False);
		showhide(c->snext);
	}
	else { /* hide clients bottom up */
		showhide(c->snext);
		XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
	}
}

void
sigchld(int unused) {
	if(signal(SIGCHLD, sigchld) == SIG_ERR)
		die("Can't install SIGCHLD handler");
	while(0 < waitpid(-1, NULL, WNOHANG));
}

void
spawn(const Arg *arg) {
	if(fork() == 0) {
		if(dpy)
			close(ConnectionNumber(dpy));
		setsid();
		execvp(((char **)arg->v)[0], (char **)arg->v);
		fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
		perror(" failed");
		exit(EXIT_SUCCESS);
	}
}

void
tag(const Arg *arg) {
	if(selmon->sel && arg->ui & TAGMASK) {
		selmon->sel->tags = arg->ui & TAGMASK;
		arrange(selmon);
	}
}

void
tagmon(const Arg *arg) {
	if(!selmon->sel || !mons->next)
		return;
	sendmon(selmon->sel, dirtomon(arg->i));
}

int
textnw(const char *text, unsigned int len) {
	PangoRectangle r;
	pango_layout_set_text(dc.plo, text, len);
	pango_layout_get_extents(dc.plo, &r, 0);
	return r.width / PANGO_SCALE;
}

void
tile(Monitor *m) {
	int x, y, h, w, mw;
	unsigned int i, n;
	Client *c;

	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
	if(n == 0)
		return;
	/* master */
	c = nexttiled(m->clients);
	mw = m->mfacts[m->curtag] * m->ww;
	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False);
	if(--n == 0)
		return;
	/* tile stack */
	x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw;
	y = m->wy;
	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
	h = m->wh / n;
	if(h < bh)
		h = m->wh;
	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False);
		if(h != m->wh)
			y = c->y + HEIGHT(c);
	}
}

void
togglebar(const Arg *arg) {
	selmon->showbar = !selmon->showbar;
	updatebarpos(selmon);
	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
	arrange(selmon);
}

void
togglefloating(const Arg *arg) {
	if(!selmon->sel)
		return;
	selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed;
	if(selmon->sel->isfloating)
		resize(selmon->sel, selmon->sel->x, selmon->sel->y,
		       selmon->sel->w, selmon->sel->h, False);
	arrange(selmon);
}

void
toggletag(const Arg *arg) {
	unsigned int newtags;
	unsigned int i;

	if(!selmon->sel)
		return;
	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
	if(newtags) {
		selmon->sel->tags = newtags;
		if(newtags == ~0) {
			selmon->prevtag = selmon->curtag;
			selmon->curtag  = 0;
		}
		if(!(newtags & 1 << (selmon->curtag -1))) {
			selmon->prevtag = selmon->curtag;
			for (i=0; !(newtags & 1 << i); i++);
			selmon->curtag = i + 1;
		}
		selmon->sel->tags = newtags;
		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
		arrange(selmon);
	}
}

void
toggleview(const Arg *arg) {
	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);

	if(newtagset) {
		selmon->tagset[selmon->seltags] = newtagset;
		arrange(selmon);
	}
}

void
unfocus(Client *c, Bool setfocus) {
	if(!c)
		return;
	grabbuttons(c, False);
	XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
	if(setfocus)
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}

void
unmanage(Client *c, Bool destroyed) {
	Monitor *m = c->mon;
	XWindowChanges wc;

	/* The server grab construct avoids race conditions. */
	detach(c);
	detachstack(c);
	if(!destroyed) {
		wc.border_width = c->oldbw;
		XGrabServer(dpy);
		XSetErrorHandler(xerrordummy);
		XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
		XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
		setclientstate(c, WithdrawnState);
		XSync(dpy, False);
		XSetErrorHandler(xerror);
		XUngrabServer(dpy);
	}
	free(c);
	focus(NULL);
	arrange(m);
}

void
unmapnotify(XEvent *e) {
	Client *c;
	XUnmapEvent *ev = &e->xunmap;

	if((c = wintoclient(ev->window)))
		unmanage(c, False);
}

void
updatebars(void) {
	Monitor *m;
	XSetWindowAttributes wa = {
		.override_redirect = True,
		.background_pixmap = ParentRelative,
		.event_mask = ButtonPressMask|ExposureMask
	};
	for(m = mons; m; m = m->next) {
		m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
		                          CopyFromParent, DefaultVisual(dpy, screen),
		                          CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
		XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
		XMapRaised(dpy, m->barwin);
	}
}

void
updatebarpos(Monitor *m) {
	m->wy = m->my;
	m->wh = m->mh;
	if(m->showbar) {
		m->wh -= bh;
		m->wh -= BOTTOM_BAR_HEIGHT;
		if(!m->topbar)
			m->wh += BOTTOM_BAR_HEIGHT;
		m->by = m->topbar ? m->wy : m->wy + m->wh;
		m->wy = m->topbar ? m->wy + bh : m->wy;
	}
	else
		m->by = -bh;
}

Bool
updategeom(void) {
	Bool dirty = False;

#ifdef XINERAMA
	if(XineramaIsActive(dpy)) {
		int i, j, n, nn;
		Client *c;
		Monitor *m;
		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
		XineramaScreenInfo *unique = NULL;

		for(n = 0, m = mons; m; m = m->next, n++);
		/* only consider unique geometries as separate screens */
		if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn)))
			die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn);
		for(i = 0, j = 0; i < nn; i++)
			if(isuniquegeom(unique, j, &info[i]))
				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
		XFree(info);
		nn = j;
		if(n <= nn) {
			for(i = 0; i < (nn - n); i++) { /* new monitors available */
				for(m = mons; m && m->next; m = m->next);
				if(m)
					m->next = createmon();
				else
					mons = createmon();
			}
			for(i = 0, m = mons; i < nn && m; m = m->next, i++)
				if(i >= n
				|| (unique[i].x_org != m->mx || unique[i].y_org != m->my
				    || unique[i].width != m->mw || unique[i].height != m->mh))
				{
					dirty = True;
					m->num = i;
					m->mx = m->wx = unique[i].x_org;
					m->my = m->wy = unique[i].y_org;
					m->mw = m->ww = unique[i].width;
					m->mh = m->wh = unique[i].height;
					updatebarpos(m);
				}
		}
		else { /* less monitors available nn < n */
			for(i = nn; i < n; i++) {
				for(m = mons; m && m->next; m = m->next);
				while(m->clients) {
					dirty = True;
					c = m->clients;
					m->clients = c->next;
					detachstack(c);
					c->mon = mons;
					attach(c);
					attachstack(c);
				}
				if(m == selmon)
					selmon = mons;
				cleanupmon(m);
			}
		}
		free(unique);
	}
	else
#endif /* XINERAMA */
	/* default monitor setup */
	{
		if(!mons)
			mons = createmon();
		if(mons->mw != sw || mons->mh != sh) {
			dirty = True;
			mons->mw = mons->ww = sw;
			mons->mh = mons->wh = sh;
			updatebarpos(mons);
		}
	}
	if(dirty) {
		selmon = mons;
		selmon = wintomon(root);
	}
	return dirty;
}

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
updatesizehints(Client *c) {
	long msize;
	XSizeHints size;

	if(!XGetWMNormalHints(dpy, c->win, &size, &msize))
		/* size is uninitialized, ensure that size.flags aren't used */
		size.flags = PSize;
	if(size.flags & PBaseSize) {
		c->basew = size.base_width;
		c->baseh = size.base_height;
	}
	else if(size.flags & PMinSize) {
		c->basew = size.min_width;
		c->baseh = size.min_height;
	}
	else
		c->basew = c->baseh = 0;
	if(size.flags & PResizeInc) {
		c->incw = size.width_inc;
		c->inch = size.height_inc;
	}
	else
		c->incw = c->inch = 0;
	if(size.flags & PMaxSize) {
		c->maxw = size.max_width;
		c->maxh = size.max_height;
	}
	else
		c->maxw = c->maxh = 0;
	if(size.flags & PMinSize) {
		c->minw = size.min_width;
		c->minh = size.min_height;
	}
	else if(size.flags & PBaseSize) {
		c->minw = size.base_width;
		c->minh = size.base_height;
	}
	else
		c->minw = c->minh = 0;
	if(size.flags & PAspect) {
		c->mina = (float)size.min_aspect.y / size.min_aspect.x;
		c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
	}
	else
		c->maxa = c->mina = 0.0;
	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
	             && c->maxw == c->minw && c->maxh == c->minh);
}

void
updatetitle(Client *c) {
	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
	if(c->name[0] == '\0') /* hack to mark broken clients */
		strcpy(c->name, broken);
}

void
updatestatus(void) {
	if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
		strcpy(stext, "dwm-"VERSION);
	drawbar(selmon);
}

void
updatewmhints(Client *c) {
	XWMHints *wmh;

	if((wmh = XGetWMHints(dpy, c->win))) {
		if(c == selmon->sel && wmh->flags & XUrgencyHint) {
			wmh->flags &= ~XUrgencyHint;
			XSetWMHints(dpy, c->win, wmh);
		}
		else
			c->isurgent = (wmh->flags & XUrgencyHint) ? True : False;
		if(wmh->flags & InputHint)
			c->neverfocus = !wmh->input;
		else
			c->neverfocus = False;
		XFree(wmh);
	}
}

void
view(const Arg *arg) {
	unsigned int i;

	if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
		return;
	selmon->seltags ^= 1; /* toggle sel tagset */
	if(arg->ui & TAGMASK) {
		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
		selmon->prevtag = selmon->curtag;
		if(arg->ui == ~0)
			selmon->curtag = 0;
		else {
			for(i=0; !(arg->ui & 1 << i); i++);
			selmon->curtag = i + 1;
		}
	} else {
		selmon->prevtag = selmon->curtag ^ selmon->prevtag;
		selmon->curtag ^= selmon->prevtag;
		selmon->prevtag = selmon->curtag ^ selmon->prevtag;
	}
	selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
	arrange(selmon);
}

void
view_adjacent_tag(int distance)
{
	int i, curtags;
	int seltag = 0;
	Arg arg;

	curtags = (selmon->tagset[selmon->seltags] & TAGMASK);
	for(i = 0; i < LENGTH(tags); i++) {
		if((curtags & (1 << i)) != 0) {
			seltag = i;
			break;
		}
	}

	seltag = (seltag + distance) % (int)LENGTH(tags);
	if(seltag < 0)
		seltag += LENGTH(tags);

	arg.i   = (1 << seltag);
	view(&arg);
}

void
view_next_tag(const Arg *arg)
{
	(void)arg;
	view_adjacent_tag(+1);
}

void
view_prev_tag(const Arg *arg)
{
	(void)arg;
	view_adjacent_tag(-1);
}

Client *
wintoclient(Window w) {
	Client *c;
	Monitor *m;

	for(m = mons; m; m = m->next)
		for(c = m->clients; c; c = c->next)
			if(c->win == w)
				return c;
	return NULL;
}

Monitor *
wintomon(Window w) {
	int x, y;
	Client *c;
	Monitor *m;

	if(w == root && getrootptr(&x, &y))
		return ptrtomon(x, y);
	for(m = mons; m; m = m->next)
		if(w == m->barwin)
			return m;
	if((c = wintoclient(w)))
		return c->mon;
	return selmon;
}

/* There's no way to check accesses to destroyed windows, thus those cases are
 * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
 * default error handler, which may call exit.  */
int
xerror(Display *dpy, XErrorEvent *ee) {
	if(ee->error_code == BadWindow
	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
	|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
	|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
	|| (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
	|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
	|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
		return 0;
	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
			ee->request_code, ee->error_code);
	return xerrorxlib(dpy, ee); /* may call exit */
}

int
xerrordummy(Display *dpy, XErrorEvent *ee) {
	return 0;
}

/* Startup Error handler to check if another window manager
 * is already running. */
int
xerrorstart(Display *dpy, XErrorEvent *ee) {
	die("dwm: another window manager is already running\n");
	return -1;
}

void
zoom(const Arg *arg) {
	Client *c = selmon->sel;

	if(!selmon->lt[selmon->sellt]->arrange
	|| (selmon->sel && selmon->sel->isfloating))
		return;
	if(c == nexttiled(selmon->clients))
		if(!c || !(c = nexttiled(c->next)))
			return;
	pop(c);
}

void
incnmaster(const Arg *arg) {
	if(!arg || !selmon->lt[selmon->sellt]->arrange)
		return;
	selmon->nmasters[selmon->curtag] = MAX(selmon->nmasters[selmon->curtag] + arg->i, 1);
	arrange(NULL);
}

void
ntile(Monitor *m) {
	unsigned int i, n, mw, mh, tw, th;
	Client *c;

	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
	if(n == 0)
		return;

	mh = (n > m->nmasters[m->curtag]) ? m->wh / m->nmasters[m->curtag] : m->wh / n;
	mw = (n > m->nmasters[m->curtag]) ? m->ww * m->mfacts[m->curtag] : m->ww;
	th = (n > m->nmasters[m->curtag]) ? m->wh / (n - m->nmasters[m->curtag]) : 0;
	tw = m->ww - mw;

	for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if(i < m->nmasters[m->curtag])
			resize(c, m->wx, m->wy + (i*mh), mw - (2*c->bw), mh - (2*c->bw), False);
		else
			resize(c, m->wx + mw, m->wy + ((i - m->nmasters[m->curtag])*th), tw - (2*c->bw), th - (2*c->bw), False);
}


int
main(int argc, char *argv[]) {
	if(argc == 2 && !strcmp("-v", argv[1]))
		die("dwm-"VERSION", © 2006-2011 dwm engineers, see LICENSE for details\n");
	else if(argc != 1)
		die("usage: dwm [-v]\n");
	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
		fputs("warning: no locale support\n", stderr);
	if(!(dpy = XOpenDisplay(NULL)))
		die("dwm: cannot open display\n");
	checkotherwm();
	setup();
	scan();
	run();
	cleanup();
	XCloseDisplay(dpy);
	return EXIT_SUCCESS;
}

EDIT: Added dwm files

Last edited by c0r73x (2011-09-04 08:35:50)

Offline

Board footer

Powered by FluxBB