Introduction
Introduction Statistics Contact Development Disclaimer Help
dwm-git-20130119-systray.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
dwm-git-20130119-systray.diff (20248B)
---
1 Author: Jan Christoph Ebersbach <[email protected]>, inspired by http://code.…
2 URL: http://dwm.suckless.org/patches/systray
3 Implements a system tray for dwm.
4
5 diff -r c794a9f5ae5e config.def.h
6 --- a/config.def.h Sun Jul 08 09:45:53 2012 +0200
7 +++ b/config.def.h Sat Aug 18 13:28:31 2012 +0200
8 @@ -10,6 +10,8 @@
9 static const char selfgcolor[] = "#eeeeee";
10 static const unsigned int borderpx = 1; /* border pixel of wind…
11 static const unsigned int snap = 32; /* snap pixel */
12 +static const unsigned int systrayspacing = 2; /* systray spacing */
13 +static const Bool showsystray = True; /* False means no systr…
14 static const Bool showbar = True; /* False means no bar */
15 static const Bool topbar = True; /* False means bottom b…
16
17 diff -r c794a9f5ae5e dwm.c
18 --- a/dwm.c Sun Jul 08 09:45:53 2012 +0200
19 +++ b/dwm.c Sat Aug 18 13:28:31 2012 +0200
20 @@ -56,12 +56,30 @@
21 #define TAGMASK ((1 << LENGTH(tags)) - 1)
22 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height)
23
24 +#define SYSTEM_TRAY_REQUEST_DOCK 0
25 +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
26 +
27 +/* XEMBED messages */
28 +#define XEMBED_EMBEDDED_NOTIFY 0
29 +#define XEMBED_WINDOW_ACTIVATE 1
30 +#define XEMBED_FOCUS_IN 4
31 +#define XEMBED_MODALITY_ON 10
32 +
33 +#define XEMBED_MAPPED (1 << 0)
34 +#define XEMBED_WINDOW_ACTIVATE 1
35 +#define XEMBED_WINDOW_DEACTIVATE 2
36 +
37 +#define VERSION_MAJOR 0
38 +#define VERSION_MINOR 0
39 +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
40 +
41 /* enums */
42 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
43 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
44 -enum { NetSupported, NetWMName, NetWMState,
45 - NetWMFullscreen, NetActiveWindow, NetWMWindowType,
46 - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH ato…
47 +enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrien…
48 + NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, Net…
49 + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH ato…
50 +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
51 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* defaul…
52 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
53 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
54 @@ -155,6 +173,12 @@
55 int monitor;
56 } Rule;
57
58 +typedef struct Systray Systray;
59 +struct Systray {
60 + Window win;
61 + Client *icons;
62 +};
63 +
64 /* function declarations */
65 static void applyrules(Client *c);
66 static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, B…
67 @@ -187,9 +211,11 @@
68 static void focusin(XEvent *e);
69 static void focusmon(const Arg *arg);
70 static void focusstack(const Arg *arg);
71 +static Atom getatomprop(Client *c, Atom prop);
72 static unsigned long getcolor(const char *colstr);
73 static Bool getrootptr(int *x, int *y);
74 static long getstate(Window w);
75 +static unsigned int getsystraywidth();
76 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int s…
77 static void grabbuttons(Client *c, Bool focused);
78 static void grabkeys(void);
79 @@ -208,13 +234,16 @@
80 static void propertynotify(XEvent *e);
81 static void quit(const Arg *arg);
82 static Monitor *recttomon(int x, int y, int w, int h);
83 +static void removesystrayicon(Client *i);
84 static void resize(Client *c, int x, int y, int w, int h, Bool interact…
85 +static void resizebarwin(Monitor *m);
86 static void resizeclient(Client *c, int x, int y, int w, int h);
87 static void resizemouse(const Arg *arg);
88 +static void resizerequest(XEvent *e);
89 static void restack(Monitor *m);
90 static void run(void);
91 static void scan(void);
92 -static Bool sendevent(Client *c, Atom proto);
93 +static Bool sendevent(Window w, Atom proto, int m, long d0, long d1, lo…
94 static void sendmon(Client *c, Monitor *m);
95 static void setclientstate(Client *c, long state);
96 static void setfocus(Client *c);
97 @@ -243,18 +272,24 @@
98 static void updatenumlockmask(void);
99 static void updatesizehints(Client *c);
100 static void updatestatus(void);
101 +static void updatesystray(void);
102 +static void updatesystrayicongeom(Client *i, int w, int h);
103 +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
104 static void updatewindowtype(Client *c);
105 static void updatetitle(Client *c);
106 static void updatewmhints(Client *c);
107 static void view(const Arg *arg);
108 static Client *wintoclient(Window w);
109 static Monitor *wintomon(Window w);
110 +static Client *wintosystrayicon(Window w);
111 static int xerror(Display *dpy, XErrorEvent *ee);
112 static int xerrordummy(Display *dpy, XErrorEvent *ee);
113 static int xerrorstart(Display *dpy, XErrorEvent *ee);
114 static void zoom(const Arg *arg);
115
116 /* variables */
117 +static Systray *systray = NULL;
118 +static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_…
119 static const char broken[] = "broken";
120 static char stext[256];
121 static int screen;
122 @@ -276,9 +311,10 @@
123 [MapRequest] = maprequest,
124 [MotionNotify] = motionnotify,
125 [PropertyNotify] = propertynotify,
126 + [ResizeRequest] = resizerequest,
127 [UnmapNotify] = unmapnotify
128 };
129 -static Atom wmatom[WMLast], netatom[NetLast];
130 +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
131 static Bool running = True;
132 static Cursor cursor[CurLast];
133 static Display *dpy;
134 @@ -499,6 +535,11 @@
135 XFreeCursor(dpy, cursor[CurMove]);
136 while(mons)
137 cleanupmon(mons);
138 + if(showsystray) {
139 + XUnmapWindow(dpy, systray->win);
140 + XDestroyWindow(dpy, systray->win);
141 + free(systray);
142 + }
143 XSync(dpy, False);
144 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTi…
145 XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
146 @@ -533,9 +575,49 @@
147
148 void
149 clientmessage(XEvent *e) {
150 + XWindowAttributes wa;
151 + XSetWindowAttributes swa;
152 XClientMessageEvent *cme = &e->xclient;
153 Client *c = wintoclient(cme->window);
154
155 + if(showsystray && cme->window == systray->win && cme->message_t…
156 + /* add systray icons */
157 + if(cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
158 + if(!(c = (Client *)calloc(1, sizeof(Client))))
159 + die("fatal: could not malloc() %u bytes…
160 + c->win = cme->data.l[2];
161 + c->mon = selmon;
162 + c->next = systray->icons;
163 + systray->icons = c;
164 + XGetWindowAttributes(dpy, c->win, &wa);
165 + c->x = c->oldx = c->y = c->oldy = 0;
166 + c->w = c->oldw = wa.width;
167 + c->h = c->oldh = wa.height;
168 + c->oldbw = wa.border_width;
169 + c->bw = 0;
170 + c->isfloating = True;
171 + /* reuse tags field as mapped status */
172 + c->tags = 1;
173 + updatesizehints(c);
174 + updatesystrayicongeom(c, wa.width, wa.height);
175 + XAddToSaveSet(dpy, c->win);
176 + XSelectInput(dpy, c->win, StructureNotifyMask |…
177 + XReparentWindow(dpy, c->win, systray->win, 0, 0…
178 + /* use parents background pixmap */
179 + swa.background_pixmap = ParentRelative;
180 + swa.background_pixel = dc.norm[ColBG];
181 + XChangeWindowAttributes(dpy, c->win, CWBackPixm…
182 + sendevent(c->win, netatom[Xembed], StructureNot…
183 + /* FIXME not sure if I have to send these event…
184 + sendevent(c->win, netatom[Xembed], StructureNot…
185 + sendevent(c->win, netatom[Xembed], StructureNot…
186 + sendevent(c->win, netatom[Xembed], StructureNot…
187 + resizebarwin(selmon);
188 + updatesystray();
189 + setclientstate(c, NormalState);
190 + }
191 + return;
192 + }
193 if(!c)
194 return;
195 if(cme->message_type == netatom[NetWMState]) {
196 @@ -587,7 +667,7 @@
197 dc.drawable = XCreatePixmap(dpy, root, sw, bh, …
198 updatebars();
199 for(m = mons; m; m = m->next)
200 - XMoveResizeWindow(dpy, m->barwin, m->wx…
201 + resizebarwin(m);
202 focus(NULL);
203 arrange(NULL);
204 }
205 @@ -671,6 +751,11 @@
206
207 if((c = wintoclient(ev->window)))
208 unmanage(c, True);
209 + else if((c = wintosystrayicon(ev->window))) {
210 + removesystrayicon(c);
211 + resizebarwin(selmon);
212 + updatesystray();
213 + }
214 }
215
216 void
217 @@ -726,6 +811,7 @@
218 unsigned long *col;
219 Client *c;
220
221 + resizebarwin(m);
222 for(c = m->clients; c; c = c->next) {
223 occ |= c->tags;
224 if(c->isurgent)
225 @@ -747,6 +833,9 @@
226 if(m == selmon) { /* status is only drawn on selected monitor */
227 dc.w = TEXTW(stext);
228 dc.x = m->ww - dc.w;
229 + if(showsystray && m == selmon) {
230 + dc.x -= getsystraywidth();
231 + }
232 if(dc.x < x) {
233 dc.x = x;
234 dc.w = m->ww - x;
235 @@ -775,6 +864,7 @@
236
237 for(m = mons; m; m = m->next)
238 drawbar(m);
239 + updatesystray();
240 }
241
242 void
243 @@ -924,10 +1014,17 @@
244 unsigned long dl;
245 unsigned char *p = NULL;
246 Atom da, atom = None;
247 + /* FIXME getatomprop should return the number of items and a po…
248 + * the stored data instead of this workaround */
249 + Atom req = XA_ATOM;
250 + if(prop == xatom[XembedInfo])
251 + req = xatom[XembedInfo];
252
253 - if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False…
254 + if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False…
255 &da, &di, &dl, &dl, &p) == Success && p) {
256 atom = *(Atom *)p;
257 + if(da == xatom[XembedInfo] && dl == 2)
258 + atom = ((Atom *)p)[1];
259 XFree(p);
260 }
261 return atom;
262 @@ -969,6 +1066,15 @@
263 return result;
264 }
265
266 +unsigned int
267 +getsystraywidth() {
268 + unsigned int w = 0;
269 + Client *i;
270 + if(showsystray)
271 + for(i = systray->icons; i; w += i->w + systrayspacing, …
272 + return w ? w + systrayspacing : 1;
273 +}
274 +
275 Bool
276 gettextprop(Window w, Atom atom, char *text, unsigned int size) {
277 char **list = NULL;
278 @@ -1103,7 +1209,7 @@
279 killclient(const Arg *arg) {
280 if(!selmon->sel)
281 return;
282 - if(!sendevent(selmon->sel, wmatom[WMDelete])) {
283 + if(!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, …
284 XGrabServer(dpy);
285 XSetErrorHandler(xerrordummy);
286 XSetCloseDownMode(dpy, DestroyAll);
287 @@ -1189,6 +1295,12 @@
288 maprequest(XEvent *e) {
289 static XWindowAttributes wa;
290 XMapRequestEvent *ev = &e->xmaprequest;
291 + Client *i;
292 + if((i = wintosystrayicon(ev->window))) {
293 + sendevent(i->win, netatom[Xembed], StructureNotifyMask,…
294 + resizebarwin(selmon);
295 + updatesystray();
296 + }
297
298 if(!XGetWindowAttributes(dpy, ev->window, &wa))
299 return;
300 @@ -1305,6 +1417,16 @@
301 Window trans;
302 XPropertyEvent *ev = &e->xproperty;
303
304 + if((c = wintosystrayicon(ev->window))) {
305 + if(ev->atom == XA_WM_NORMAL_HINTS) {
306 + updatesizehints(c);
307 + updatesystrayicongeom(c, c->w, c->h);
308 + }
309 + else
310 + updatesystrayiconstate(c, ev);
311 + resizebarwin(selmon);
312 + updatesystray();
313 + }
314 if((ev->window == root) && (ev->atom == XA_WM_NAME))
315 updatestatus();
316 else if(ev->state == PropertyDelete)
317 @@ -1354,12 +1476,33 @@
318 }
319
320 void
321 +removesystrayicon(Client *i) {
322 + Client **ii;
323 +
324 + if(!showsystray || !i)
325 + return;
326 + for(ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
327 + if(ii)
328 + *ii = i->next;
329 + free(i);
330 +}
331 +
332 +
333 +void
334 resize(Client *c, int x, int y, int w, int h, Bool interact) {
335 if(applysizehints(c, &x, &y, &w, &h, interact))
336 resizeclient(c, x, y, w, h);
337 }
338
339 void
340 +resizebarwin(Monitor *m) {
341 + unsigned int w = m->ww;
342 + if(showsystray && m == selmon)
343 + w -= getsystraywidth();
344 + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
345 +}
346 +
347 +void
348 resizeclient(Client *c, int x, int y, int w, int h) {
349 XWindowChanges wc;
350
351 @@ -1426,6 +1569,18 @@
352 }
353
354 void
355 +resizerequest(XEvent *e) {
356 + XResizeRequestEvent *ev = &e->xresizerequest;
357 + Client *i;
358 +
359 + if((i = wintosystrayicon(ev->window))) {
360 + updatesystrayicongeom(i, ev->width, ev->height);
361 + resizebarwin(selmon);
362 + updatesystray();
363 + }
364 +}
365 +
366 +void
367 restack(Monitor *m) {
368 Client *c;
369 XEvent ev;
370 @@ -1509,25 +1664,35 @@
371 }
372
373 Bool
374 -sendevent(Client *c, Atom proto) {
375 +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, lo…
376 int n;
377 - Atom *protocols;
378 + Atom *protocols, mt;
379 Bool exists = False;
380 XEvent ev;
381
382 - if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
383 - while(!exists && n--)
384 - exists = protocols[n] == proto;
385 - XFree(protocols);
386 + if(proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
387 + mt = wmatom[WMProtocols];
388 + if(XGetWMProtocols(dpy, w, &protocols, &n)) {
389 + while(!exists && n--)
390 + exists = protocols[n] == proto;
391 + XFree(protocols);
392 + }
393 + }
394 + else {
395 + exists = True;
396 + mt = proto;
397 }
398 if(exists) {
399 ev.type = ClientMessage;
400 - ev.xclient.window = c->win;
401 - ev.xclient.message_type = wmatom[WMProtocols];
402 + ev.xclient.window = w;
403 + ev.xclient.message_type = mt;
404 ev.xclient.format = 32;
405 - ev.xclient.data.l[0] = proto;
406 - ev.xclient.data.l[1] = CurrentTime;
407 - XSendEvent(dpy, c->win, False, NoEventMask, &ev);
408 + ev.xclient.data.l[0] = d0;
409 + ev.xclient.data.l[1] = d1;
410 + ev.xclient.data.l[2] = d2;
411 + ev.xclient.data.l[3] = d3;
412 + ev.xclient.data.l[4] = d4;
413 + XSendEvent(dpy, w, False, mask, &ev);
414 }
415 return exists;
416 }
417 @@ -1540,7 +1705,7 @@
418 XA_WINDOW, 32, PropModeReplace,
419 (unsigned char *) &(c->win), 1);
420 }
421 - sendevent(c, wmatom[WMTakeFocus]);
422 + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTa…
423 }
424
425 void
426 @@ -1620,12 +1785,18 @@
427 wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
428 netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW…
429 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", Fals…
430 + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0"…
431 + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_O…
432 + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYST…
433 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
434 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
435 netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULL…
436 netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYP…
437 netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WIND…
438 netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", F…
439 + xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
440 + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
441 + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
442 /* init cursors */
443 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
444 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
445 @@ -1642,6 +1813,8 @@
446 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter…
447 if(!dc.font.set)
448 XSetFont(dpy, dc.gc, dc.font.xfont->fid);
449 + /* init system tray */
450 + updatesystray();
451 /* init bars */
452 updatebars();
453 updatestatus();
454 @@ -1751,7 +1924,18 @@
455 togglebar(const Arg *arg) {
456 selmon->showbar = !selmon->showbar;
457 updatebarpos(selmon);
458 - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, …
459 + resizebarwin(selmon);
460 + if(showsystray) {
461 + XWindowChanges wc;
462 + if(!selmon->showbar)
463 + wc.y = -bh;
464 + else if(selmon->showbar) {
465 + wc.y = 0;
466 + if(!selmon->topbar)
467 + wc.y = selmon->mh - bh;
468 + }
469 + XConfigureWindow(dpy, systray->win, CWY, &wc);
470 + }
471 arrange(selmon);
472 }
473
474 @@ -1841,11 +2025,18 @@
475 else
476 unmanage(c, False);
477 }
478 + else if((c = wintosystrayicon(ev->window))) {
479 + removesystrayicon(c);
480 + resizebarwin(selmon);
481 + updatesystray();
482 + }
483 }
484
485 void
486 updatebars(void) {
487 + unsigned int w;
488 Monitor *m;
489 +
490 XSetWindowAttributes wa = {
491 .override_redirect = True,
492 .background_pixmap = ParentRelative,
493 @@ -1854,10 +2045,15 @@
494 for(m = mons; m; m = m->next) {
495 if (m->barwin)
496 continue;
497 - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->w…
498 + w = m->ww;
499 + if(showsystray && m == selmon)
500 + w -= getsystraywidth();
501 + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, b…
502 CopyFromParent, DefaultVisual…
503 CWOverrideRedirect|CWBackPixm…
504 XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
505 + if(showsystray && m == selmon)
506 + XMapRaised(dpy, systray->win);
507 XMapRaised(dpy, m->barwin);
508 }
509 }
510 @@ -2051,6 +2250,107 @@
511 }
512
513 void
514 +updatesystrayicongeom(Client *i, int w, int h) {
515 + if(i) {
516 + i->h = bh;
517 + if(w == h)
518 + i->w = bh;
519 + else if(h == bh)
520 + i->w = w;
521 + else
522 + i->w = (int) ((float)bh * ((float)w / (float)h)…
523 + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), F…
524 + /* force icons into the systray dimenons if they don't …
525 + if(i->h > bh) {
526 + if(i->w == i->h)
527 + i->w = bh;
528 + else
529 + i->w = (int) ((float)bh * ((float)i->w …
530 + i->h = bh;
531 + }
532 + }
533 +}
534 +
535 +void
536 +updatesystrayiconstate(Client *i, XPropertyEvent *ev) {
537 + long flags;
538 + int code = 0;
539 +
540 + if(!showsystray || !i || ev->atom != xatom[XembedInfo] ||
541 + !(flags = getatomprop(i, xatom[XembedInfo])))
542 + return;
543 +
544 + if(flags & XEMBED_MAPPED && !i->tags) {
545 + i->tags = 1;
546 + code = XEMBED_WINDOW_ACTIVATE;
547 + XMapRaised(dpy, i->win);
548 + setclientstate(i, NormalState);
549 + }
550 + else if(!(flags & XEMBED_MAPPED) && i->tags) {
551 + i->tags = 0;
552 + code = XEMBED_WINDOW_DEACTIVATE;
553 + XUnmapWindow(dpy, i->win);
554 + setclientstate(i, WithdrawnState);
555 + }
556 + else
557 + return;
558 + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTi…
559 + systray->win, XEMBED_EMBEDDED_VERSION);
560 +}
561 +
562 +void
563 +updatesystray(void) {
564 + XSetWindowAttributes wa;
565 + Client *i;
566 + unsigned int x = selmon->mx + selmon->mw;
567 + unsigned int w = 1;
568 +
569 + if(!showsystray)
570 + return;
571 + if(!systray) {
572 + /* init systray */
573 + if(!(systray = (Systray *)calloc(1, sizeof(Systray))))
574 + die("fatal: could not malloc() %u bytes\n", siz…
575 + systray->win = XCreateSimpleWindow(dpy, root, x, selmon…
576 + wa.event_mask = ButtonPressMask | ExposureMask;
577 + wa.override_redirect = True;
578 + wa.background_pixmap = ParentRelative;
579 + wa.background_pixel = dc.norm[ColBG];
580 + XSelectInput(dpy, systray->win, SubstructureNotifyMask);
581 + XChangeProperty(dpy, systray->win, netatom[NetSystemTra…
582 + PropModeReplace, (unsigned char *)&syst…
583 + XChangeWindowAttributes(dpy, systray->win, CWEventMask|…
584 + XMapRaised(dpy, systray->win);
585 + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray…
586 + if(XGetSelectionOwner(dpy, netatom[NetSystemTray]) == s…
587 + sendevent(root, xatom[Manager], StructureNotify…
588 + XSync(dpy, False);
589 + }
590 + else {
591 + fprintf(stderr, "dwm: unable to obtain system t…
592 + free(systray);
593 + systray = NULL;
594 + return;
595 + }
596 + }
597 + for(w = 0, i = systray->icons; i; i = i->next) {
598 + XMapRaised(dpy, i->win);
599 + w += systrayspacing;
600 + XMoveResizeWindow(dpy, i->win, (i->x = w), 0, i->w, i->…
601 + w += i->w;
602 + if(i->mon != selmon)
603 + i->mon = selmon;
604 + }
605 + w = w ? w + systrayspacing : 1;
606 + x -= w;
607 + XMoveResizeWindow(dpy, systray->win, x, selmon->by, w, bh);
608 + /* redraw background */
609 + XSetForeground(dpy, dc.gc, dc.norm[ColBG]);
610 + XFillRectangle(dpy, systray->win, dc.gc, 0, 0, w, bh);
611 + XSync(dpy, False);
612 +}
613 +
614 +void
615 updatewindowtype(Client *c) {
616 Atom state = getatomprop(c, netatom[NetWMState]);
617 Atom wtype = getatomprop(c, netatom[NetWMWindowType]);
618 @@ -2119,6 +2413,16 @@
619 return selmon;
620 }
621
622 +Client *
623 +wintosystrayicon(Window w) {
624 + Client *i = NULL;
625 +
626 + if(!showsystray || !w)
627 + return i;
628 + for(i = systray->icons; i && i->win != w; i = i->next) ;
629 + return i;
630 +}
631 +
632 /* There's no way to check accesses to destroyed windows, thus those ca…
633 * ignored (especially on UnmapNotify's). Other types of errors call X…
634 * default error handler, which may call exit. */
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.