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