You are not logged in.
but (false) transparent bar for dwm would be fancy! looking forward to anyone who submit a patch
You are right. Here:
(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
“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
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
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
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
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.
“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
fair enough
Offline
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
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.
-- 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
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.
Really nice color scheme, can you post your .Xresources/.Xdefaults.
Offline
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
This is my DWM setup for my new notebook for school this September.
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
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
[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
Use rxvt-unicode-patched from AUR.
Nice! Thanks!
Offline
bump
When you live for a strong purpose, then hard work isn't an option. It's a necessity. - Steve Pavlina
dotFiles
Offline
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.
Last edited by mjheagle8 (2011-08-17 14:47:38)
Desktop/Laptop - DWM :: VM - screen
Registered Linux User Number 483137 :: Victory! :: GitHub
Offline
It doesn't work, sorry for repost my help here. I just create new thread but the mod has closed it
When you live for a strong purpose, then hard work isn't an option. It's a necessity. - Steve Pavlina
dotFiles
Offline
It doesn't work, sorry for repost my help here. I just create new thread but the mod has closed it
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
Offline
Nice work c0r73x: but this is the screenshot thread - you want this in https://bbs.archlinux.org/viewtopic.php?id=92895
Offline
Offline
Quite heavily modified dwm.. Looks like dwm on outside, but acts different inside.
/*
* 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} },
};
Offline
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
http://img163.imageshack.us/img163/6715/dwm20110820095721.th.png
Can you show your dwm/.Xresources/vim/weechat configs?
Thx.
Offline
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} }, };
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
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
http://img163.imageshack.us/img163/6715/dwm20110820095721.th.pngCan 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
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