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