Advertisement
Guest User

Untitled

a guest
Nov 26th, 2015
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.54 KB | None | 0 0
  1. diff --git a/config.def.h b/config.def.h
  2. index 7054c06..c6cf7ee 100644
  3. --- a/config.def.h
  4. +++ b/config.def.h
  5. @@ -1,52 +1,65 @@
  6. /* See LICENSE file for copyright and license details. */
  7. +#include <X11/XF86keysym.h>
  8.  
  9. /* appearance */
  10. static const char *fonts[] = {
  11. - "monospace:size=10"
  12. + "Terminus:pixelsize=9"
  13. };
  14. -static const char dmenufont[] = "monospace:size=10";
  15. -static const char normbordercolor[] = "#444444";
  16. -static const char normbgcolor[] = "#222222";
  17. -static const char normfgcolor[] = "#bbbbbb";
  18. -static const char selbordercolor[] = "#005577";
  19. -static const char selbgcolor[] = "#005577";
  20. -static const char selfgcolor[] = "#eeeeee";
  21. -static const unsigned int borderpx = 1; /* border pixel of windows */
  22. +static const char dmenufont[] = "Terminus:pixelsize=9";
  23. +static const char normbordercolor[] = "#fdf6e3";
  24. +static const char normbgcolor[] = "#002b36";
  25. +static const char normfgcolor[] = "#93a1a1";
  26. +static const char selbordercolor[] = "#002b36";
  27. +static const char selbgcolor[] = "#586e75";
  28. +static const char selfgcolor[] = "#fdf6e3";
  29. +static const char urgbordercolor[] = "#dc322f";
  30. +static const unsigned int borderpx = 3; /* border pixel of windows */
  31. static const unsigned int snap = 32; /* snap pixel */
  32. +static const unsigned int systraypinning = 1; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
  33. +static const unsigned int systrayspacing = 1; /* systray spacing */
  34. +static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, 0: display systray on the last monitor*/
  35. +static const int showsystray = 1; /* 0 means no systray */
  36. static const int showbar = 1; /* 0 means no bar */
  37. static const int topbar = 1; /* 0 means bottom bar */
  38.  
  39. /* tagging */
  40. -static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
  41. +static const char *tags[] = { "term", "web", "ide", "doc", "fm", "media", "gfx", "bt" };
  42.  
  43. static const Rule rules[] = {
  44. - /* xprop(1):
  45. - * WM_CLASS(STRING) = instance, class
  46. - * WM_NAME(STRING) = title
  47. - */
  48. - /* class instance title tags mask isfloating monitor */
  49. - { "Gimp", NULL, NULL, 0, 1, -1 },
  50. - { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
  51. + /* class instance title tags mask isfloating ispermanent monitor */
  52. + { "Display", NULL, NULL, 0, True, False, -1 },
  53. + { "feh", NULL, NULL, 0, True, False, -1 },
  54. + { "Firefox", NULL, NULL, 1 << 1, False, False, -1 },
  55. + { "Jumanji", NULL, NULL, 1 << 1, False, False, -1 },
  56. + { "QtCreator",NULL, NULL, 1 << 2, False, False, -1 },
  57. + { "Zathura", NULL, NULL, 1 << 3, False, False, -1 },
  58. + { "Thunar", NULL, NULL, 1 << 4, False, False, -1 },
  59. + { "mpv", NULL, NULL, 1 << 5, False, -1 },
  60. + { "Blender", NULL, NULL, 1 << 6, False, -1 },
  61. + { "Gimp", NULL, NULL, 1 << 6, False, -1 },
  62. + { "Transmission-gtk",NULL,NULL, 1 << 7, False, -1 },
  63. + { "Deluge", NULL, NULL, 1 << 7, False, -1 },
  64. };
  65.  
  66. /* layout(s) */
  67. -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
  68. +static const float mfact = 0.65; /* factor of master area size [0.05..0.95] */
  69. static const int nmaster = 1; /* number of clients in master area */
  70. -static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
  71. +static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
  72.  
  73. static const Layout layouts[] = {
  74. /* symbol arrange function */
  75. - { "[]=", tile }, /* first entry is default */
  76. - { "><>", NULL }, /* no layout function means floating behavior */
  77. - { "[M]", monocle },
  78. + { "T", tile }, /* first entry is default */
  79. + { "F", NULL }, /* no layout function means floating behavior */
  80. + { "M", monocle },
  81. + { "G", htile },
  82. };
  83.  
  84. /* key definitions */
  85. -#define MODKEY Mod1Mask
  86. +#define MODKEY Mod4Mask
  87. #define TAGKEYS(KEY,TAG) \
  88. - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
  89. + { MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \
  90. { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
  91. - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
  92. + { MODKEY|ShiftMask, KEY, combotag, {.ui = 1 << TAG} }, \
  93. { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
  94.  
  95. /* helper for spawning shell commands in the pre dwm-5.0 fashion */
  96. @@ -55,25 +68,34 @@ static const Layout layouts[] = {
  97. /* commands */
  98. static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
  99. static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
  100. -static const char *termcmd[] = { "st", NULL };
  101. +static const char *termcmd[] = { "urxvtc", NULL };
  102. +static const char *webcmd[] = { "firefox", NULL };
  103. +static const char *fmcmd[] = { "thunar", NULL };
  104. +static const char *logoutcmd[] = { "xfce4-session-logout", NULL );
  105.  
  106. static Key keys[] = {
  107. /* modifier key function argument */
  108. { MODKEY, XK_p, spawn, {.v = dmenucmd } },
  109. - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
  110. + { MODKEY, XK_a, spawn, {.v = termcmd } },
  111. + { MODKEY, XK_w, spawn, {.v = webcmd } },
  112. + { MODKEY, XK_q, spawn, {.v = fmcmd } },
  113. { MODKEY, XK_b, togglebar, {0} },
  114. { MODKEY, XK_j, focusstack, {.i = +1 } },
  115. { MODKEY, XK_k, focusstack, {.i = -1 } },
  116. { MODKEY, XK_i, incnmaster, {.i = +1 } },
  117. - { MODKEY, XK_d, incnmaster, {.i = -1 } },
  118. + { MODKEY, XK_u, incnmaster, {.i = -1 } },
  119. { MODKEY, XK_h, setmfact, {.f = -0.05} },
  120. { MODKEY, XK_l, setmfact, {.f = +0.05} },
  121. + { MODKEY, XK_o, setcfact, {.f = +0.25} },
  122. + { MODKEY, XK_y, setcfact, {.f = -0.25} },
  123. + { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
  124. { MODKEY, XK_Return, zoom, {0} },
  125. { MODKEY, XK_Tab, view, {0} },
  126. { MODKEY|ShiftMask, XK_c, killclient, {0} },
  127. { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
  128. { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
  129. { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
  130. + { MODKEY, XK_g, setlayout, {.v = &layouts[3]} },
  131. { MODKEY, XK_space, setlayout, {0} },
  132. { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
  133. { MODKEY, XK_0, view, {.ui = ~0 } },
  134. @@ -90,8 +112,7 @@ static Key keys[] = {
  135. TAGKEYS( XK_6, 5)
  136. TAGKEYS( XK_7, 6)
  137. TAGKEYS( XK_8, 7)
  138. - TAGKEYS( XK_9, 8)
  139. - { MODKEY|ShiftMask, XK_q, quit, {0} },
  140. + { MODKEY|ShiftMask, XK_q, spawn, {.v = logoutcmd } },
  141. };
  142.  
  143. /* button definitions */
  144. diff --git a/dwm.c b/dwm.c
  145. index 0362114..89aadd8 100644
  146. --- a/dwm.c
  147. +++ b/dwm.c
  148. @@ -49,7 +49,8 @@
  149. #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
  150. #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
  151. * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
  152. -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
  153. +#define ISVISIBLEONTAG(C, T) ((C->tags & T))
  154. +#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
  155. #define LENGTH(X) (sizeof X / sizeof X[0])
  156. #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
  157. #define WIDTH(X) ((X)->w + 2 * (X)->bw)
  158. @@ -57,12 +58,30 @@
  159. #define TAGMASK ((1 << LENGTH(tags)) - 1)
  160. #define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
  161.  
  162. +#define SYSTEM_TRAY_REQUEST_DOCK 0
  163. +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
  164. +
  165. +/* XEMBED messages */
  166. +#define XEMBED_EMBEDDED_NOTIFY 0
  167. +#define XEMBED_WINDOW_ACTIVATE 1
  168. +#define XEMBED_FOCUS_IN 4
  169. +#define XEMBED_MODALITY_ON 10
  170. +
  171. +#define XEMBED_MAPPED (1 << 0)
  172. +#define XEMBED_WINDOW_ACTIVATE 1
  173. +#define XEMBED_WINDOW_DEACTIVATE 2
  174. +
  175. +#define VERSION_MAJOR 0
  176. +#define VERSION_MINOR 0
  177. +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
  178. +
  179. /* enums */
  180. enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
  181. enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
  182. -enum { NetSupported, NetWMName, NetWMState,
  183. - NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  184. - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
  185. +enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
  186. + NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  187. + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
  188. +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
  189. enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
  190. enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
  191. ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
  192. @@ -87,12 +106,13 @@ typedef struct Client Client;
  193. struct Client {
  194. char name[256];
  195. float mina, maxa;
  196. + float cfact;
  197. int x, y, w, h;
  198. int oldx, oldy, oldw, oldh;
  199. int basew, baseh, incw, inch, maxw, maxh, minw, minh;
  200. int bw, oldbw;
  201. unsigned int tags;
  202. - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
  203. + int isfixed, ispermanent, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
  204. Client *next;
  205. Client *snext;
  206. Monitor *mon;
  207. @@ -111,6 +131,7 @@ typedef struct {
  208. void (*arrange)(Monitor *);
  209. } Layout;
  210.  
  211. +typedef struct Pertag Pertag;
  212. struct Monitor {
  213. char ltsymbol[16];
  214. float mfact;
  215. @@ -130,6 +151,7 @@ struct Monitor {
  216. Monitor *next;
  217. Window barwin;
  218. const Layout *lt[2];
  219. + Pertag *pertag;
  220. };
  221.  
  222. typedef struct {
  223. @@ -138,15 +160,23 @@ typedef struct {
  224. const char *title;
  225. unsigned int tags;
  226. int isfloating;
  227. + int ispermanent;
  228. int monitor;
  229. } Rule;
  230.  
  231. +typedef struct Systray Systray;
  232. +struct Systray {
  233. + Window win;
  234. + Client *icons;
  235. +};
  236. +
  237. /* function declarations */
  238. static void applyrules(Client *c);
  239. static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
  240. static void arrange(Monitor *m);
  241. static void arrangemon(Monitor *m);
  242. static void attach(Client *c);
  243. +static void attachaside(Client *c);
  244. static void attachstack(Client *c);
  245. static void buttonpress(XEvent *e);
  246. static void checkotherwm(void);
  247. @@ -162,6 +192,7 @@ static void destroynotify(XEvent *e);
  248. static void detach(Client *c);
  249. static void detachstack(Client *c);
  250. static Monitor *dirtomon(int dir);
  251. +static void dmenuspawn(const Arg *arg);
  252. static void drawbar(Monitor *m);
  253. static void drawbars(void);
  254. static void enternotify(XEvent *e);
  255. @@ -170,8 +201,10 @@ static void focus(Client *c);
  256. static void focusin(XEvent *e);
  257. static void focusmon(const Arg *arg);
  258. static void focusstack(const Arg *arg);
  259. +static Atom getatomprop(Client *c, Atom prop);
  260. static int getrootptr(int *x, int *y);
  261. static long getstate(Window w);
  262. +static unsigned int getsystraywidth();
  263. static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
  264. static void grabbuttons(Client *c, int focused);
  265. static void grabkeys(void);
  266. @@ -184,31 +217,38 @@ static void maprequest(XEvent *e);
  267. static void monocle(Monitor *m);
  268. static void motionnotify(XEvent *e);
  269. static void movemouse(const Arg *arg);
  270. +static Client *nexttagged(Client *c);
  271. static Client *nexttiled(Client *c);
  272. static void pop(Client *);
  273. static void propertynotify(XEvent *e);
  274. static void quit(const Arg *arg);
  275. static Monitor *recttomon(int x, int y, int w, int h);
  276. +static void removesystrayicon(Client *i);
  277. static void resize(Client *c, int x, int y, int w, int h, int interact);
  278. +static void resizebarwin(Monitor *m);
  279. static void resizeclient(Client *c, int x, int y, int w, int h);
  280. static void resizemouse(const Arg *arg);
  281. +static void resizerequest(XEvent *e);
  282. static void restack(Monitor *m);
  283. static void run(void);
  284. static void scan(void);
  285. -static int sendevent(Client *c, Atom proto);
  286. +static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
  287. static void sendmon(Client *c, Monitor *m);
  288. static void setclientstate(Client *c, long state);
  289. static void setfocus(Client *c);
  290. static void setfullscreen(Client *c, int fullscreen);
  291. static void setlayout(const Arg *arg);
  292. +static void setcfact(const Arg *arg);
  293. static void setmfact(const Arg *arg);
  294. static void setup(void);
  295. static void showhide(Client *c);
  296. static void sigchld(int unused);
  297. static void spawn(const Arg *arg);
  298. +static Monitor *systraytomon(Monitor *m);
  299. static void tag(const Arg *arg);
  300. static void tagmon(const Arg *arg);
  301. static void tile(Monitor *);
  302. +static void htile(Monitor *);
  303. static void togglebar(const Arg *arg);
  304. static void togglefloating(const Arg *arg);
  305. static void toggletag(const Arg *arg);
  306. @@ -223,18 +263,30 @@ static void updateclientlist(void);
  307. static void updatenumlockmask(void);
  308. static void updatesizehints(Client *c);
  309. static void updatestatus(void);
  310. +static void updatesystray(void);
  311. +static void updatesystrayicongeom(Client *i, int w, int h);
  312. +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
  313. static void updatewindowtype(Client *c);
  314. static void updatetitle(Client *c);
  315. static void updatewmhints(Client *c);
  316. static void view(const Arg *arg);
  317. +static void warp(const Client *c);
  318. static Client *wintoclient(Window w);
  319. static Monitor *wintomon(Window w);
  320. +static Client *wintosystrayicon(Window w);
  321. static int xerror(Display *dpy, XErrorEvent *ee);
  322. static int xerrordummy(Display *dpy, XErrorEvent *ee);
  323. static int xerrorstart(Display *dpy, XErrorEvent *ee);
  324. static void zoom(const Arg *arg);
  325.  
  326. +static void keyrelease(XEvent *e);
  327. +static void combotag(const Arg *arg);
  328. +static void comboview(const Arg *arg);
  329. +
  330. +
  331. /* variables */
  332. +static Systray *systray = NULL;
  333. +static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
  334. static const char broken[] = "broken";
  335. static char stext[256];
  336. static int screen;
  337. @@ -244,6 +296,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *);
  338. static unsigned int numlockmask = 0;
  339. static void (*handler[LASTEvent]) (XEvent *) = {
  340. [ButtonPress] = buttonpress,
  341. + [ButtonRelease] = keyrelease,
  342. [ClientMessage] = clientmessage,
  343. [ConfigureRequest] = configurerequest,
  344. [ConfigureNotify] = configurenotify,
  345. @@ -251,14 +304,16 @@ static void (*handler[LASTEvent]) (XEvent *) = {
  346. [EnterNotify] = enternotify,
  347. [Expose] = expose,
  348. [FocusIn] = focusin,
  349. + [KeyRelease] = keyrelease,
  350. [KeyPress] = keypress,
  351. [MappingNotify] = mappingnotify,
  352. [MapRequest] = maprequest,
  353. [MotionNotify] = motionnotify,
  354. [PropertyNotify] = propertynotify,
  355. + [ResizeRequest] = resizerequest,
  356. [UnmapNotify] = unmapnotify
  357. };
  358. -static Atom wmatom[WMLast], netatom[NetLast];
  359. +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
  360. static int running = 1;
  361. static Cur *cursor[CurLast];
  362. static ClrScheme scheme[SchemeLast];
  363. @@ -270,10 +325,54 @@ static Window root;
  364. /* configuration, allows nested code to access above variables */
  365. #include "config.h"
  366.  
  367. +struct Pertag {
  368. + unsigned int curtag, prevtag; /* current and previous tag */
  369. + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
  370. + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
  371. + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
  372. + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
  373. +};
  374. +
  375. /* compile-time check if all tags fit into an unsigned int bit array. */
  376. struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
  377.  
  378. /* function implementations */
  379. +static int combo = 0;
  380. +
  381. +void
  382. +keyrelease(XEvent *e) {
  383. + combo = 0;
  384. +}
  385. +
  386. +void
  387. +combotag(const Arg *arg) {
  388. + if(selmon->sel && arg->ui & TAGMASK) {
  389. + if (combo) {
  390. + selmon->sel->tags |= arg->ui & TAGMASK;
  391. + } else {
  392. + combo = 1;
  393. + selmon->sel->tags = arg->ui & TAGMASK;
  394. + }
  395. + focus(NULL);
  396. + arrange(selmon);
  397. + }
  398. +}
  399. +
  400. +void
  401. +comboview(const Arg *arg) {
  402. + unsigned newtags = arg->ui & TAGMASK;
  403. + if (combo) {
  404. + selmon->tagset[selmon->seltags] |= newtags;
  405. + } else {
  406. + selmon->seltags ^= 1; /*toggle tagset*/
  407. + combo = 1;
  408. + if (newtags)
  409. + selmon->tagset[selmon->seltags] = newtags;
  410. + }
  411. + focus(NULL);
  412. + arrange(selmon);
  413. +}
  414. +
  415. void
  416. applyrules(Client *c)
  417. {
  418. @@ -297,6 +396,7 @@ applyrules(Client *c)
  419. && (!r->instance || strstr(instance, r->instance)))
  420. {
  421. c->isfloating = r->isfloating;
  422. + c->ispermanent = r->ispermanent;
  423. c->tags |= r->tags;
  424. for (m = mons; m && m->num != r->monitor; m = m->next);
  425. if (m)
  426. @@ -310,6 +410,34 @@ applyrules(Client *c)
  427. c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
  428. }
  429.  
  430. +void
  431. +adjustborders(Monitor *m) {
  432. + Client *c, *l = NULL;
  433. + int visible = 0;
  434. +
  435. + for(c = m->clients; c; c = c->next) {
  436. + if (ISVISIBLE(c) && !c->isfloating && m->lt[m->sellt]->arrange) {
  437. + if (m->lt[m->sellt]->arrange == monocle) {
  438. + visible = 1;
  439. + c->oldbw = c->bw;
  440. + c->bw = 0;
  441. + } else {
  442. + visible++;
  443. + c->oldbw = c->bw;
  444. + c->bw = borderpx;
  445. + }
  446. +
  447. + l = c;
  448. + }
  449. + }
  450. +
  451. + if (l && visible == 1 && l->bw) {
  452. + l->oldbw = l->bw;
  453. + l->bw = 0;
  454. + resizeclient(l, l->x, l->y, l->w, l->h);
  455. + }
  456. +}
  457. +
  458. int
  459. applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
  460. {
  461. @@ -379,10 +507,13 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
  462. void
  463. arrange(Monitor *m)
  464. {
  465. - if (m)
  466. + if (m) {
  467. + adjustborders(m);
  468. showhide(m->stack);
  469. - else for (m = mons; m; m = m->next)
  470. + } else for (m = mons; m; m = m->next) {
  471. + adjustborders(m);
  472. showhide(m->stack);
  473. + }
  474. if (m) {
  475. arrangemon(m);
  476. restack(m);
  477. @@ -406,6 +537,17 @@ attach(Client *c)
  478. }
  479.  
  480. void
  481. +attachaside(Client *c) {
  482. + Client *at = nexttagged(c);
  483. + if(!at) {
  484. + attach(c);
  485. + return;
  486. + }
  487. + c->next = at->next;
  488. + at->next = c;
  489. +}
  490. +
  491. +void
  492. attachstack(Client *c)
  493. {
  494. c->snext = c->mon->stack;
  495. @@ -479,6 +621,11 @@ cleanup(void)
  496. XUngrabKey(dpy, AnyKey, AnyModifier, root);
  497. while (mons)
  498. cleanupmon(mons);
  499. + if (showsystray) {
  500. + XUnmapWindow(dpy, systray->win);
  501. + XDestroyWindow(dpy, systray->win);
  502. + free(systray);
  503. + }
  504. for (i = 0; i < CurLast; i++)
  505. drw_cur_free(drw, cursor[i]);
  506. for (i = 0; i < SchemeLast; i++) {
  507. @@ -524,9 +671,50 @@ clearurgent(Client *c)
  508. void
  509. clientmessage(XEvent *e)
  510. {
  511. + XWindowAttributes wa;
  512. + XSetWindowAttributes swa;
  513. XClientMessageEvent *cme = &e->xclient;
  514. Client *c = wintoclient(cme->window);
  515.  
  516. + if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
  517. + /* add systray icons */
  518. + if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
  519. + if (!(c = (Client *)calloc(1, sizeof(Client))))
  520. + die("fatal: could not malloc() %u bytes\n", sizeof(Client));
  521. + c->win = cme->data.l[2];
  522. + c->mon = selmon;
  523. + c->next = systray->icons;
  524. + systray->icons = c;
  525. + XGetWindowAttributes(dpy, c->win, &wa);
  526. + c->x = c->oldx = c->y = c->oldy = 0;
  527. + c->w = c->oldw = wa.width;
  528. + c->h = c->oldh = wa.height;
  529. + c->oldbw = wa.border_width;
  530. + c->bw = 0;
  531. + c->isfloating = True;
  532. + /* reuse tags field as mapped status */
  533. + c->tags = 1;
  534. + updatesizehints(c);
  535. + updatesystrayicongeom(c, wa.width, wa.height);
  536. + XAddToSaveSet(dpy, c->win);
  537. + XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
  538. + XReparentWindow(dpy, c->win, systray->win, 0, 0);
  539. + /* use parents background color */
  540. + swa.background_pixel = scheme[SchemeNorm].bg->pix;
  541. + XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
  542. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  543. + /* FIXME not sure if I have to send these events, too */
  544. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  545. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  546. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  547. + XSync(dpy, False);
  548. + resizebarwin(selmon);
  549. + updatesystray();
  550. + setclientstate(c, NormalState);
  551. + }
  552. + return;
  553. + }
  554. +
  555. if (!c)
  556. return;
  557. if (cme->message_type == netatom[NetWMState]) {
  558. @@ -577,7 +765,7 @@ configurenotify(XEvent *e)
  559. drw_resize(drw, sw, bh);
  560. updatebars();
  561. for (m = mons; m; m = m->next)
  562. - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
  563. + resizebarwin(m);
  564. focus(NULL);
  565. arrange(NULL);
  566. }
  567. @@ -640,6 +828,7 @@ Monitor *
  568. createmon(void)
  569. {
  570. Monitor *m;
  571. + int i;
  572.  
  573. m = ecalloc(1, sizeof(Monitor));
  574. m->tagset[0] = m->tagset[1] = 1;
  575. @@ -650,6 +839,21 @@ createmon(void)
  576. m->lt[0] = &layouts[0];
  577. m->lt[1] = &layouts[1 % LENGTH(layouts)];
  578. strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
  579. + if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
  580. + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
  581. + m->pertag->curtag = m->pertag->prevtag = 1;
  582. + for (i=0; i <= LENGTH(tags); i++) {
  583. + /* init nmaster */
  584. + m->pertag->nmasters[i] = m->nmaster;
  585. +
  586. + /* init mfacts */
  587. + m->pertag->mfacts[i] = m->mfact;
  588. +
  589. + /* init layouts */
  590. + m->pertag->ltidxs[i][0] = m->lt[0];
  591. + m->pertag->ltidxs[i][1] = m->lt[1];
  592. + m->pertag->sellts[i] = m->sellt;
  593. + }
  594. return m;
  595. }
  596.  
  597. @@ -661,6 +865,11 @@ destroynotify(XEvent *e)
  598.  
  599. if ((c = wintoclient(ev->window)))
  600. unmanage(c, 1);
  601. + else if ((c = wintosystrayicon(ev->window))) {
  602. + removesystrayicon(c);
  603. + resizebarwin(selmon);
  604. + updatesystray();
  605. + }
  606. }
  607.  
  608. void
  609. @@ -702,6 +911,17 @@ dirtomon(int dir)
  610. }
  611.  
  612. void
  613. +dmenuspawn(const Arg *arg) {
  614. + char monstr[2] = "0";
  615. + const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-m", monstr, "-nb",
  616. + normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf",
  617. + selfgcolor, NULL };
  618. + Arg a = { .v = dmenucmd };
  619. + monstr[0] = '0' + selmon->num;
  620. + spawn(&a);
  621. +}
  622. +
  623. +void
  624. drawbar(Monitor *m)
  625. {
  626. int x, xx, w, dx;
  627. @@ -710,6 +930,7 @@ drawbar(Monitor *m)
  628.  
  629. dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
  630.  
  631. + resizebarwin(m);
  632. for (c = m->clients; c; c = c->next) {
  633. occ |= c->tags;
  634. if (c->isurgent)
  635. @@ -732,6 +953,9 @@ drawbar(Monitor *m)
  636. if (m == selmon) { /* status is only drawn on selected monitor */
  637. w = TEXTW(stext);
  638. x = m->ww - w;
  639. + if (showsystray && m == systraytomon(m)) {
  640. + x -= getsystraywidth();
  641. + }
  642. if (x < xx) {
  643. x = xx;
  644. w = m->ww - xx;
  645. @@ -760,6 +984,7 @@ drawbars(void)
  646.  
  647. for (m = mons; m; m = m->next)
  648. drawbar(m);
  649. + updatesystray();
  650. }
  651.  
  652. void
  653. @@ -787,8 +1012,11 @@ expose(XEvent *e)
  654. Monitor *m;
  655. XExposeEvent *ev = &e->xexpose;
  656.  
  657. - if (ev->count == 0 && (m = wintomon(ev->window)))
  658. + if (ev->count == 0 && (m = wintomon(ev->window))) {
  659. drawbar(m);
  660. + if (m == selmon)
  661. + updatesystray();
  662. + }
  663. }
  664.  
  665. void
  666. @@ -840,6 +1068,7 @@ focusmon(const Arg *arg)
  667. in gedit and anjuta */
  668. selmon = m;
  669. focus(NULL);
  670. + warp(selmon->sel);
  671. }
  672.  
  673. void
  674. @@ -875,10 +1104,17 @@ getatomprop(Client *c, Atom prop)
  675. unsigned long dl;
  676. unsigned char *p = NULL;
  677. Atom da, atom = None;
  678. + /* FIXME getatomprop should return the number of items and a pointer to
  679. + * the stored data instead of this workaround */
  680. + Atom req = XA_ATOM;
  681. + if (prop == xatom[XembedInfo])
  682. + req = xatom[XembedInfo];
  683.  
  684. - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
  685. + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
  686. &da, &di, &dl, &dl, &p) == Success && p) {
  687. atom = *(Atom *)p;
  688. + if (da == xatom[XembedInfo] && dl == 2)
  689. + atom = ((Atom *)p)[1];
  690. XFree(p);
  691. }
  692. return atom;
  693. @@ -912,6 +1148,15 @@ getstate(Window w)
  694. return result;
  695. }
  696.  
  697. +unsigned int
  698. +getsystraywidth() {
  699. + unsigned int w = 0;
  700. + Client *i;
  701. + if (showsystray)
  702. + for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
  703. + return w ? w + systrayspacing : 1;
  704. +}
  705. +
  706. int
  707. gettextprop(Window w, Atom atom, char *text, unsigned int size)
  708. {
  709. @@ -981,7 +1226,7 @@ grabkeys(void)
  710. void
  711. incnmaster(const Arg *arg)
  712. {
  713. - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
  714. + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
  715. arrange(selmon);
  716. }
  717.  
  718. @@ -1016,9 +1261,9 @@ keypress(XEvent *e)
  719. void
  720. killclient(const Arg *arg)
  721. {
  722. - if (!selmon->sel)
  723. + if(!selmon->sel || selmon->sel->ispermanent)
  724. return;
  725. - if (!sendevent(selmon->sel, wmatom[WMDelete])) {
  726. + if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
  727. XGrabServer(dpy);
  728. XSetErrorHandler(xerrordummy);
  729. XSetCloseDownMode(dpy, DestroyAll);
  730. @@ -1052,6 +1297,7 @@ manage(Window w, XWindowAttributes *wa)
  731. c->w = c->oldw = wa->width;
  732. c->h = c->oldh = wa->height;
  733. c->oldbw = wa->border_width;
  734. + c->cfact = 1.0;
  735.  
  736. if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
  737. c->x = c->mon->mx + c->mon->mw - WIDTH(c);
  738. @@ -1061,7 +1307,20 @@ manage(Window w, XWindowAttributes *wa)
  739. /* only fix client y-offset, if the client center might cover the bar */
  740. c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
  741. && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
  742. - c->bw = borderpx;
  743. +
  744. + updatewindowtype(c);
  745. + if (c->isfloating) {
  746. + c->bw = c->isfullscreen ? 0 : borderpx;
  747. + } else {
  748. + c->bw = 0;
  749. + for(t = c->mon->clients; t; t = c->next) {
  750. + if (!t->isfloating && c != t && c->tags & t->tags) {
  751. + c->bw = borderpx;
  752. + break;
  753. + }
  754. + }
  755. + adjustborders(c->mon);
  756. + }
  757.  
  758. wc.border_width = c->bw;
  759. XConfigureWindow(dpy, w, CWBorderWidth, &wc);
  760. @@ -1076,7 +1335,7 @@ manage(Window w, XWindowAttributes *wa)
  761. c->isfloating = c->oldstate = trans != None || c->isfixed;
  762. if (c->isfloating)
  763. XRaiseWindow(dpy, c->win);
  764. - attach(c);
  765. + attachaside(c);
  766. attachstack(c);
  767. XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
  768. (unsigned char *) &(c->win), 1);
  769. @@ -1105,6 +1364,12 @@ maprequest(XEvent *e)
  770. {
  771. static XWindowAttributes wa;
  772. XMapRequestEvent *ev = &e->xmaprequest;
  773. + Client *i;
  774. + if ((i = wintosystrayicon(ev->window))) {
  775. + sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
  776. + resizebarwin(selmon);
  777. + updatesystray();
  778. + }
  779.  
  780. if (!XGetWindowAttributes(dpy, ev->window, &wa))
  781. return;
  782. @@ -1210,6 +1475,16 @@ movemouse(const Arg *arg)
  783. }
  784.  
  785. Client *
  786. +nexttagged(Client *c) {
  787. + Client *walked = c->mon->clients;
  788. + for(;
  789. + walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags));
  790. + walked = walked->next
  791. + );
  792. + return walked;
  793. +}
  794. +
  795. +Client *
  796. nexttiled(Client *c)
  797. {
  798. for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
  799. @@ -1232,6 +1507,16 @@ propertynotify(XEvent *e)
  800. Window trans;
  801. XPropertyEvent *ev = &e->xproperty;
  802.  
  803. + if ((c = wintosystrayicon(ev->window))) {
  804. + if (ev->atom == XA_WM_NORMAL_HINTS) {
  805. + updatesizehints(c);
  806. + updatesystrayicongeom(c, c->w, c->h);
  807. + }
  808. + else
  809. + updatesystrayiconstate(c, ev);
  810. + resizebarwin(selmon);
  811. + updatesystray();
  812. + }
  813. if ((ev->window == root) && (ev->atom == XA_WM_NAME))
  814. updatestatus();
  815. else if (ev->state == PropertyDelete)
  816. @@ -1283,6 +1568,19 @@ recttomon(int x, int y, int w, int h)
  817. }
  818.  
  819. void
  820. +removesystrayicon(Client *i) {
  821. + Client **ii;
  822. +
  823. + if (!showsystray || !i)
  824. + return;
  825. + for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
  826. + if (ii)
  827. + *ii = i->next;
  828. + free(i);
  829. +}
  830. +
  831. +
  832. +void
  833. resize(Client *c, int x, int y, int w, int h, int interact)
  834. {
  835. if (applysizehints(c, &x, &y, &w, &h, interact))
  836. @@ -1290,6 +1588,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
  837. }
  838.  
  839. void
  840. +resizebarwin(Monitor *m) {
  841. + unsigned int w = m->ww;
  842. + if (showsystray && m == systraytomon(m))
  843. + w -= getsystraywidth();
  844. + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
  845. +}
  846. +
  847. +void
  848. resizeclient(Client *c, int x, int y, int w, int h)
  849. {
  850. XWindowChanges wc;
  851. @@ -1362,6 +1668,18 @@ resizemouse(const Arg *arg)
  852. }
  853.  
  854. void
  855. +resizerequest(XEvent *e) {
  856. + XResizeRequestEvent *ev = &e->xresizerequest;
  857. + Client *i;
  858. +
  859. + if ((i = wintosystrayicon(ev->window))) {
  860. + updatesystrayicongeom(i, ev->width, ev->height);
  861. + resizebarwin(selmon);
  862. + updatesystray();
  863. + }
  864. +}
  865. +
  866. +void
  867. restack(Monitor *m)
  868. {
  869. Client *c;
  870. @@ -1384,6 +1702,8 @@ restack(Monitor *m)
  871. }
  872. XSync(dpy, False);
  873. while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  874. + if (m == selmon && (m->tagset[m->seltags] & m->sel->tags))
  875. + warp(m->sel);
  876. }
  877.  
  878. void
  879. @@ -1434,7 +1754,7 @@ sendmon(Client *c, Monitor *m)
  880. detachstack(c);
  881. c->mon = m;
  882. c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
  883. - attach(c);
  884. + attachaside(c);
  885. attachstack(c);
  886. focus(NULL);
  887. arrange(NULL);
  888. @@ -1450,26 +1770,36 @@ setclientstate(Client *c, long state)
  889. }
  890.  
  891. int
  892. -sendevent(Client *c, Atom proto)
  893. +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
  894. {
  895. int n;
  896. - Atom *protocols;
  897. + Atom *protocols, mt;
  898. int exists = 0;
  899. XEvent ev;
  900.  
  901. - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
  902. - while (!exists && n--)
  903. - exists = protocols[n] == proto;
  904. - XFree(protocols);
  905. + if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
  906. + mt = wmatom[WMProtocols];
  907. + if (XGetWMProtocols(dpy, w, &protocols, &n)) {
  908. + while(!exists && n--)
  909. + exists = protocols[n] == proto;
  910. + XFree(protocols);
  911. + }
  912. + }
  913. + else {
  914. + exists = True;
  915. + mt = proto;
  916. }
  917. if (exists) {
  918. ev.type = ClientMessage;
  919. - ev.xclient.window = c->win;
  920. - ev.xclient.message_type = wmatom[WMProtocols];
  921. + ev.xclient.window = w;
  922. + ev.xclient.message_type = mt;
  923. ev.xclient.format = 32;
  924. - ev.xclient.data.l[0] = proto;
  925. - ev.xclient.data.l[1] = CurrentTime;
  926. - XSendEvent(dpy, c->win, False, NoEventMask, &ev);
  927. + ev.xclient.data.l[0] = d0;
  928. + ev.xclient.data.l[1] = d1;
  929. + ev.xclient.data.l[2] = d2;
  930. + ev.xclient.data.l[3] = d3;
  931. + ev.xclient.data.l[4] = d4;
  932. + XSendEvent(dpy, w, False, mask, &ev);
  933. }
  934. return exists;
  935. }
  936. @@ -1483,7 +1813,7 @@ setfocus(Client *c)
  937. XA_WINDOW, 32, PropModeReplace,
  938. (unsigned char *) &(c->win), 1);
  939. }
  940. - sendevent(c, wmatom[WMTakeFocus]);
  941. + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
  942. }
  943.  
  944. void
  945. @@ -1517,10 +1847,13 @@ setfullscreen(Client *c, int fullscreen)
  946. void
  947. setlayout(const Arg *arg)
  948. {
  949. - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
  950. - selmon->sellt ^= 1;
  951. + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
  952. + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
  953. + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
  954. + }
  955. if (arg && arg->v)
  956. - selmon->lt[selmon->sellt] = (Layout *)arg->v;
  957. + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
  958. + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
  959. strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
  960. if (selmon->sel)
  961. arrange(selmon);
  962. @@ -1528,6 +1861,23 @@ setlayout(const Arg *arg)
  963. drawbar(selmon);
  964. }
  965.  
  966. +void setcfact(const Arg *arg) {
  967. + float f;
  968. + Client *c;
  969. +
  970. + c = selmon->sel;
  971. +
  972. + if(!arg || !c || !selmon->lt[selmon->sellt]->arrange)
  973. + return;
  974. + f = arg->f + c->cfact;
  975. + if(arg->f == 0.0)
  976. + f = 1.0;
  977. + else if(f < 0.25 || f > 4.0)
  978. + return;
  979. + c->cfact = f;
  980. + arrange(selmon);
  981. +}
  982. +
  983. /* arg > 1.0 will set mfact absolutly */
  984. void
  985. setmfact(const Arg *arg)
  986. @@ -1539,7 +1889,7 @@ setmfact(const Arg *arg)
  987. f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
  988. if (f < 0.1 || f > 0.9)
  989. return;
  990. - selmon->mfact = f;
  991. + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
  992. arrange(selmon);
  993. }
  994.  
  995. @@ -1569,12 +1919,18 @@ setup(void)
  996. wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
  997. netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
  998. netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  999. + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
  1000. + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
  1001. + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
  1002. netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  1003. netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
  1004. netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
  1005. netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
  1006. netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  1007. netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
  1008. + xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
  1009. + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
  1010. + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
  1011. /* init cursors */
  1012. cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
  1013. cursor[CurResize] = drw_cur_create(drw, XC_sizing);
  1014. @@ -1586,6 +1942,8 @@ setup(void)
  1015. scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor);
  1016. scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor);
  1017. scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor);
  1018. + /* init system tray */
  1019. + updatesystray();
  1020. /* init bars */
  1021. updatebars();
  1022. updatestatus();
  1023. @@ -1645,6 +2003,22 @@ spawn(const Arg *arg)
  1024. }
  1025. }
  1026.  
  1027. +Monitor *
  1028. +systraytomon(Monitor *m) {
  1029. + Monitor *t;
  1030. + int i, n;
  1031. + if (!systraypinning) {
  1032. + if (!m)
  1033. + return selmon;
  1034. + return m == selmon ? m : NULL;
  1035. + }
  1036. + for (n = 1, t = mons; t && t->next; n++, t = t->next);
  1037. + for (i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next);
  1038. + if (systraypinningfailfirst && n < systraypinning)
  1039. + return mons;
  1040. + return t;
  1041. +}
  1042. +
  1043. void
  1044. tag(const Arg *arg)
  1045. {
  1046. @@ -1667,9 +2041,15 @@ void
  1047. tile(Monitor *m)
  1048. {
  1049. unsigned int i, n, h, mw, my, ty;
  1050. + float mfacts = 0, sfacts = 0;
  1051. Client *c;
  1052.  
  1053. - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  1054. + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
  1055. + if(n < m->nmaster)
  1056. + mfacts += c->cfact;
  1057. + else
  1058. + sfacts += c->cfact;
  1059. + }
  1060. if (n == 0)
  1061. return;
  1062.  
  1063. @@ -1679,22 +2059,61 @@ tile(Monitor *m)
  1064. mw = m->ww;
  1065. for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  1066. if (i < m->nmaster) {
  1067. - h = (m->wh - my) / (MIN(n, m->nmaster) - i);
  1068. + h = (m->wh - my) * (c->cfact / mfacts);
  1069. resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
  1070. my += HEIGHT(c);
  1071. + mfacts -= c->cfact;
  1072. } else {
  1073. - h = (m->wh - ty) / (n - i);
  1074. + h = (m->wh - ty) * (c->cfact / sfacts);
  1075. resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
  1076. ty += HEIGHT(c);
  1077. + sfacts -= c->cfact;
  1078. }
  1079. }
  1080.  
  1081. void
  1082. -togglebar(const Arg *arg)
  1083. +htile(Monitor *m) {
  1084. + unsigned int i, n, w, mh, mx, tx;
  1085. + Client *c;
  1086. +
  1087. + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  1088. + if(n == 0)
  1089. + return;
  1090. +
  1091. + if(n > m->nmaster)
  1092. + mh = m->nmaster ? m->wh * m->mfact : 0;
  1093. + else
  1094. + mh = m->wh;
  1095. + for(i = mx = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  1096. + if(i < m->nmaster) {
  1097. + w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
  1098. + resize(c, m->wx + mx, m->wy, w - (2*c->bw), mh - (2*c->bw), False);
  1099. + mx += WIDTH(c);
  1100. + }
  1101. + else {
  1102. + w = (m->ww - tx) / (n - i);
  1103. + resize(c, m->wx + tx, m->wy + mh, w - (2*c->bw), m->wh - mh - (2*c->bw), False);
  1104. + tx += WIDTH(c);
  1105. + }
  1106. +}
  1107. +
  1108. +void
  1109. +ogglebar(const Arg *arg)
  1110. {
  1111. selmon->showbar = !selmon->showbar;
  1112. updatebarpos(selmon);
  1113. - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
  1114. + resizebarwin(selmon);
  1115. + if (showsystray) {
  1116. + XWindowChanges wc;
  1117. + if (!selmon->showbar)
  1118. + wc.y = -bh;
  1119. + else if (selmon->showbar) {
  1120. + wc.y = 0;
  1121. + if (!selmon->topbar)
  1122. + wc.y = selmon->mh - bh;
  1123. + }
  1124. + XConfigureWindow(dpy, systray->win, CWY, &wc);
  1125. + }
  1126. arrange(selmon);
  1127. }
  1128.  
  1129. @@ -1731,9 +2150,27 @@ void
  1130. toggleview(const Arg *arg)
  1131. {
  1132. unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
  1133. + int i;
  1134.  
  1135. if (newtagset) {
  1136. + if (newtagset == ~0) {
  1137. + selmon->pertag->prevtag = selmon->pertag->curtag;
  1138. + selmon->pertag->curtag = 0;
  1139. + }
  1140. + /* test if the user did not select the same tag */
  1141. + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
  1142. + selmon->pertag->prevtag = selmon->pertag->curtag;
  1143. + for (i=0; !(newtagset & 1 << i); i++) ;
  1144. + selmon->pertag->curtag = i + 1;
  1145. + }
  1146. selmon->tagset[selmon->seltags] = newtagset;
  1147. +
  1148. + /* apply settings for this view */
  1149. + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
  1150. + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
  1151. + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
  1152. + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
  1153. + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
  1154. focus(NULL);
  1155. arrange(selmon);
  1156. }
  1157. @@ -1790,11 +2227,17 @@ unmapnotify(XEvent *e)
  1158. else
  1159. unmanage(c, 0);
  1160. }
  1161. + else if ((c = wintosystrayicon(ev->window))) {
  1162. + removesystrayicon(c);
  1163. + resizebarwin(selmon);
  1164. + updatesystray();
  1165. + }
  1166. }
  1167.  
  1168. void
  1169. updatebars(void)
  1170. {
  1171. + unsigned int w;
  1172. Monitor *m;
  1173. XSetWindowAttributes wa = {
  1174. .override_redirect = True,
  1175. @@ -1804,10 +2247,15 @@ updatebars(void)
  1176. for (m = mons; m; m = m->next) {
  1177. if (m->barwin)
  1178. continue;
  1179. - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
  1180. + w = m->ww;
  1181. + if (showsystray && m == systraytomon(m))
  1182. + w -= getsystraywidth();
  1183. + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
  1184. CopyFromParent, DefaultVisual(dpy, screen),
  1185. CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
  1186. XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
  1187. + if (showsystray && m == systraytomon(m))
  1188. + XMapRaised(dpy, systray->win);
  1189. XMapRaised(dpy, m->barwin);
  1190. }
  1191. }
  1192. @@ -1891,7 +2339,7 @@ updategeom(void)
  1193. m->clients = c->next;
  1194. detachstack(c);
  1195. c->mon = mons;
  1196. - attach(c);
  1197. + attachaside(c);
  1198. attachstack(c);
  1199. }
  1200. if (m == selmon)
  1201. @@ -1998,6 +2446,117 @@ updatestatus(void)
  1202. }
  1203.  
  1204. void
  1205. +updatesystrayicongeom(Client *i, int w, int h) {
  1206. + if (i) {
  1207. + i->h = bh;
  1208. + if (w == h)
  1209. + i->w = bh;
  1210. + else if (h == bh)
  1211. + i->w = w;
  1212. + else
  1213. + i->w = (int) ((float)bh * ((float)w / (float)h));
  1214. + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
  1215. + /* force icons into the systray dimenons if they don't want to */
  1216. + if (i->h > bh) {
  1217. + if (i->w == i->h)
  1218. + i->w = bh;
  1219. + else
  1220. + i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
  1221. + i->h = bh;
  1222. + }
  1223. + }
  1224. +}
  1225. +
  1226. +void
  1227. +updatesystrayiconstate(Client *i, XPropertyEvent *ev) {
  1228. + long flags;
  1229. + int code = 0;
  1230. +
  1231. + if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
  1232. + !(flags = getatomprop(i, xatom[XembedInfo])))
  1233. + return;
  1234. +
  1235. + if (flags & XEMBED_MAPPED && !i->tags) {
  1236. + i->tags = 1;
  1237. + code = XEMBED_WINDOW_ACTIVATE;
  1238. + XMapRaised(dpy, i->win);
  1239. + setclientstate(i, NormalState);
  1240. + }
  1241. + else if (!(flags & XEMBED_MAPPED) && i->tags) {
  1242. + i->tags = 0;
  1243. + code = XEMBED_WINDOW_DEACTIVATE;
  1244. + XUnmapWindow(dpy, i->win);
  1245. + setclientstate(i, WithdrawnState);
  1246. + }
  1247. + else
  1248. + return;
  1249. + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
  1250. + systray->win, XEMBED_EMBEDDED_VERSION);
  1251. +}
  1252. +
  1253. +void
  1254. +updatesystray(void) {
  1255. + XSetWindowAttributes wa;
  1256. + XWindowChanges wc;
  1257. + Client *i;
  1258. + Monitor *m = systraytomon(NULL);
  1259. + unsigned int x = m->mx + m->mw;
  1260. + unsigned int w = 1;
  1261. +
  1262. + if (!showsystray)
  1263. + return;
  1264. + if (!systray) {
  1265. + /* init systray */
  1266. + if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
  1267. + die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
  1268. + systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel].bg->pix);
  1269. + wa.event_mask = ButtonPressMask | ExposureMask;
  1270. + wa.override_redirect = True;
  1271. + wa.background_pixel = scheme[SchemeNorm].bg->pix;
  1272. + XSelectInput(dpy, systray->win, SubstructureNotifyMask);
  1273. + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
  1274. + PropModeReplace, (unsigned char *)&systrayorientation, 1);
  1275. + XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
  1276. + XMapRaised(dpy, systray->win);
  1277. + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
  1278. + if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
  1279. + sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
  1280. + XSync(dpy, False);
  1281. + }
  1282. + else {
  1283. + fprintf(stderr, "dwm: unable to obtain system tray.\n");
  1284. + free(systray);
  1285. + systray = NULL;
  1286. + return;
  1287. + }
  1288. + }
  1289. + for (w = 0, i = systray->icons; i; i = i->next) {
  1290. + /* make sure the background color stays the same */
  1291. + wa.background_pixel = scheme[SchemeNorm].bg->pix;
  1292. + XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
  1293. + XMapRaised(dpy, i->win);
  1294. + w += systrayspacing;
  1295. + i->x = w;
  1296. + XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
  1297. + w += i->w;
  1298. + if (i->mon != m)
  1299. + i->mon = m;
  1300. + }
  1301. + w = w ? w + systrayspacing : 1;
  1302. + x -= w;
  1303. + XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
  1304. + wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
  1305. + wc.stack_mode = Above; wc.sibling = m->barwin;
  1306. + XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
  1307. + XMapWindow(dpy, systray->win);
  1308. + XMapSubwindows(dpy, systray->win);
  1309. + /* redraw background */
  1310. + XSetForeground(dpy, drw->gc, scheme[SchemeNorm].bg->pix);
  1311. + XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
  1312. + XSync(dpy, False);
  1313. +}
  1314. +
  1315. +void
  1316. updatewindowtype(Client *c)
  1317. {
  1318. Atom state = getatomprop(c, netatom[NetWMState]);
  1319. @@ -2031,15 +2590,56 @@ updatewmhints(Client *c)
  1320. void
  1321. view(const Arg *arg)
  1322. {
  1323. + int i;
  1324. + unsigned int tmptag;
  1325. +
  1326. if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
  1327. return;
  1328. selmon->seltags ^= 1; /* toggle sel tagset */
  1329. - if (arg->ui & TAGMASK)
  1330. + if (arg->ui & TAGMASK) {
  1331. + selmon->pertag->prevtag = selmon->pertag->curtag;
  1332. selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
  1333. + if (arg->ui == ~0)
  1334. + selmon->pertag->curtag = 0;
  1335. + else {
  1336. + for (i=0; !(arg->ui & 1 << i); i++) ;
  1337. + selmon->pertag->curtag = i + 1;
  1338. + }
  1339. + } else {
  1340. + tmptag = selmon->pertag->prevtag;
  1341. + selmon->pertag->prevtag = selmon->pertag->curtag;
  1342. + selmon->pertag->curtag = tmptag;
  1343. + }
  1344. + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
  1345. + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
  1346. + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
  1347. + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
  1348. + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
  1349. focus(NULL);
  1350. arrange(selmon);
  1351. }
  1352.  
  1353. +void
  1354. +warp(const Client *c)
  1355. +{
  1356. + Window dummy;
  1357. + int x, y, di;
  1358. + unsigned int dui;
  1359. +
  1360. + if (!c) {
  1361. + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh/2);
  1362. + return;
  1363. + }
  1364. +
  1365. + XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui);
  1366. +
  1367. + if ((x > c->x && y > c->y && x < c->x + c->w && y < c->y + c->h) ||
  1368. + (y > c->mon->by && y < c->mon->by + bh))
  1369. + return;
  1370. +
  1371. + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
  1372. +}
  1373. +
  1374. Client *
  1375. wintoclient(Window w)
  1376. {
  1377. @@ -2070,6 +2670,16 @@ wintomon(Window w)
  1378. return selmon;
  1379. }
  1380.  
  1381. +Client *
  1382. +wintosystrayicon(Window w) {
  1383. + Client *i = NULL;
  1384. +
  1385. + if (!showsystray || !w)
  1386. + return i;
  1387. + for (i = systray->icons; i && i->win != w; i = i->next);
  1388. + return i;
  1389. +}
  1390. +
  1391. /* There's no way to check accesses to destroyed windows, thus those cases are
  1392. * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
  1393. * default error handler, which may call exit. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement