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