Introduction
Introduction Statistics Contact Development Disclaimer Help
dwm-systray-20190208-cb3f58a.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
dwm-systray-20190208-cb3f58a.diff (23241B)
---
1 diff --git a/config.def.h b/config.def.h
2 index 1c0b587..2d824d1 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -3,6 +3,10 @@
6 /* appearance */
7 static const unsigned int borderpx = 1; /* border pixel of wind…
8 static const unsigned int snap = 32; /* snap pixel */
9 +static const unsigned int systraypinning = 0; /* 0: sloppy systray fo…
10 +static const unsigned int systrayspacing = 2; /* systray spacing */
11 +static const int systraypinningfailfirst = 1; /* 1: if pinning fails,…
12 +static const int showsystray = 1; /* 0 means no systray */
13 static const int showbar = 1; /* 0 means no bar */
14 static const int topbar = 1; /* 0 means bottom bar */
15 static const char *fonts[] = { "monospace:size=10" };
16 diff --git a/dwm.c b/dwm.c
17 index 4465af1..4bccb41 100644
18 --- a/dwm.c
19 +++ b/dwm.c
20 @@ -57,12 +57,30 @@
21 #define TAGMASK ((1 << LENGTH(tags)) - 1)
22 #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
23
24 +#define SYSTEM_TRAY_REQUEST_DOCK 0
25 +
26 +/* XEMBED messages */
27 +#define XEMBED_EMBEDDED_NOTIFY 0
28 +#define XEMBED_WINDOW_ACTIVATE 1
29 +#define XEMBED_FOCUS_IN 4
30 +#define XEMBED_MODALITY_ON 10
31 +
32 +#define XEMBED_MAPPED (1 << 0)
33 +#define XEMBED_WINDOW_ACTIVATE 1
34 +#define XEMBED_WINDOW_DEACTIVATE 2
35 +
36 +#define VERSION_MAJOR 0
37 +#define VERSION_MINOR 0
38 +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
39 +
40 /* enums */
41 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
42 enum { SchemeNorm, SchemeSel }; /* color schemes */
43 enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
44 + NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSys…
45 NetWMFullscreen, NetActiveWindow, NetWMWindowType,
46 NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
47 +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
48 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* defaul…
49 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
50 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
51 @@ -141,6 +159,12 @@ typedef struct {
52 int monitor;
53 } Rule;
54
55 +typedef struct Systray Systray;
56 +struct Systray {
57 + Window win;
58 + Client *icons;
59 +};
60 +
61 /* function declarations */
62 static void applyrules(Client *c);
63 static int applysizehints(Client *c, int *x, int *y, int *w, int *h, in…
64 @@ -169,8 +193,10 @@ static void focus(Client *c);
65 static void focusin(XEvent *e);
66 static void focusmon(const Arg *arg);
67 static void focusstack(const Arg *arg);
68 +static Atom getatomprop(Client *c, Atom prop);
69 static int getrootptr(int *x, int *y);
70 static long getstate(Window w);
71 +static unsigned int getsystraywidth();
72 static int gettextprop(Window w, Atom atom, char *text, unsigned int si…
73 static void grabbuttons(Client *c, int focused);
74 static void grabkeys(void);
75 @@ -188,13 +214,16 @@ static void pop(Client *);
76 static void propertynotify(XEvent *e);
77 static void quit(const Arg *arg);
78 static Monitor *recttomon(int x, int y, int w, int h);
79 +static void removesystrayicon(Client *i);
80 static void resize(Client *c, int x, int y, int w, int h, int interact);
81 +static void resizebarwin(Monitor *m);
82 static void resizeclient(Client *c, int x, int y, int w, int h);
83 static void resizemouse(const Arg *arg);
84 +static void resizerequest(XEvent *e);
85 static void restack(Monitor *m);
86 static void run(void);
87 static void scan(void);
88 -static int sendevent(Client *c, Atom proto);
89 +static int sendevent(Window w, Atom proto, int m, long d0, long d1, lon…
90 static void sendmon(Client *c, Monitor *m);
91 static void setclientstate(Client *c, long state);
92 static void setfocus(Client *c);
93 @@ -206,6 +235,7 @@ static void seturgent(Client *c, int urg);
94 static void showhide(Client *c);
95 static void sigchld(int unused);
96 static void spawn(const Arg *arg);
97 +static Monitor *systraytomon(Monitor *m);
98 static void tag(const Arg *arg);
99 static void tagmon(const Arg *arg);
100 static void tile(Monitor *);
101 @@ -223,18 +253,23 @@ static int updategeom(void);
102 static void updatenumlockmask(void);
103 static void updatesizehints(Client *c);
104 static void updatestatus(void);
105 +static void updatesystray(void);
106 +static void updatesystrayicongeom(Client *i, int w, int h);
107 +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
108 static void updatetitle(Client *c);
109 static void updatewindowtype(Client *c);
110 static void updatewmhints(Client *c);
111 static void view(const Arg *arg);
112 static Client *wintoclient(Window w);
113 static Monitor *wintomon(Window w);
114 +static Client *wintosystrayicon(Window w);
115 static int xerror(Display *dpy, XErrorEvent *ee);
116 static int xerrordummy(Display *dpy, XErrorEvent *ee);
117 static int xerrorstart(Display *dpy, XErrorEvent *ee);
118 static void zoom(const Arg *arg);
119
120 /* variables */
121 +static Systray *systray = NULL;
122 static const char broken[] = "broken";
123 static char stext[256];
124 static int screen;
125 @@ -257,9 +292,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
126 [MapRequest] = maprequest,
127 [MotionNotify] = motionnotify,
128 [PropertyNotify] = propertynotify,
129 + [ResizeRequest] = resizerequest,
130 [UnmapNotify] = unmapnotify
131 };
132 -static Atom wmatom[WMLast], netatom[NetLast];
133 +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
134 static int running = 1;
135 static Cur *cursor[CurLast];
136 static Clr **scheme;
137 @@ -439,7 +475,7 @@ buttonpress(XEvent *e)
138 arg.ui = 1 << i;
139 } else if (ev->x < x + blw)
140 click = ClkLtSymbol;
141 - else if (ev->x > selmon->ww - TEXTW(stext))
142 + else if (ev->x > selmon->ww - TEXTW(stext) - getsystray…
143 click = ClkStatusText;
144 else
145 click = ClkWinTitle;
146 @@ -482,6 +518,11 @@ cleanup(void)
147 XUngrabKey(dpy, AnyKey, AnyModifier, root);
148 while (mons)
149 cleanupmon(mons);
150 + if (showsystray) {
151 + XUnmapWindow(dpy, systray->win);
152 + XDestroyWindow(dpy, systray->win);
153 + free(systray);
154 + }
155 for (i = 0; i < CurLast; i++)
156 drw_cur_free(drw, cursor[i]);
157 for (i = 0; i < LENGTH(colors); i++)
158 @@ -512,9 +553,52 @@ cleanupmon(Monitor *mon)
159 void
160 clientmessage(XEvent *e)
161 {
162 + XWindowAttributes wa;
163 + XSetWindowAttributes swa;
164 XClientMessageEvent *cme = &e->xclient;
165 Client *c = wintoclient(cme->window);
166
167 + if (showsystray && cme->window == systray->win && cme->message_…
168 + /* add systray icons */
169 + if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
170 + if (!(c = (Client *)calloc(1, sizeof(Client))))
171 + die("fatal: could not malloc() %u bytes…
172 + if (!(c->win = cme->data.l[2])) {
173 + free(c);
174 + return;
175 + }
176 + c->mon = selmon;
177 + c->next = systray->icons;
178 + systray->icons = c;
179 + XGetWindowAttributes(dpy, c->win, &wa);
180 + c->x = c->oldx = c->y = c->oldy = 0;
181 + c->w = c->oldw = wa.width;
182 + c->h = c->oldh = wa.height;
183 + c->oldbw = wa.border_width;
184 + c->bw = 0;
185 + c->isfloating = True;
186 + /* reuse tags field as mapped status */
187 + c->tags = 1;
188 + updatesizehints(c);
189 + updatesystrayicongeom(c, wa.width, wa.height);
190 + XAddToSaveSet(dpy, c->win);
191 + XSelectInput(dpy, c->win, StructureNotifyMask |…
192 + XReparentWindow(dpy, c->win, systray->win, 0, 0…
193 + /* use parents background color */
194 + swa.background_pixel = scheme[SchemeNorm][ColB…
195 + XChangeWindowAttributes(dpy, c->win, CWBackPixe…
196 + sendevent(c->win, netatom[Xembed], StructureNot…
197 + /* FIXME not sure if I have to send these event…
198 + sendevent(c->win, netatom[Xembed], StructureNot…
199 + sendevent(c->win, netatom[Xembed], StructureNot…
200 + sendevent(c->win, netatom[Xembed], StructureNot…
201 + XSync(dpy, False);
202 + resizebarwin(selmon);
203 + updatesystray();
204 + setclientstate(c, NormalState);
205 + }
206 + return;
207 + }
208 if (!c)
209 return;
210 if (cme->message_type == netatom[NetWMState]) {
211 @@ -567,7 +651,7 @@ configurenotify(XEvent *e)
212 for (c = m->clients; c; c = c->next)
213 if (c->isfullscreen)
214 resizeclient(c, m->mx, …
215 - XMoveResizeWindow(dpy, m->barwin, m->wx…
216 + resizebarwin(m);
217 }
218 focus(NULL);
219 arrange(NULL);
220 @@ -652,6 +736,11 @@ destroynotify(XEvent *e)
221
222 if ((c = wintoclient(ev->window)))
223 unmanage(c, 1);
224 + else if ((c = wintosystrayicon(ev->window))) {
225 + removesystrayicon(c);
226 + resizebarwin(selmon);
227 + updatesystray();
228 + }
229 }
230
231 void
232 @@ -695,19 +784,23 @@ dirtomon(int dir)
233 void
234 drawbar(Monitor *m)
235 {
236 - int x, w, sw = 0;
237 + int x, w, sw = 0, stw = 0;
238 int boxs = drw->fonts->h / 9;
239 int boxw = drw->fonts->h / 6 + 2;
240 unsigned int i, occ = 0, urg = 0;
241 Client *c;
242
243 + if(showsystray && m == systraytomon(m))
244 + stw = getsystraywidth();
245 +
246 /* draw status first so it can be overdrawn by tags later */
247 if (m == selmon) { /* status is only drawn on selected monitor …
248 drw_setscheme(drw, scheme[SchemeNorm]);
249 - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
250 - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
251 + sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding…
252 + drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - …
253 }
254
255 + resizebarwin(m);
256 for (c = m->clients; c; c = c->next) {
257 occ |= c->tags;
258 if (c->isurgent)
259 @@ -728,7 +821,7 @@ drawbar(Monitor *m)
260 drw_setscheme(drw, scheme[SchemeNorm]);
261 x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
262
263 - if ((w = m->ww - sw - x) > bh) {
264 + if ((w = m->ww - sw - stw - x) > bh) {
265 if (m->sel) {
266 drw_setscheme(drw, scheme[m == selmon ? SchemeS…
267 drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->n…
268 @@ -739,7 +832,7 @@ drawbar(Monitor *m)
269 drw_rect(drw, x, 0, w, bh, 1, 1);
270 }
271 }
272 - drw_map(drw, m->barwin, 0, 0, m->ww, bh);
273 + drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
274 }
275
276 void
277 @@ -776,8 +869,11 @@ expose(XEvent *e)
278 Monitor *m;
279 XExposeEvent *ev = &e->xexpose;
280
281 - if (ev->count == 0 && (m = wintomon(ev->window)))
282 + if (ev->count == 0 && (m = wintomon(ev->window))) {
283 drawbar(m);
284 + if (m == selmon)
285 + updatesystray();
286 + }
287 }
288
289 void
290 @@ -862,10 +958,17 @@ getatomprop(Client *c, Atom prop)
291 unsigned long dl;
292 unsigned char *p = NULL;
293 Atom da, atom = None;
294 + /* FIXME getatomprop should return the number of items and a po…
295 + * the stored data instead of this workaround */
296 + Atom req = XA_ATOM;
297 + if (prop == xatom[XembedInfo])
298 + req = xatom[XembedInfo];
299
300 - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, Fals…
301 + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, Fals…
302 &da, &di, &dl, &dl, &p) == Success && p) {
303 atom = *(Atom *)p;
304 + if (da == xatom[XembedInfo] && dl == 2)
305 + atom = ((Atom *)p)[1];
306 XFree(p);
307 }
308 return atom;
309 @@ -899,6 +1002,16 @@ getstate(Window w)
310 return result;
311 }
312
313 +unsigned int
314 +getsystraywidth()
315 +{
316 + unsigned int w = 0;
317 + Client *i;
318 + if(showsystray)
319 + for(i = systray->icons; i; w += i->w + systrayspacing, …
320 + return w ? w + systrayspacing : 1;
321 +}
322 +
323 int
324 gettextprop(Window w, Atom atom, char *text, unsigned int size)
325 {
326 @@ -1003,7 +1116,7 @@ killclient(const Arg *arg)
327 {
328 if (!selmon->sel)
329 return;
330 - if (!sendevent(selmon->sel, wmatom[WMDelete])) {
331 + if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask,…
332 XGrabServer(dpy);
333 XSetErrorHandler(xerrordummy);
334 XSetCloseDownMode(dpy, DestroyAll);
335 @@ -1091,6 +1204,12 @@ maprequest(XEvent *e)
336 {
337 static XWindowAttributes wa;
338 XMapRequestEvent *ev = &e->xmaprequest;
339 + Client *i;
340 + if ((i = wintosystrayicon(ev->window))) {
341 + sendevent(i->win, netatom[Xembed], StructureNotifyMask,…
342 + resizebarwin(selmon);
343 + updatesystray();
344 + }
345
346 if (!XGetWindowAttributes(dpy, ev->window, &wa))
347 return;
348 @@ -1215,6 +1334,16 @@ propertynotify(XEvent *e)
349 Window trans;
350 XPropertyEvent *ev = &e->xproperty;
351
352 + if ((c = wintosystrayicon(ev->window))) {
353 + if (ev->atom == XA_WM_NORMAL_HINTS) {
354 + updatesizehints(c);
355 + updatesystrayicongeom(c, c->w, c->h);
356 + }
357 + else
358 + updatesystrayiconstate(c, ev);
359 + resizebarwin(selmon);
360 + updatesystray();
361 + }
362 if ((ev->window == root) && (ev->atom == XA_WM_NAME))
363 updatestatus();
364 else if (ev->state == PropertyDelete)
365 @@ -1265,6 +1394,20 @@ recttomon(int x, int y, int w, int h)
366 return r;
367 }
368
369 +void
370 +removesystrayicon(Client *i)
371 +{
372 + Client **ii;
373 +
374 + if (!showsystray || !i)
375 + return;
376 + for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
377 + if (ii)
378 + *ii = i->next;
379 + free(i);
380 +}
381 +
382 +
383 void
384 resize(Client *c, int x, int y, int w, int h, int interact)
385 {
386 @@ -1272,6 +1415,14 @@ resize(Client *c, int x, int y, int w, int h, int…
387 resizeclient(c, x, y, w, h);
388 }
389
390 +void
391 +resizebarwin(Monitor *m) {
392 + unsigned int w = m->ww;
393 + if (showsystray && m == systraytomon(m))
394 + w -= getsystraywidth();
395 + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
396 +}
397 +
398 void
399 resizeclient(Client *c, int x, int y, int w, int h)
400 {
401 @@ -1344,6 +1495,19 @@ resizemouse(const Arg *arg)
402 }
403 }
404
405 +void
406 +resizerequest(XEvent *e)
407 +{
408 + XResizeRequestEvent *ev = &e->xresizerequest;
409 + Client *i;
410 +
411 + if ((i = wintosystrayicon(ev->window))) {
412 + updatesystrayicongeom(i, ev->width, ev->height);
413 + resizebarwin(selmon);
414 + updatesystray();
415 + }
416 +}
417 +
418 void
419 restack(Monitor *m)
420 {
421 @@ -1433,26 +1597,36 @@ setclientstate(Client *c, long state)
422 }
423
424 int
425 -sendevent(Client *c, Atom proto)
426 +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, lo…
427 {
428 int n;
429 - Atom *protocols;
430 + Atom *protocols, mt;
431 int exists = 0;
432 XEvent ev;
433
434 - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
435 - while (!exists && n--)
436 - exists = protocols[n] == proto;
437 - XFree(protocols);
438 + if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
439 + mt = wmatom[WMProtocols];
440 + if (XGetWMProtocols(dpy, w, &protocols, &n)) {
441 + while (!exists && n--)
442 + exists = protocols[n] == proto;
443 + XFree(protocols);
444 + }
445 + }
446 + else {
447 + exists = True;
448 + mt = proto;
449 }
450 if (exists) {
451 ev.type = ClientMessage;
452 - ev.xclient.window = c->win;
453 - ev.xclient.message_type = wmatom[WMProtocols];
454 + ev.xclient.window = w;
455 + ev.xclient.message_type = mt;
456 ev.xclient.format = 32;
457 - ev.xclient.data.l[0] = proto;
458 - ev.xclient.data.l[1] = CurrentTime;
459 - XSendEvent(dpy, c->win, False, NoEventMask, &ev);
460 + ev.xclient.data.l[0] = d0;
461 + ev.xclient.data.l[1] = d1;
462 + ev.xclient.data.l[2] = d2;
463 + ev.xclient.data.l[3] = d3;
464 + ev.xclient.data.l[4] = d4;
465 + XSendEvent(dpy, w, False, mask, &ev);
466 }
467 return exists;
468 }
469 @@ -1466,7 +1640,7 @@ setfocus(Client *c)
470 XA_WINDOW, 32, PropModeReplace,
471 (unsigned char *) &(c->win), 1);
472 }
473 - sendevent(c, wmatom[WMTakeFocus]);
474 + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTa…
475 }
476
477 void
478 @@ -1555,6 +1729,10 @@ setup(void)
479 wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
480 netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW…
481 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", Fals…
482 + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0"…
483 + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_O…
484 + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYST…
485 + netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_…
486 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
487 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
488 netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHEC…
489 @@ -1562,6 +1740,9 @@ setup(void)
490 netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYP…
491 netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WIND…
492 netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", F…
493 + xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
494 + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
495 + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
496 /* init cursors */
497 cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
498 cursor[CurResize] = drw_cur_create(drw, XC_sizing);
499 @@ -1570,6 +1751,8 @@ setup(void)
500 scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
501 for (i = 0; i < LENGTH(colors); i++)
502 scheme[i] = drw_scm_create(drw, colors[i], 3);
503 + /* init system tray */
504 + updatesystray();
505 /* init bars */
506 updatebars();
507 updatestatus();
508 @@ -1701,7 +1884,18 @@ togglebar(const Arg *arg)
509 {
510 selmon->showbar = !selmon->showbar;
511 updatebarpos(selmon);
512 - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, …
513 + resizebarwin(selmon);
514 + if (showsystray) {
515 + XWindowChanges wc;
516 + if (!selmon->showbar)
517 + wc.y = -bh;
518 + else if (selmon->showbar) {
519 + wc.y = 0;
520 + if (!selmon->topbar)
521 + wc.y = selmon->mh - bh;
522 + }
523 + XConfigureWindow(dpy, systray->win, CWY, &wc);
524 + }
525 arrange(selmon);
526 }
527
528 @@ -1796,11 +1990,18 @@ unmapnotify(XEvent *e)
529 else
530 unmanage(c, 0);
531 }
532 + else if ((c = wintosystrayicon(ev->window))) {
533 + /* KLUDGE! sometimes icons occasionally unmap their win…
534 + * _not_ destroy them. We map those windows back */
535 + XMapRaised(dpy, c->win);
536 + updatesystray();
537 + }
538 }
539
540 void
541 updatebars(void)
542 {
543 + unsigned int w;
544 Monitor *m;
545 XSetWindowAttributes wa = {
546 .override_redirect = True,
547 @@ -1811,10 +2012,15 @@ updatebars(void)
548 for (m = mons; m; m = m->next) {
549 if (m->barwin)
550 continue;
551 - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->w…
552 + w = m->ww;
553 + if (showsystray && m == systraytomon(m))
554 + w -= getsystraywidth();
555 + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, b…
556 CopyFromParent, DefaultVisual(dpy, scre…
557 CWOverrideRedirect|CWBackPixmap|CWEvent…
558 XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor…
559 + if (showsystray && m == systraytomon(m))
560 + XMapRaised(dpy, systray->win);
561 XMapRaised(dpy, m->barwin);
562 XSetClassHint(dpy, m->barwin, &ch);
563 }
564 @@ -1990,6 +2196,121 @@ updatestatus(void)
565 if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
566 strcpy(stext, "dwm-"VERSION);
567 drawbar(selmon);
568 + updatesystray();
569 +}
570 +
571 +void
572 +updatesystrayicongeom(Client *i, int w, int h)
573 +{
574 + if (i) {
575 + i->h = bh;
576 + if (w == h)
577 + i->w = bh;
578 + else if (h == bh)
579 + i->w = w;
580 + else
581 + i->w = (int) ((float)bh * ((float)w / (float)h)…
582 + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), F…
583 + /* force icons into the systray dimenons if they don't …
584 + if (i->h > bh) {
585 + if (i->w == i->h)
586 + i->w = bh;
587 + else
588 + i->w = (int) ((float)bh * ((float)i->w …
589 + i->h = bh;
590 + }
591 + }
592 +}
593 +
594 +void
595 +updatesystrayiconstate(Client *i, XPropertyEvent *ev)
596 +{
597 + long flags;
598 + int code = 0;
599 +
600 + if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
601 + !(flags = getatomprop(i, xatom[XembedInfo])))
602 + return;
603 +
604 + if (flags & XEMBED_MAPPED && !i->tags) {
605 + i->tags = 1;
606 + code = XEMBED_WINDOW_ACTIVATE;
607 + XMapRaised(dpy, i->win);
608 + setclientstate(i, NormalState);
609 + }
610 + else if (!(flags & XEMBED_MAPPED) && i->tags) {
611 + i->tags = 0;
612 + code = XEMBED_WINDOW_DEACTIVATE;
613 + XUnmapWindow(dpy, i->win);
614 + setclientstate(i, WithdrawnState);
615 + }
616 + else
617 + return;
618 + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTi…
619 + systray->win, XEMBED_EMBEDDED_VERSION);
620 +}
621 +
622 +void
623 +updatesystray(void)
624 +{
625 + XSetWindowAttributes wa;
626 + XWindowChanges wc;
627 + Client *i;
628 + Monitor *m = systraytomon(NULL);
629 + unsigned int x = m->mx + m->mw;
630 + unsigned int w = 1;
631 +
632 + if (!showsystray)
633 + return;
634 + if (!systray) {
635 + /* init systray */
636 + if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
637 + die("fatal: could not malloc() %u bytes\n", siz…
638 + systray->win = XCreateSimpleWindow(dpy, root, x, m->by,…
639 + wa.event_mask = ButtonPressMask | ExposureMask;
640 + wa.override_redirect = True;
641 + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
642 + XSelectInput(dpy, systray->win, SubstructureNotifyMask);
643 + XChangeProperty(dpy, systray->win, netatom[NetSystemTra…
644 + PropModeReplace, (unsigned char *)&neta…
645 + XChangeWindowAttributes(dpy, systray->win, CWEventMask|…
646 + XMapRaised(dpy, systray->win);
647 + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray…
648 + if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == …
649 + sendevent(root, xatom[Manager], StructureNotify…
650 + XSync(dpy, False);
651 + }
652 + else {
653 + fprintf(stderr, "dwm: unable to obtain system t…
654 + free(systray);
655 + systray = NULL;
656 + return;
657 + }
658 + }
659 + for (w = 0, i = systray->icons; i; i = i->next) {
660 + /* make sure the background color stays the same */
661 + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
662 + XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
663 + XMapRaised(dpy, i->win);
664 + w += systrayspacing;
665 + i->x = w;
666 + XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
667 + w += i->w;
668 + if (i->mon != m)
669 + i->mon = m;
670 + }
671 + w = w ? w + systrayspacing : 1;
672 + x -= w;
673 + XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
674 + wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
675 + wc.stack_mode = Above; wc.sibling = m->barwin;
676 + XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CW…
677 + XMapWindow(dpy, systray->win);
678 + XMapSubwindows(dpy, systray->win);
679 + /* redraw background */
680 + XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
681 + XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
682 + XSync(dpy, False);
683 }
684
685 void
686 @@ -2057,6 +2378,16 @@ wintoclient(Window w)
687 return NULL;
688 }
689
690 +Client *
691 +wintosystrayicon(Window w) {
692 + Client *i = NULL;
693 +
694 + if (!showsystray || !w)
695 + return i;
696 + for (i = systray->icons; i && i->win != w; i = i->next) ;
697 + return i;
698 +}
699 +
700 Monitor *
701 wintomon(Window w)
702 {
703 @@ -2110,6 +2441,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
704 return -1;
705 }
706
707 +Monitor *
708 +systraytomon(Monitor *m) {
709 + Monitor *t;
710 + int i, n;
711 + if(!systraypinning) {
712 + if(!m)
713 + return selmon;
714 + return m == selmon ? m : NULL;
715 + }
716 + for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
717 + for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t…
718 + if(systraypinningfailfirst && n < systraypinning)
719 + return mons;
720 + return t;
721 +}
722 +
723 void
724 zoom(const Arg *arg)
725 {
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.