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