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