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