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