Created
April 21, 2015 11:28
-
-
Save Stanley00/2e4b3b71b6e55bac39b5 to your computer and use it in GitHub Desktop.
DWM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* See LICENSE file for copyright and license details. */ | |
/* appearance */ | |
static const char font[] = "-*-droid sans-medium-r-*-*-12-*-*-*-*-*-*-*"; | |
static const char normbordercolor[] = "#3BFF3B"; | |
static const char normbgcolor[] = "#222222"; | |
static const char normfgcolor[] = "#0EB00E"; | |
static const char selbordercolor[] = "#EE0000"; | |
static const char selbgcolor[] = "#111111"; | |
static const char selfgcolor[] = "#EA0000"; | |
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 */ | |
static const unsigned int systrayspacing = 1; /* systray spacing */ | |
static const Bool showsystray = True; /* False means no systray */ | |
/* tagging */ | |
static const char *tags[] = { "T", "W", "S", "|", "C", "E", "D", "|", "F", "X", "R", "|", "Q", "A", "Z" }; | |
/* using xprop to get window info */ | |
static const Rule rules[] = { | |
/* class instance title tags mask isfloating monitor */ | |
{ "Terminator", NULL, NULL, 1 << 0, False, -1 }, | |
{ "Xfce4-terminal", NULL, NULL, 1 << 0, False, -1 }, | |
{ "Mate-terminal", NULL, NULL, 1 << 0, False, -1 }, | |
{ "Sakura", NULL, NULL, 1 << 0, False, -1 }, | |
{ "Chromium", NULL, NULL, 1 << 1, False, -1 }, | |
{ "Firefox", NULL, NULL, 1 << 3, False, -1 }, | |
{ "Hexchat", NULL, NULL, 1 << 9, False, -1 }, | |
{ "Xchat", NULL, NULL, 1 << 9, False, -1 }, | |
{ "Skype", NULL, NULL, 1 << 11, False, -1 }, | |
{ "Pidgin", NULL, NULL, 1 << 9, False, -1 }, | |
{ "Xchm", NULL, NULL, 1 << 2, False, -1 }, | |
{ "Evince", NULL, NULL, 1 << 2, False, -1 }, | |
{ "Atril", NULL, NULL, 1 << 2, False, -1 }, | |
{ "Eclipse", NULL, NULL, 1 << 4, False, -1 }, | |
{ "Java", NULL, "Eclipse", 1 << 4, False, -1 }, | |
{ "Geany", NULL, NULL, 1 << 5, False, -1 }, | |
{ "libreoffice",NULL, NULL, 1 << 6, False, -1 }, | |
{ "Pcmanfm", NULL, NULL, 1 << 8, False, -1 }, | |
{ "Caja", NULL, NULL, 1 << 8, False, -1 }, | |
{ "Thunar", NULL, NULL, 1 << 8, False, -1 }, | |
{ "Deadbeef", NULL, NULL, 1 << 10, False, -1 }, | |
{ NULL, NULL, NULL, 0, False, -1 }, | |
}; | |
/* layout(s) */ | |
static const float mfact = 0.8; /* factor of master area size [0.05..0.95] */ | |
static const int nmaster = 1; /* number of clients in master area */ | |
static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ | |
static const Layout layouts[] = { | |
/* symbol arrange function */ | |
{ "[]=", tile }, /* first entry is default */ | |
{ "><>", NULL }, /* no layout function means floating behavior */ | |
{ "[M]", monocle }, | |
}; | |
/* key definitions */ | |
#define MODKEY Mod4Mask | |
#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", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; | |
static const char *termcmd[] = { "sakura", NULL }; | |
static const char *viewcmd[] = { "evince", NULL }; | |
static const char *codecmd[] = { "eclipse", NULL }; | |
/*static const char *filemgrcmd[] = { "caja", "--no-desktop", "--browser", NULL }; */ | |
static const char *filemgrcmd[] = { "thunar", NULL }; | |
static const char *geanycmd[] = { "geany", NULL }; | |
static const char *webcmd_alt[] = { "firefox", NULL }; | |
static const char *webcmd[] = { "chromium", NULL }; | |
static const char *xchatcmd[] = { "hexchat", NULL }; | |
static const char *doccmd[] = { "libreoffice", NULL }; | |
static const char *sndcmd[] = { "deadbeef", NULL }; | |
static const char *vidcmd[] = { "smplayer", NULL }; | |
static const char *mailcmd[] = { "thunderbird", NULL }; | |
static const char *chatcmd[] = { "pidgin", NULL }; | |
static const char *skypecmd[] = { "skype", NULL }; | |
static const char *lockcmd[] = { "xflock4", NULL }; | |
static Key keys[] = { | |
/* modifier key function argument */ | |
{ MODKEY, XK_r, spawn, {.v = dmenucmd } }, | |
{ MODKEY, XK_p, spawn, {.v = dmenucmd } }, | |
{ MODKEY, XK_l, spawn, {.v = lockcmd } }, | |
{ MODKEY|ShiftMask, XK_t, spawn, {.v = termcmd } }, | |
{ MODKEY|ShiftMask, XK_w, spawn, {.v = webcmd } }, | |
{ MODKEY|ShiftMask, XK_s, spawn, {.v = viewcmd } }, | |
{ MODKEY|ShiftMask, XK_c, spawn, {.v = codecmd } }, | |
{ MODKEY|ShiftMask, XK_e, spawn, {.v = geanycmd } }, | |
{ MODKEY|ShiftMask, XK_d, spawn, {.v = doccmd } }, | |
{ MODKEY|ShiftMask, XK_f, spawn, {.v = filemgrcmd } }, | |
{ MODKEY|ShiftMask, XK_x, spawn, {.v = xchatcmd } }, | |
{ MODKEY|ShiftMask, XK_r, spawn, {.v = sndcmd } }, | |
{ MODKEY|ShiftMask, XK_v, spawn, {.v = vidcmd } }, | |
{ MODKEY|ShiftMask, XK_p, spawn, {.v = chatcmd } }, | |
{ MODKEY|ShiftMask, XK_m, spawn, {.v = mailcmd } }, | |
{ MODKEY|ShiftMask, XK_k, spawn, {.v = skypecmd } }, | |
{ MODKEY, XK_b, togglebar, {0} }, | |
{ MODKEY, XK_j, focusstack, {.i = +1 } }, | |
{ MODKEY, XK_k, focusstack, {.i = -1 } }, | |
{ MODKEY, XK_i, incnmaster, {.i = +1 } }, | |
{ MODKEY, XK_d, incnmaster, {.i = -1 } }, | |
{ MODKEY, XK_h, setmfact, {.f = -0.1} }, | |
{ MODKEY, XK_l, setmfact, {.f = +0.025} }, | |
{ MODKEY, XK_Return, zoom, {0} }, | |
{ MODKEY, XK_Tab, view, {0} }, | |
{ MODKEY|ShiftMask, XK_z, killclient, {0} }, | |
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, | |
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, | |
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, | |
{ 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, changeview, {.i = -1 } }, | |
{ MODKEY, XK_Right, changeview, {.i = +1 } }, | |
TAGKEYS( XK_1, 0) | |
TAGKEYS( XK_2, 1) | |
TAGKEYS( XK_3, 2) | |
TAGKEYS( XK_4, 4) | |
TAGKEYS( XK_5, 5) | |
TAGKEYS( XK_6, 6) | |
TAGKEYS( XK_7, 8) | |
TAGKEYS( XK_8, 9) | |
TAGKEYS( XK_9, 10) | |
{ MODKEY|ShiftMask, XK_q, quit, {0} }, | |
}; | |
/* button definitions */ | |
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ | |
static Button buttons[] = { | |
/* click event mask button function argument */ | |
{ ClkLtSymbol, 0, Button1, setlayout, {0} }, | |
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, | |
{ ClkWinTitle, 0, Button2, zoom, {0} }, | |
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, | |
{ ClkClientWin, MODKEY, Button1, movemouse, {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} }, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/dwm.c 2011-12-19 22:02:46.000000000 +0700 | |
+++ b/dwm.c 2015-04-05 09:04:32.740500543 +0700 | |
@@ -245,6 +245,7 @@ | |
static void updatetitle(Client *c); | |
static void updatewmhints(Client *c); | |
static void view(const Arg *arg); | |
+static void changeview(const Arg *arg); | |
static Client *wintoclient(Window w); | |
static Monitor *wintomon(Window w); | |
static int xerror(Display *dpy, XErrorEvent *ee); | |
@@ -2052,6 +2053,21 @@ | |
arrange(selmon); | |
} | |
+void | |
+changeview(const Arg *arg) { | |
+ static Arg a; | |
+ static unsigned int ROT[] = {1 << (LENGTH(tags)-1), 0, 1}; | |
+ unsigned int current = selmon->tagset[selmon->seltags]; | |
+ if ( arg->i>0) | |
+ current <<= arg->i; | |
+ else | |
+ current >>= -arg->i; | |
+ if ((current & TAGMASK)==0) | |
+ current = ROT[arg->i+1]; | |
+ a.ui=current; | |
+ view(&a); | |
+} | |
+ | |
Client * | |
wintoclient(Window w) { | |
Client *c; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Author: Jan Christoph Ebersbach <jceb@e-jc.de> | |
URL: http://dwm.suckless.org/patches/noborder | |
This patch removes the border when there is just one window visible in tiled or | |
monocle layout. | |
diff -r ec4baab78314 dwm.c | |
--- a/dwm.c Mon Dec 19 15:38:30 2011 +0100 | |
+++ b/dwm.c Fri Apr 06 08:23:31 2012 +0200 | |
@@ -1191,7 +1191,7 @@ | |
void | |
monocle(Monitor *m) { | |
- unsigned int n = 0; | |
+ unsigned int n = 0, r = 0; | |
Client *c; | |
for(c = m->clients; c; c = c->next) | |
@@ -1199,8 +1199,17 @@ | |
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); | |
+ for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) { | |
+ /* remove border when in monocle layout */ | |
+ if(c->bw) { | |
+ c->oldbw = c->bw; | |
+ c->bw = 0; | |
+ r = 1; | |
+ } | |
+ resize(c, m->wx, m->wy, m->ww - (2 * c->bw), m->wh - (2 * c->bw), False); | |
+ if(r) | |
+ resizeclient(c, m->wx, m->wy, m->ww - (2 * c->bw), m->wh - (2 * c->bw)); | |
+ } | |
} | |
void | |
@@ -1703,7 +1712,7 @@ | |
void | |
tile(Monitor *m) { | |
- unsigned int i, n, h, mw, my, ty; | |
+ unsigned int i, n, h, mw, my, ty, r; | |
Client *c; | |
for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); | |
@@ -1714,17 +1723,36 @@ | |
mw = m->nmaster ? m->ww * m->mfact : 0; | |
else | |
mw = m->ww; | |
- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) | |
+ for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, r = 0) { | |
+ if(n == 1) { | |
+ if (c->bw) { | |
+ /* remove border when only one window is on the current tag */ | |
+ c->oldbw = c->bw; | |
+ c->bw = 0; | |
+ r = 1; | |
+ } | |
+ } | |
+ else if(!c->bw && c->oldbw) { | |
+ /* restore border when more than one window is displayed */ | |
+ c->bw = c->oldbw; | |
+ c->oldbw = 0; | |
+ r = 1; | |
+ } | |
if(i < m->nmaster) { | |
h = (m->wh - my) / (MIN(n, m->nmaster) - i); | |
resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); | |
+ if(r) | |
+ resizeclient(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw)); | |
my += HEIGHT(c); | |
} | |
else { | |
h = (m->wh - ty) / (n - i); | |
resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); | |
+ if(r) | |
+ resizeclient(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw)); | |
ty += HEIGHT(c); | |
} | |
+ } | |
} | |
void | |
@@ -1741,6 +1769,12 @@ | |
return; | |
selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; | |
if(selmon->sel->isfloating) | |
+ /* restore border when moving window into floating mode */ | |
+ if(!selmon->sel->bw && selmon->sel->oldbw) { | |
+ selmon->sel->bw = selmon->sel->oldbw; | |
+ selmon->sel->oldbw = 0; | |
+ } | |
+ if(selmon->sel->isfloating) | |
resize(selmon->sel, selmon->sel->x, selmon->sel->y, | |
selmon->sel->w, selmon->sel->h, False); | |
arrange(selmon); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Author: Jan Christoph Ebersbach <jceb@e-jc.de>, inspired by http://code.google.com/p/dwm-plus | |
URL: http://dwm.suckless.org/patches/systray | |
Implements a system tray for dwm. | |
diff -r ec4baab78314 config.def.h | |
--- a/config.def.h Mon Dec 19 15:38:30 2011 +0100 | |
+++ b/config.def.h Fri Apr 06 08:25:40 2012 +0200 | |
@@ -10,6 +10,8 @@ | |
static const char selfgcolor[] = "#eeeeee"; | |
static const unsigned int borderpx = 1; /* border pixel of windows */ | |
static const unsigned int snap = 32; /* snap pixel */ | |
+static const unsigned int systrayspacing = 2; /* systray spacing */ | |
+static const Bool showsystray = True; /* False means no systray */ | |
static const Bool showbar = True; /* False means no bar */ | |
static const Bool topbar = True; /* False means bottom bar */ | |
diff -r ec4baab78314 dwm.c | |
--- a/dwm.c Mon Dec 19 15:38:30 2011 +0100 | |
+++ b/dwm.c Fri Apr 06 08:25:40 2012 +0200 | |
@@ -55,12 +55,30 @@ | |
#define TAGMASK ((1 << LENGTH(tags)) - 1) | |
#define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) | |
+#define SYSTEM_TRAY_REQUEST_DOCK 0 | |
+#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 | |
+ | |
+/* XEMBED messages */ | |
+#define XEMBED_EMBEDDED_NOTIFY 0 | |
+#define XEMBED_WINDOW_ACTIVATE 1 | |
+#define XEMBED_FOCUS_IN 4 | |
+#define XEMBED_MODALITY_ON 10 | |
+ | |
+#define XEMBED_MAPPED (1 << 0) | |
+#define XEMBED_WINDOW_ACTIVATE 1 | |
+#define XEMBED_WINDOW_DEACTIVATE 2 | |
+ | |
+#define VERSION_MAJOR 0 | |
+#define VERSION_MINOR 0 | |
+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR | |
+ | |
/* enums */ | |
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | |
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ | |
-enum { NetSupported, NetWMName, NetWMState, | |
- NetWMFullscreen, NetActiveWindow, NetWMWindowType, | |
- NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ | |
+enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, | |
+ NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType, | |
+ NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ | |
+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ | |
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ | |
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, | |
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ | |
@@ -154,6 +172,12 @@ | |
int monitor; | |
} Rule; | |
+typedef struct Systray Systray; | |
+struct Systray { | |
+ Window win; | |
+ Client *icons; | |
+}; | |
+ | |
/* function declarations */ | |
static void applyrules(Client *c); | |
static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); | |
@@ -186,9 +210,11 @@ | |
static void focusin(XEvent *e); | |
static void focusmon(const Arg *arg); | |
static void focusstack(const Arg *arg); | |
+static Atom getatomprop(Client *c, Atom prop); | |
static unsigned long getcolor(const char *colstr); | |
static Bool getrootptr(int *x, int *y); | |
static long getstate(Window w); | |
+static unsigned int getsystraywidth(); | |
static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); | |
static void grabbuttons(Client *c, Bool focused); | |
static void grabkeys(void); | |
@@ -207,13 +233,16 @@ | |
static void propertynotify(XEvent *e); | |
static void quit(const Arg *arg); | |
static Monitor *recttomon(int x, int y, int w, int h); | |
+static void removesystrayicon(Client *i); | |
static void resize(Client *c, int x, int y, int w, int h, Bool interact); | |
+static void resizebarwin(Monitor *m); | |
static void resizeclient(Client *c, int x, int y, int w, int h); | |
static void resizemouse(const Arg *arg); | |
+static void resizerequest(XEvent *e); | |
static void restack(Monitor *m); | |
static void run(void); | |
static void scan(void); | |
-static Bool sendevent(Client *c, Atom proto); | |
+static Bool sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); | |
static void sendmon(Client *c, Monitor *m); | |
static void setclientstate(Client *c, long state); | |
static void setfocus(Client *c); | |
@@ -241,18 +270,24 @@ | |
static void updatenumlockmask(void); | |
static void updatesizehints(Client *c); | |
static void updatestatus(void); | |
+static void updatesystray(void); | |
+static void updatesystrayicongeom(Client *i, int w, int h); | |
+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); | |
static void updatewindowtype(Client *c); | |
static void updatetitle(Client *c); | |
static void updatewmhints(Client *c); | |
static void view(const Arg *arg); | |
static Client *wintoclient(Window w); | |
static Monitor *wintomon(Window w); | |
+static Client *wintosystrayicon(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); | |
/* variables */ | |
+static Systray *systray = NULL; | |
+static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; | |
static const char broken[] = "broken"; | |
static char stext[256]; | |
static int screen; | |
@@ -274,9 +309,10 @@ | |
[MapRequest] = maprequest, | |
[MotionNotify] = motionnotify, | |
[PropertyNotify] = propertynotify, | |
+ [ResizeRequest] = resizerequest, | |
[UnmapNotify] = unmapnotify | |
}; | |
-static Atom wmatom[WMLast], netatom[NetLast]; | |
+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; | |
static Bool running = True; | |
static Cursor cursor[CurLast]; | |
static Display *dpy; | |
@@ -497,6 +533,11 @@ | |
XFreeCursor(dpy, cursor[CurMove]); | |
while(mons) | |
cleanupmon(mons); | |
+ if(showsystray) { | |
+ XUnmapWindow(dpy, systray->win); | |
+ XDestroyWindow(dpy, systray->win); | |
+ free(systray); | |
+ } | |
XSync(dpy, False); | |
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); | |
} | |
@@ -530,9 +571,48 @@ | |
void | |
clientmessage(XEvent *e) { | |
+ XWindowAttributes wa; | |
+ XSetWindowAttributes swa; | |
XClientMessageEvent *cme = &e->xclient; | |
Client *c = wintoclient(cme->window); | |
+ if(showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { | |
+ /* add systray icons */ | |
+ if(cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { | |
+ if(!(c = (Client *)calloc(1, sizeof(Client)))) | |
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); | |
+ c->win = cme->data.l[2]; | |
+ c->mon = selmon; | |
+ c->next = systray->icons; | |
+ systray->icons = c; | |
+ XGetWindowAttributes(dpy, c->win, &wa); | |
+ c->x = c->oldx = c->y = c->oldy = 0; | |
+ c->w = c->oldw = wa.width; | |
+ c->h = c->oldh = wa.height; | |
+ c->oldbw = wa.border_width; | |
+ c->bw = 0; | |
+ c->isfloating = True; | |
+ /* reuse tags field as mapped status */ | |
+ c->tags = 1; | |
+ updatesizehints(c); | |
+ updatesystrayicongeom(c, wa.width, wa.height); | |
+ XAddToSaveSet(dpy, c->win); | |
+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); | |
+ XReparentWindow(dpy, c->win, systray->win, 0, 0); | |
+ /* use parents background pixmap */ | |
+ swa.background_pixmap = ParentRelative; | |
+ XChangeWindowAttributes(dpy, c->win, CWBackPixmap, &swa); | |
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); | |
+ /* FIXME not sure if I have to send these events, too */ | |
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); | |
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); | |
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); | |
+ resizebarwin(selmon); | |
+ updatesystray(); | |
+ setclientstate(c, NormalState); | |
+ } | |
+ return; | |
+ } | |
if(!c) | |
return; | |
if(cme->message_type == netatom[NetWMState]) { | |
@@ -583,7 +663,7 @@ | |
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); | |
+ resizebarwin(m); | |
focus(NULL); | |
arrange(NULL); | |
} | |
@@ -667,6 +747,11 @@ | |
if((c = wintoclient(ev->window))) | |
unmanage(c, True); | |
+ else if((c = wintosystrayicon(ev->window))) { | |
+ removesystrayicon(c); | |
+ resizebarwin(selmon); | |
+ updatesystray(); | |
+ } | |
} | |
void | |
@@ -722,6 +807,7 @@ | |
unsigned long *col; | |
Client *c; | |
+ resizebarwin(m); | |
for(c = m->clients; c; c = c->next) { | |
occ |= c->tags; | |
if(c->isurgent) | |
@@ -743,6 +829,9 @@ | |
if(m == selmon) { /* status is only drawn on selected monitor */ | |
dc.w = TEXTW(stext); | |
dc.x = m->ww - dc.w; | |
+ if(showsystray && m == selmon) { | |
+ dc.x -= getsystraywidth(); | |
+ } | |
if(dc.x < x) { | |
dc.x = x; | |
dc.w = m->ww - x; | |
@@ -771,6 +860,7 @@ | |
for(m = mons; m; m = m->next) | |
drawbar(m); | |
+ updatesystray(); | |
} | |
void | |
@@ -917,10 +1007,17 @@ | |
unsigned long dl; | |
unsigned char *p = NULL; | |
Atom da, atom = None; | |
+ /* FIXME getatomprop should return the number of items and a pointer to | |
+ * the stored data instead of this workaround */ | |
+ Atom req = XA_ATOM; | |
+ if(prop == xatom[XembedInfo]) | |
+ req = xatom[XembedInfo]; | |
- if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, | |
+ if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, | |
&da, &di, &dl, &dl, &p) == Success && p) { | |
atom = *(Atom *)p; | |
+ if(da == xatom[XembedInfo] && dl == 2) | |
+ atom = ((Atom *)p)[1]; | |
XFree(p); | |
} | |
return atom; | |
@@ -962,6 +1059,15 @@ | |
return result; | |
} | |
+unsigned int | |
+getsystraywidth() { | |
+ unsigned int w = 0; | |
+ Client *i; | |
+ if(showsystray) | |
+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; | |
+ return w ? w + systrayspacing : 1; | |
+} | |
+ | |
Bool | |
gettextprop(Window w, Atom atom, char *text, unsigned int size) { | |
char **list = NULL; | |
@@ -1096,7 +1202,7 @@ | |
killclient(const Arg *arg) { | |
if(!selmon->sel) | |
return; | |
- if(!sendevent(selmon->sel, wmatom[WMDelete])) { | |
+ if(!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { | |
XGrabServer(dpy); | |
XSetErrorHandler(xerrordummy); | |
XSetCloseDownMode(dpy, DestroyAll); | |
@@ -1180,6 +1286,12 @@ | |
maprequest(XEvent *e) { | |
static XWindowAttributes wa; | |
XMapRequestEvent *ev = &e->xmaprequest; | |
+ Client *i; | |
+ if((i = wintosystrayicon(ev->window))) { | |
+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); | |
+ resizebarwin(selmon); | |
+ updatesystray(); | |
+ } | |
if(!XGetWindowAttributes(dpy, ev->window, &wa)) | |
return; | |
@@ -1293,6 +1405,16 @@ | |
Window trans; | |
XPropertyEvent *ev = &e->xproperty; | |
+ if((c = wintosystrayicon(ev->window))) { | |
+ if(ev->atom == XA_WM_NORMAL_HINTS) { | |
+ updatesizehints(c); | |
+ updatesystrayicongeom(c, c->w, c->h); | |
+ } | |
+ else | |
+ updatesystrayiconstate(c, ev); | |
+ resizebarwin(selmon); | |
+ updatesystray(); | |
+ } | |
if((ev->window == root) && (ev->atom == XA_WM_NAME)) | |
updatestatus(); | |
else if(ev->state == PropertyDelete) | |
@@ -1342,12 +1464,33 @@ | |
} | |
void | |
+removesystrayicon(Client *i) { | |
+ Client **ii; | |
+ | |
+ if(!showsystray || !i) | |
+ return; | |
+ for(ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); | |
+ if(ii) | |
+ *ii = i->next; | |
+ free(i); | |
+} | |
+ | |
+ | |
+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 | |
+resizebarwin(Monitor *m) { | |
+ unsigned int w = m->ww; | |
+ if(showsystray && m == selmon) | |
+ w -= getsystraywidth(); | |
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); | |
+} | |
+ | |
+void | |
resizeclient(Client *c, int x, int y, int w, int h) { | |
XWindowChanges wc; | |
@@ -1412,6 +1555,18 @@ | |
} | |
void | |
+resizerequest(XEvent *e) { | |
+ XResizeRequestEvent *ev = &e->xresizerequest; | |
+ Client *i; | |
+ | |
+ if((i = wintosystrayicon(ev->window))) { | |
+ updatesystrayicongeom(i, ev->width, ev->height); | |
+ resizebarwin(selmon); | |
+ updatesystray(); | |
+ } | |
+} | |
+ | |
+void | |
restack(Monitor *m) { | |
Client *c; | |
XEvent ev; | |
@@ -1495,25 +1650,35 @@ | |
} | |
Bool | |
-sendevent(Client *c, Atom proto) { | |
+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) { | |
int n; | |
- Atom *protocols; | |
+ Atom *protocols, mt; | |
Bool exists = False; | |
XEvent ev; | |
- if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { | |
- while(!exists && n--) | |
- exists = protocols[n] == proto; | |
- XFree(protocols); | |
+ if(proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { | |
+ mt = wmatom[WMProtocols]; | |
+ if(XGetWMProtocols(dpy, w, &protocols, &n)) { | |
+ while(!exists && n--) | |
+ exists = protocols[n] == proto; | |
+ XFree(protocols); | |
+ } | |
+ } | |
+ else { | |
+ exists = True; | |
+ mt = proto; | |
} | |
if(exists) { | |
ev.type = ClientMessage; | |
- ev.xclient.window = c->win; | |
- ev.xclient.message_type = wmatom[WMProtocols]; | |
+ ev.xclient.window = w; | |
+ ev.xclient.message_type = mt; | |
ev.xclient.format = 32; | |
- ev.xclient.data.l[0] = proto; | |
- ev.xclient.data.l[1] = CurrentTime; | |
- XSendEvent(dpy, c->win, False, NoEventMask, &ev); | |
+ ev.xclient.data.l[0] = d0; | |
+ ev.xclient.data.l[1] = d1; | |
+ ev.xclient.data.l[2] = d2; | |
+ ev.xclient.data.l[3] = d3; | |
+ ev.xclient.data.l[4] = d4; | |
+ XSendEvent(dpy, w, False, mask, &ev); | |
} | |
return exists; | |
} | |
@@ -1522,7 +1687,7 @@ | |
setfocus(Client *c) { | |
if(!c->neverfocus) | |
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); | |
- sendevent(c, wmatom[WMTakeFocus]); | |
+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); | |
} | |
void | |
@@ -1602,11 +1767,17 @@ | |
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); | |
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); | |
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); | |
+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); | |
+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); | |
+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", 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); | |
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); | |
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); | |
+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); | |
+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); | |
+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); | |
/* init cursors */ | |
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); | |
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); | |
@@ -1623,6 +1794,8 @@ | |
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); | |
if(!dc.font.set) | |
XSetFont(dpy, dc.gc, dc.font.xfont->fid); | |
+ /* init system tray */ | |
+ updatesystray(); | |
/* init bars */ | |
updatebars(); | |
updatestatus(); | |
@@ -1731,7 +1904,18 @@ | |
togglebar(const Arg *arg) { | |
selmon->showbar = !selmon->showbar; | |
updatebarpos(selmon); | |
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); | |
+ resizebarwin(selmon); | |
+ if(showsystray) { | |
+ XWindowChanges wc; | |
+ if(!selmon->showbar) | |
+ wc.y = -bh; | |
+ else if(selmon->showbar) { | |
+ wc.y = 0; | |
+ if(!selmon->topbar) | |
+ wc.y = selmon->mh - bh; | |
+ } | |
+ XConfigureWindow(dpy, systray->win, CWY, &wc); | |
+ } | |
arrange(selmon); | |
} | |
@@ -1816,18 +2000,28 @@ | |
else | |
unmanage(c, False); | |
} | |
+ else if((c = wintosystrayicon(ev->window))) { | |
+ removesystrayicon(c); | |
+ resizebarwin(selmon); | |
+ updatesystray(); | |
+ } | |
} | |
void | |
updatebars(void) { | |
+ unsigned int w; | |
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), | |
+ w = m->ww; | |
+ if(showsystray && m == selmon) | |
+ w -= getsystraywidth(); | |
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), | |
CopyFromParent, DefaultVisual(dpy, screen), | |
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); | |
XDefineCursor(dpy, m->barwin, cursor[CurNormal]); | |
@@ -2011,6 +2205,104 @@ | |
} | |
void | |
+updatesystrayicongeom(Client *i, int w, int h) { | |
+ if(i) { | |
+ i->h = bh; | |
+ if(w == h) | |
+ i->w = bh; | |
+ else if(h == bh) | |
+ i->w = w; | |
+ else | |
+ i->w = (int) ((float)bh * ((float)w / (float)h)); | |
+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); | |
+ /* force icons into the systray dimenons if they don't want to */ | |
+ if(i->h > bh) { | |
+ if(i->w == i->h) | |
+ i->w = bh; | |
+ else | |
+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); | |
+ i->h = bh; | |
+ } | |
+ } | |
+} | |
+ | |
+void | |
+updatesystrayiconstate(Client *i, XPropertyEvent *ev) { | |
+ long flags; | |
+ int code = 0; | |
+ | |
+ if(!showsystray || !i || ev->atom != xatom[XembedInfo] || | |
+ !(flags = getatomprop(i, xatom[XembedInfo]))) | |
+ return; | |
+ | |
+ if(flags & XEMBED_MAPPED && !i->tags) { | |
+ i->tags = 1; | |
+ code = XEMBED_WINDOW_ACTIVATE; | |
+ XMapRaised(dpy, i->win); | |
+ setclientstate(i, NormalState); | |
+ } | |
+ else if(!(flags & XEMBED_MAPPED) && i->tags) { | |
+ i->tags = 0; | |
+ code = XEMBED_WINDOW_DEACTIVATE; | |
+ XUnmapWindow(dpy, i->win); | |
+ setclientstate(i, WithdrawnState); | |
+ } | |
+ else | |
+ return; | |
+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, | |
+ systray->win, XEMBED_EMBEDDED_VERSION); | |
+} | |
+ | |
+void | |
+updatesystray(void) { | |
+ XSetWindowAttributes wa; | |
+ Client *i; | |
+ unsigned int x = selmon->mx + selmon->mw; | |
+ unsigned int w = 1; | |
+ | |
+ if(!showsystray) | |
+ return; | |
+ if(!systray) { | |
+ /* init systray */ | |
+ if(!(systray = (Systray *)calloc(1, sizeof(Systray)))) | |
+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); | |
+ systray->win = XCreateSimpleWindow(dpy, root, x, selmon->by, w, bh, 0, 0, dc.sel[ColBG]); | |
+ wa.event_mask = ButtonPressMask | ExposureMask; | |
+ wa.override_redirect = True; | |
+ wa.background_pixmap = ParentRelative; | |
+ wa.background_pixel = dc.norm[ColBG]; | |
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask); | |
+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, | |
+ PropModeReplace, (unsigned char *)&systrayorientation, 1); | |
+ XChangeWindowAttributes(dpy, systray->win, CWEventMask | CWOverrideRedirect | CWBackPixel, &wa); | |
+ XMapRaised(dpy, systray->win); | |
+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); | |
+ if(XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { | |
+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); | |
+ XSync(dpy, False); | |
+ } | |
+ else { | |
+ fprintf(stderr, "dwm: unable to obtain system tray.\n"); | |
+ free(systray); | |
+ systray = NULL; | |
+ return; | |
+ } | |
+ } | |
+ for(w = 0, i = systray->icons; i; i = i->next) { | |
+ XMapRaised(dpy, i->win); | |
+ w += systrayspacing; | |
+ XMoveResizeWindow(dpy, i->win, (i->x = w), 0, i->w, i->h); | |
+ w += i->w; | |
+ if(i->mon != selmon) | |
+ i->mon = selmon; | |
+ } | |
+ w = w ? w + systrayspacing : 1; | |
+ x -= w; | |
+ XMoveResizeWindow(dpy, systray->win, x, selmon->by, w, bh); | |
+ XSync(dpy, False); | |
+} | |
+ | |
+void | |
updatewindowtype(Client *c) { | |
Atom state = getatomprop(c, netatom[NetWMState]); | |
Atom wtype = getatomprop(c, netatom[NetWMWindowType]); | |
@@ -2080,6 +2372,16 @@ | |
return selmon; | |
} | |
+Client * | |
+wintosystrayicon(Window w) { | |
+ Client *i = NULL; | |
+ | |
+ if(!showsystray || !w) | |
+ return i; | |
+ for(i = systray->icons; i && i->win != w; i = i->next) ; | |
+ return i; | |
+} | |
+ | |
/* 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. */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# $Id: PKGBUILD 60970 2011-12-19 21:33:58Z spupykin $ | |
# Maintainer: Sergej Pupykin <pupykin.s+arch@gmail.com> | |
# Contributor: Dag Odenhall <dag.odenhall@gmail.com> | |
# Contributor: Grigorios Bouzakis <grbzks@gmail.com> | |
pkgname=dwm | |
pkgver=6.0 | |
pkgrel=100 | |
pkgdesc="A dynamic window manager for X" | |
url="http://dwm.suckless.org" | |
arch=('i686' 'x86_64') | |
license=('MIT') | |
options=(zipman) | |
depends=('libx11' 'libxinerama') | |
install=dwm.install | |
source=(http://dl.suckless.org/dwm/dwm-$pkgver.tar.gz | |
config.h | |
dwm.desktop | |
dstatus | |
dwm-cus | |
dwm-6.0-systray.diff | |
dwm-6.0-single_window_no_border.diff | |
dwm-6.0-change_view_with_arrow.diff | |
) | |
build() { | |
cd $srcdir/$pkgname-$pkgver | |
cp $srcdir/config.h config.h | |
patch -p1 < $srcdir/dwm-6.0-systray.diff | |
patch -p1 < $srcdir/dwm-6.0-single_window_no_border.diff | |
patch -p1 < $srcdir/dwm-6.0-change_view_with_arrow.diff | |
sed -i 's/CPPFLAGS =/CPPFLAGS +=/g' config.mk | |
sed -i 's/^CFLAGS = -g/#CFLAGS += -g/g' config.mk | |
sed -i 's/^#CFLAGS = -std/CFLAGS += -std/g' config.mk | |
sed -i 's/^LDFLAGS = -g/#LDFLAGS += -g/g' config.mk | |
sed -i 's/^#LDFLAGS = -s/LDFLAGS += -s/g' config.mk | |
make X11INC=/usr/include/X11 X11LIB=/usr/lib/X11 | |
} | |
package() { | |
cd $srcdir/$pkgname-$pkgver | |
make PREFIX=/usr DESTDIR=$pkgdir install | |
install -m644 -D LICENSE $pkgdir/usr/share/licenses/$pkgname/LICENSE | |
install -m644 -D README $pkgdir/usr/share/doc/$pkgname/README | |
install -m644 -D $srcdir/dwm.desktop $pkgdir/usr/share/xsessions/dwm.desktop | |
install -m755 -D $srcdir/dwm-cus $pkgdir/usr/bin/dwm-cus | |
install -m755 -D $srcdir/dstatus $pkgdir/usr/bin/dstatus | |
} | |
md5sums=('8bb00d4142259beb11e13473b81c0857' | |
SKIP | |
'463130320651a0ecda3171321ab4dd3a' | |
'56b70a67b98b1f6ed1f8c9d0375ac5d4' | |
'890b436609f590116cb49463229ccdc1' | |
'0a527af3bcfbf628ed118bdf86521161' | |
'88d7faa3a0488ee3eb7fe029555181f2' | |
'5953584082c138f2f96bef1233bd2a43') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment