On Thu, Mar 05, 2015 at 09:40:56AM +0300, Yury Shvedov wrote:
> Yep! Sometimes I have the same glitches but It doesn't hurt me. But
> absence of an icon any time the client runs distress me. I have not
> much time to investigate this too but when I will, I would look to
> the code of something like trayer or stalonetray as an example.
I ended up solving my systray problems by writing a patch that treats
systray applications as special windows. I've attached the patch to this
email, but I wrote the patch on top of my existing patch set, so it will
not apply cleanly to dwm 6.x without some work. It's a bit kludgey, and
the patch was hastily cobbled together, but I will probably refine it
later. I first used the patch with trayer, but trayer [does not allow
you to specify the amount of padding between icons][1], and the default
padding is [way too thin for my tastes. On top of that, I ran into
[Debian Bug #749031][2] which is a non-issue with stalonetray.
Here's the stalonetray invocation I'm currently using:
stalonetray -bg '#000000' -d --icon-gravity NE --grow-gravity E \
--skip-taskbar --window-layer top -i 16 \
--kludges force_icons_size --decorations none \
--geometry 1x1-0+0 --slot-size 18
[1]: https://github.com/sargon/trayer-srg/issues/16
[2]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=749031
Eric
diff --git a/dwm.c b/dwm.c
index ce232b4..aa0eb7e 100644
--- a/dwm.c
+++ b/dwm.c
@@ -52,6 +52,7 @@
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
+#define ISTRAY(C) (systrayclient && systrayclient == (C))
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
@@ -246,6 +247,7 @@ static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
static int (*xerrorxlib)(Display *, XErrorEvent *);
+static Client *systrayclient;
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
@@ -835,6 +837,9 @@ drawbar(Monitor *m) {
if(m == selmon) { /* status is only drawn on selected monitor */
w = TEXTW(stext);
x = m->ww - w;
+ if (systrayclient) {
+ x -= WIDTH(systrayclient);
+ }
if(x < xx) {
x = xx;
w = m->ww - xx;
@@ -883,7 +888,7 @@ focus(Client *c) {
if(!c || !ISVISIBLE(c)) {
if (focusbyft) {
for(i = 0, c = selmon->clients; c; c = c->next) {
- if (!ISVISIBLE(c)) {
+ if (!ISVISIBLE(c) || ISTRAY(c)) {
continue;
}
@@ -903,7 +908,7 @@ focus(Client *c) {
c = o;
focusbyft = False;
} else {
- for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
+ for(c = selmon->stack; c && (!ISVISIBLE(c) || ISTRAY(c)); c = c->snext);
}
}
/* was if(selmon->sel) */
@@ -1049,7 +1054,7 @@ grabbuttons(Client *c, Bool focused) {
unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
- if(!focused)
+ if(!focused && !ISTRAY(c))
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
for(i = 0; i < LENGTH(buttons); i++)
@@ -1160,6 +1165,11 @@ manage(Window w, XWindowAttributes *wa) {
c->mon = selmon;
applyrules(c);
}
+ if (!strcmp("stalonetray", c->name)) {
+ c->tags = 0;
+ systrayclient = c;
+ }
+
/* geometry */
c->x = c->oldx = wa->x;
c->y = c->oldy = wa->y;
@@ -1173,11 +1183,17 @@ manage(Window w, XWindowAttributes *wa) {
c->y = c->mon->my + c->mon->mh - HEIGHT(c);
c->x = MAX(c->x, c->mon->mx);
/* only fix client y-offset, if the client center might cover the bar */
- c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
- && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ if (ISTRAY(c)) {
+ c->y = 0;
+ } else {
+ c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ }
updatewindowtype(c);
- if (c->isfloating) {
+ if (c == systrayclient) {
+ c->bw = 0;
+ } else if (c->isfloating) {
c->bw = c->isfullscreen ? 0 : borderpx;
} else {
c->bw = 0;
@@ -1410,7 +1426,7 @@ resizeclient(Client *c, int x, int y, int w, int h) {
XWindowChanges wc;
c->oldx = c->x; c->x = wc.x = x;
- c->oldy = c->y; c->y = wc.y = y;
+ c->oldy = c->y; c->y = wc.y = ISTRAY(c) ? 0 : y;
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
wc.border_width = c->bw;
@@ -1719,7 +1735,7 @@ void
showhide(Client *c) {
if(!c)
return;
- if(ISVISIBLE(c)) { /* show clients top down */
+ if(ISVISIBLE(c) || ISTRAY(c)) { /* show clients top down */
if (c->isurgent) {
clearurgent(c);
}
@@ -1875,6 +1891,8 @@ unmanage(Client *c, Bool destroyed) {
XSetErrorHandler(xerror);
XUngrabServer(dpy);
}
+ if (ISTRAY(c))
+ systrayclient = NULL;
free(c);
focus(NULL);
updateclientlist();