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