Advertisement
Guest User

Untitled

a guest
Jun 15th, 2012
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.26 KB | None | 0 0
  1. --- dwm.c.orig 2012-05-26 15:42:46.462912626 +0200
  2. +++ src/dwm-6.0/dwm.c 2012-05-26 15:42:15.122913347 +0200
  3. @@ -56,12 +56,30 @@
  4. #define TAGMASK ((1 << LENGTH(tags)) - 1)
  5. #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height)
  6.  
  7. +#define SYSTEM_TRAY_REQUEST_DOCK 0
  8. +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
  9. +
  10. +/* XEMBED messages */
  11. +#define XEMBED_EMBEDDED_NOTIFY 0
  12. +#define XEMBED_WINDOW_ACTIVATE 1
  13. +#define XEMBED_FOCUS_IN 4
  14. +#define XEMBED_MODALITY_ON 10
  15. +
  16. +#define XEMBED_MAPPED (1 << 0)
  17. +#define XEMBED_WINDOW_ACTIVATE 1
  18. +#define XEMBED_WINDOW_DEACTIVATE 2
  19. +
  20. +#define VERSION_MAJOR 0
  21. +#define VERSION_MINOR 0
  22. +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
  23. +
  24. /* enums */
  25. enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
  26. enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
  27. -enum { NetSupported, NetWMName, NetWMState,
  28. - NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  29. - NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */
  30. +enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
  31. + NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType,
  32. + NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */
  33. +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
  34. enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
  35. enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
  36. ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
  37. @@ -165,6 +183,12 @@
  38. int monitor;
  39. } Rule;
  40.  
  41. +typedef struct Systray Systray;
  42. +struct Systray {
  43. + Window win;
  44. + Client *icons;
  45. +};
  46. +
  47. /* function declarations */
  48. static void applyrules(Client *c);
  49. static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
  50. @@ -197,9 +221,11 @@
  51. static void focusin(XEvent *e);
  52. static void focusmon(const Arg *arg);
  53. static void focusstack(const Arg *arg);
  54. +static Atom getatomprop(Client *c, Atom prop);
  55. static XftColor getcolor(const char *colstr);
  56. static Bool getrootptr(int *x, int *y);
  57. static long getstate(Window w);
  58. +static unsigned int getsystraywidth();
  59. static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
  60. static void grabbuttons(Client *c, Bool focused);
  61. static void grabkeys(void);
  62. @@ -218,13 +244,16 @@
  63. static void propertynotify(XEvent *e);
  64. static void quit(const Arg *arg);
  65. static Monitor *recttomon(int x, int y, int w, int h);
  66. +static void removesystrayicon(Client *i);
  67. static void resize(Client *c, int x, int y, int w, int h, Bool interact);
  68. +static void resizebarwin(Monitor *m);
  69. static void resizeclient(Client *c, int x, int y, int w, int h);
  70. static void resizemouse(const Arg *arg);
  71. +static void resizerequest(XEvent *e);
  72. static void restack(Monitor *m);
  73. static void run(void);
  74. static void scan(void);
  75. -static Bool sendevent(Client *c, Atom proto);
  76. +static Bool sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
  77. static void sendmon(Client *c, Monitor *m);
  78. static void setclientstate(Client *c, long state);
  79. static void setfocus(Client *c);
  80. @@ -252,12 +281,16 @@
  81. static void updatenumlockmask(void);
  82. static void updatesizehints(Client *c);
  83. static void updatestatus(void);
  84. +static void updatesystray(void);
  85. +static void updatesystrayicongeom(Client *i, int w, int h);
  86. +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
  87. static void updatewindowtype(Client *c);
  88. static void updatetitle(Client *c);
  89. static void updatewmhints(Client *c);
  90. static void view(const Arg *arg);
  91. static Client *wintoclient(Window w);
  92. static Monitor *wintomon(Window w);
  93. +static Client *wintosystrayicon(Window w);
  94. static int xerror(Display *dpy, XErrorEvent *ee);
  95. static int xerrordummy(Display *dpy, XErrorEvent *ee);
  96. static int xerrorstart(Display *dpy, XErrorEvent *ee);
  97. @@ -265,6 +298,8 @@
  98. static void bstack(Monitor *m);
  99.  
  100. /* variables */
  101. +static Systray *systray = NULL;
  102. +static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
  103. static const char broken[] = "broken";
  104. static char stext[256];
  105. static int screen;
  106. @@ -286,9 +321,10 @@
  107. [MapRequest] = maprequest,
  108. [MotionNotify] = motionnotify,
  109. [PropertyNotify] = propertynotify,
  110. + [ResizeRequest] = resizerequest,
  111. [UnmapNotify] = unmapnotify
  112. };
  113. -static Atom wmatom[WMLast], netatom[NetLast];
  114. +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
  115. static Bool running = True;
  116. static Cursor cursor[CurLast];
  117. static Display *dpy;
  118. @@ -506,6 +542,11 @@
  119. XFreeCursor(dpy, cursor[CurMove]);
  120. while(mons)
  121. cleanupmon(mons);
  122. + if(showsystray) {
  123. + XUnmapWindow(dpy, systray->win);
  124. + XDestroyWindow(dpy, systray->win);
  125. + free(systray);
  126. + }
  127. XSync(dpy, False);
  128. XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
  129. }
  130. @@ -542,9 +583,48 @@
  131.  
  132. void
  133. clientmessage(XEvent *e) {
  134. + XWindowAttributes wa;
  135. + XSetWindowAttributes swa;
  136. XClientMessageEvent *cme = &e->xclient;
  137. Client *c = wintoclient(cme->window);
  138.  
  139. + if(showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
  140. + /* add systray icons */
  141. + if(cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
  142. + if(!(c = (Client *)calloc(1, sizeof(Client))))
  143. + die("fatal: could not malloc() %u bytes\n", sizeof(Client));
  144. + c->win = cme->data.l[2];
  145. + c->mon = selmon;
  146. + c->next = systray->icons;
  147. + systray->icons = c;
  148. + XGetWindowAttributes(dpy, c->win, &wa);
  149. + c->x = c->oldx = c->y = c->oldy = 0;
  150. + c->w = c->oldw = wa.width;
  151. + c->h = c->oldh = wa.height;
  152. + c->oldbw = wa.border_width;
  153. + c->bw = 0;
  154. + c->isfloating = True;
  155. + /* reuse tags field as mapped status */
  156. + c->tags = 1;
  157. + updatesizehints(c);
  158. + updatesystrayicongeom(c, wa.width, wa.height);
  159. + XAddToSaveSet(dpy, c->win);
  160. + XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
  161. + XReparentWindow(dpy, c->win, systray->win, 0, 0);
  162. + /* use parents background pixmap */
  163. + swa.background_pixmap = ParentRelative;
  164. + XChangeWindowAttributes(dpy, c->win, CWBackPixmap, &swa);
  165. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  166. + /* FIXME not sure if I have to send these events, too */
  167. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  168. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  169. + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
  170. + resizebarwin(selmon);
  171. + updatesystray();
  172. + setclientstate(c, NormalState);
  173. + }
  174. + return;
  175. + }
  176. if(!c)
  177. return;
  178. if(cme->message_type == netatom[NetWMState]) {
  179. @@ -595,7 +675,7 @@
  180. dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
  181. updatebars();
  182. for(m = mons; m; m = m->next)
  183. - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
  184. + resizebarwin(m);
  185. focus(NULL);
  186. arrange(NULL);
  187. }
  188. @@ -693,6 +773,11 @@
  189.  
  190. if((c = wintoclient(ev->window)))
  191. unmanage(c, True);
  192. + else if((c = wintosystrayicon(ev->window))) {
  193. + removesystrayicon(c);
  194. + resizebarwin(selmon);
  195. + updatesystray();
  196. + }
  197. }
  198.  
  199. void
  200. @@ -748,6 +833,7 @@
  201. XftColor *col;
  202. Client *c;
  203.  
  204. + resizebarwin(m);
  205. for(c = m->clients; c; c = c->next) {
  206. occ |= c->tags;
  207. if(c->isurgent)
  208. @@ -769,6 +855,9 @@
  209. if(m == selmon) { /* status is only drawn on selected monitor */
  210. dc.w = TEXTW(stext);
  211. dc.x = m->ww - dc.w;
  212. + if(showsystray && m == selmon) {
  213. + dc.x -= getsystraywidth();
  214. + }
  215. if(dc.x < x) {
  216. dc.x = x;
  217. dc.w = m->ww - x;
  218. @@ -797,6 +886,7 @@
  219.  
  220. for(m = mons; m; m = m->next)
  221. drawbar(m);
  222. + updatesystray();
  223. }
  224.  
  225. void
  226. @@ -944,10 +1034,17 @@
  227. unsigned long dl;
  228. unsigned char *p = NULL;
  229. Atom da, atom = None;
  230. + /* FIXME getatomprop should return the number of items and a pointer to
  231. + * the stored data instead of this workaround */
  232. + Atom req = XA_ATOM;
  233. + if(prop == xatom[XembedInfo])
  234. + req = xatom[XembedInfo];
  235.  
  236. - if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
  237. + if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
  238. &da, &di, &dl, &dl, &p) == Success && p) {
  239. atom = *(Atom *)p;
  240. + if(da == xatom[XembedInfo] && dl == 2)
  241. + atom = ((Atom *)p)[1];
  242. XFree(p);
  243. }
  244. return atom;
  245. @@ -989,6 +1086,15 @@
  246. return result;
  247. }
  248.  
  249. +unsigned int
  250. +getsystraywidth() {
  251. + unsigned int w = 0;
  252. + Client *i;
  253. + if(showsystray)
  254. + for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
  255. + return w ? w + systrayspacing : 1;
  256. +}
  257. +
  258. Bool
  259. gettextprop(Window w, Atom atom, char *text, unsigned int size) {
  260. char **list = NULL;
  261. @@ -1101,7 +1207,7 @@
  262. killclient(const Arg *arg) {
  263. if(!selmon->sel)
  264. return;
  265. - if(!sendevent(selmon->sel, wmatom[WMDelete])) {
  266. + if(!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
  267. XGrabServer(dpy);
  268. XSetErrorHandler(xerrordummy);
  269. XSetCloseDownMode(dpy, DestroyAll);
  270. @@ -1185,6 +1291,12 @@
  271. maprequest(XEvent *e) {
  272. static XWindowAttributes wa;
  273. XMapRequestEvent *ev = &e->xmaprequest;
  274. + Client *i;
  275. + if((i = wintosystrayicon(ev->window))) {
  276. + sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
  277. + resizebarwin(selmon);
  278. + updatesystray();
  279. + }
  280.  
  281. if(!XGetWindowAttributes(dpy, ev->window, &wa))
  282. return;
  283. @@ -1298,6 +1410,16 @@
  284. Window trans;
  285. XPropertyEvent *ev = &e->xproperty;
  286.  
  287. + if((c = wintosystrayicon(ev->window))) {
  288. + if(ev->atom == XA_WM_NORMAL_HINTS) {
  289. + updatesizehints(c);
  290. + updatesystrayicongeom(c, c->w, c->h);
  291. + }
  292. + else
  293. + updatesystrayiconstate(c, ev);
  294. + resizebarwin(selmon);
  295. + updatesystray();
  296. + }
  297. if((ev->window == root) && (ev->atom == XA_WM_NAME))
  298. updatestatus();
  299. else if(ev->state == PropertyDelete)
  300. @@ -1347,12 +1469,33 @@
  301. }
  302.  
  303. void
  304. +removesystrayicon(Client *i) {
  305. + Client **ii;
  306. +
  307. + if(!showsystray || !i)
  308. + return;
  309. + for(ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
  310. + if(ii)
  311. + *ii = i->next;
  312. + free(i);
  313. +}
  314. +
  315. +
  316. +void
  317. resize(Client *c, int x, int y, int w, int h, Bool interact) {
  318. if(applysizehints(c, &x, &y, &w, &h, interact))
  319. resizeclient(c, x, y, w, h);
  320. }
  321.  
  322. void
  323. +resizebarwin(Monitor *m) {
  324. + unsigned int w = m->ww;
  325. + if(showsystray && m == selmon)
  326. + w -= getsystraywidth();
  327. + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
  328. +}
  329. +
  330. +void
  331. resizeclient(Client *c, int x, int y, int w, int h) {
  332. XWindowChanges wc;
  333.  
  334. @@ -1418,6 +1561,18 @@
  335. }
  336.  
  337. void
  338. +resizerequest(XEvent *e) {
  339. + XResizeRequestEvent *ev = &e->xresizerequest;
  340. + Client *i;
  341. +
  342. + if((i = wintosystrayicon(ev->window))) {
  343. + updatesystrayicongeom(i, ev->width, ev->height);
  344. + resizebarwin(selmon);
  345. + updatesystray();
  346. + }
  347. +}
  348. +
  349. +void
  350. restack(Monitor *m) {
  351. Client *c;
  352. XEvent ev;
  353. @@ -1501,25 +1656,35 @@
  354. }
  355.  
  356. Bool
  357. -sendevent(Client *c, Atom proto) {
  358. +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) {
  359. int n;
  360. - Atom *protocols;
  361. + Atom *protocols, mt;
  362. Bool exists = False;
  363. XEvent ev;
  364.  
  365. - if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
  366. - while(!exists && n--)
  367. - exists = protocols[n] == proto;
  368. - XFree(protocols);
  369. + if(proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
  370. + mt = wmatom[WMProtocols];
  371. + if(XGetWMProtocols(dpy, w, &protocols, &n)) {
  372. + while(!exists && n--)
  373. + exists = protocols[n] == proto;
  374. + XFree(protocols);
  375. + }
  376. + }
  377. + else {
  378. + exists = True;
  379. + mt = proto;
  380. }
  381. if(exists) {
  382. ev.type = ClientMessage;
  383. - ev.xclient.window = c->win;
  384. - ev.xclient.message_type = wmatom[WMProtocols];
  385. + ev.xclient.window = w;
  386. + ev.xclient.message_type = mt;
  387. ev.xclient.format = 32;
  388. - ev.xclient.data.l[0] = proto;
  389. - ev.xclient.data.l[1] = CurrentTime;
  390. - XSendEvent(dpy, c->win, False, NoEventMask, &ev);
  391. + ev.xclient.data.l[0] = d0;
  392. + ev.xclient.data.l[1] = d1;
  393. + ev.xclient.data.l[2] = d2;
  394. + ev.xclient.data.l[3] = d3;
  395. + ev.xclient.data.l[4] = d4;
  396. + XSendEvent(dpy, w, False, mask, &ev);
  397. }
  398. return exists;
  399. }
  400. @@ -1528,7 +1693,7 @@
  401. setfocus(Client *c) {
  402. if(!c->neverfocus)
  403. XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
  404. - sendevent(c, wmatom[WMTakeFocus]);
  405. + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
  406. }
  407.  
  408. void
  409. @@ -1608,11 +1773,17 @@
  410. wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
  411. netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
  412. netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  413. + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
  414. + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
  415. + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
  416. netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  417. netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
  418. netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
  419. netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
  420. netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  421. + xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
  422. + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
  423. + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
  424. /* init cursors */
  425. cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  426. cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  427. @@ -1627,7 +1798,9 @@
  428. dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
  429. dc.gc = XCreateGC(dpy, root, 0, NULL);
  430. XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
  431. - /* init bars */
  432. + /* init system tray */
  433. + updatesystray();
  434. + /* init bars */
  435. updatebars();
  436. updatestatus();
  437. /* EWMH support per view */
  438. @@ -1731,7 +1904,18 @@
  439. togglebar(const Arg *arg) {
  440. selmon->showbar = !selmon->showbar;
  441. updatebarpos(selmon);
  442. - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
  443. + resizebarwin(selmon);
  444. + if(showsystray) {
  445. + XWindowChanges wc;
  446. + if(!selmon->showbar)
  447. + wc.y = -bh;
  448. + else if(selmon->showbar) {
  449. + wc.y = 0;
  450. + if(!selmon->topbar)
  451. + wc.y = selmon->mh - bh;
  452. + }
  453. + XConfigureWindow(dpy, systray->win, CWY, &wc);
  454. + }
  455. arrange(selmon);
  456. }
  457.  
  458. @@ -1827,18 +2011,28 @@
  459. else
  460. unmanage(c, False);
  461. }
  462. + else if((c = wintosystrayicon(ev->window))) {
  463. + removesystrayicon(c);
  464. + resizebarwin(selmon);
  465. + updatesystray();
  466. + }
  467. }
  468.  
  469. void
  470. updatebars(void) {
  471. + unsigned int w;
  472. Monitor *m;
  473. +
  474. XSetWindowAttributes wa = {
  475. .override_redirect = True,
  476. .background_pixmap = ParentRelative,
  477. .event_mask = ButtonPressMask|ExposureMask
  478. };
  479. for(m = mons; m; m = m->next) {
  480. - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
  481. + w = m->ww;
  482. + if(showsystray && m == selmon)
  483. + w -= getsystraywidth();
  484. + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
  485. CopyFromParent, DefaultVisual(dpy, screen),
  486. CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
  487. XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
  488. @@ -2022,6 +2216,104 @@
  489. }
  490.  
  491. void
  492. +updatesystrayicongeom(Client *i, int w, int h) {
  493. + if(i) {
  494. + i->h = bh;
  495. + if(w == h)
  496. + i->w = bh;
  497. + else if(h == bh)
  498. + i->w = w;
  499. + else
  500. + i->w = (int) ((float)bh * ((float)w / (float)h));
  501. + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
  502. + /* force icons into the systray dimenons if they don't want to */
  503. + if(i->h > bh) {
  504. + if(i->w == i->h)
  505. + i->w = bh;
  506. + else
  507. + i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
  508. + i->h = bh;
  509. + }
  510. + }
  511. +}
  512. +
  513. +void
  514. +updatesystrayiconstate(Client *i, XPropertyEvent *ev) {
  515. + long flags;
  516. + int code = 0;
  517. +
  518. + if(!showsystray || !i || ev->atom != xatom[XembedInfo] ||
  519. + !(flags = getatomprop(i, xatom[XembedInfo])))
  520. + return;
  521. +
  522. + if(flags & XEMBED_MAPPED && !i->tags) {
  523. + i->tags = 1;
  524. + code = XEMBED_WINDOW_ACTIVATE;
  525. + XMapRaised(dpy, i->win);
  526. + setclientstate(i, NormalState);
  527. + }
  528. + else if(!(flags & XEMBED_MAPPED) && i->tags) {
  529. + i->tags = 0;
  530. + code = XEMBED_WINDOW_DEACTIVATE;
  531. + XUnmapWindow(dpy, i->win);
  532. + setclientstate(i, WithdrawnState);
  533. + }
  534. + else
  535. + return;
  536. + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
  537. + systray->win, XEMBED_EMBEDDED_VERSION);
  538. +}
  539. +
  540. +void
  541. +updatesystray(void) {
  542. + XSetWindowAttributes wa;
  543. + Client *i;
  544. + unsigned int x = selmon->mx + selmon->mw;
  545. + unsigned int w = 1;
  546. +
  547. + if(!showsystray)
  548. + return;
  549. + if(!systray) {
  550. + /* init systray */
  551. + if(!(systray = (Systray *)calloc(1, sizeof(Systray))))
  552. + die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
  553. + systray->win = XCreateSimpleWindow(dpy, root, x, selmon->by, w, bh, 0, 0, dc.sel[ColBG].pixel);
  554. + wa.event_mask = ButtonPressMask | ExposureMask;
  555. + wa.override_redirect = True;
  556. + wa.background_pixmap = ParentRelative;
  557. + wa.background_pixel = dc.norm[ColBG].pixel;
  558. + XSelectInput(dpy, systray->win, SubstructureNotifyMask);
  559. + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
  560. + PropModeReplace, (unsigned char *)&systrayorientation, 1);
  561. + XChangeWindowAttributes(dpy, systray->win, CWEventMask | CWOverrideRedirect | CWBackPixel, &wa);
  562. + XMapRaised(dpy, systray->win);
  563. + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
  564. + if(XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
  565. + sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
  566. + XSync(dpy, False);
  567. + }
  568. + else {
  569. + fprintf(stderr, "dwm: unable to obtain system tray.\n");
  570. + free(systray);
  571. + systray = NULL;
  572. + return;
  573. + }
  574. + }
  575. + for(w = 0, i = systray->icons; i; i = i->next) {
  576. + XMapRaised(dpy, i->win);
  577. + w += systrayspacing;
  578. + XMoveResizeWindow(dpy, i->win, (i->x = w), 0, i->w, i->h);
  579. + w += i->w;
  580. + if(i->mon != selmon)
  581. + i->mon = selmon;
  582. + }
  583. + w = w ? w + systrayspacing : 1;
  584. + x -= w;
  585. + XMoveResizeWindow(dpy, systray->win, x, selmon->by, w, bh);
  586. + XSync(dpy, False);
  587. +}
  588. +
  589. +void
  590. updatewindowtype(Client *c) {
  591. Atom state = getatomprop(c, netatom[NetWMState]);
  592. Atom wtype = getatomprop(c, netatom[NetWMWindowType]);
  593. @@ -2106,6 +2398,16 @@
  594. return selmon;
  595. }
  596.  
  597. +Client *
  598. +wintosystrayicon(Window w) {
  599. + Client *i = NULL;
  600. +
  601. + if(!showsystray || !w)
  602. + return i;
  603. + for(i = systray->icons; i && i->win != w; i = i->next) ;
  604. + return i;
  605. +}
  606. +
  607. /* There's no way to check accesses to destroyed windows, thus those cases are
  608. * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
  609. * default error handler, which may call exit. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement