You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dwm-flexipatch/patch/bar_systray.c

194 lines
4.6 KiB
C

static Systray *systray = NULL;
static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
static int systraybaridx = -1;
static int systraybarrule = -1;
static int systrayxpos = 0;
int
width_systray(Monitor *m, BarWidthArg *a)
{
unsigned int w = 0;
Client *i;
if (!systray)
return 1;
if (showsystray)
for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
return w ? w + systrayspacing : 0;
}
int
draw_systray(Monitor *m, BarDrawArg *a)
{
systrayxpos = a->x;
updatesystray();
return systrayxpos + a->w;
}
int
click_systray(Monitor *m, Arg *arg, BarClickArg *a)
{
return -1;
}
void
removesystrayicon(Client *i)
{
Client **ii;
if (!showsystray || !i)
return;
for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
if (ii)
*ii = i->next;
free(i);
}
void
resizerequest(XEvent *e)
{
XResizeRequestEvent *ev = &e->xresizerequest;
Client *i;
if ((i = wintosystrayicon(ev->window))) {
updatesystrayicongeom(i, ev->width, ev->height);
updatesystray();
}
}
void
updatesystray(void)
{
if (!showsystray)
return;
XSetWindowAttributes wa;
Client *i;
Monitor *m;
unsigned int w = 1, r, mi;
const BarRule *br;
if (!systray) {
/* init systray */
if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
/* Work out which bar the systray is to be displayed on */
for (r = 0; r < LENGTH(barrules); r++) {
br = &barrules[r];
if (br->drawfunc == &draw_systray) {
systraybaridx = br->bar;
systraybarrule = r;
if (br->monitor == -1 || br->monitor == 'A')
m = selmon;
else
for (m = mons, mi = 0; m && mi < br->monitor && m->next; m = m->next, mi++);
systray->win = m->bars[systraybaridx]->win;
systray->mon = m;
break;
}
}
if (systraybaridx == -1) {
fprintf(stderr, "dwm: unable to obtain system tray, no draw_systray in bar rules.\n");
free(systray);
systray = NULL;
return;
}
XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&systrayorientation, 1);
#if BAR_ALPHA_PATCH
XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32,
PropModeReplace, (unsigned char *)&visual->visualid, 1);
#endif // BAR_ALPHA_PATCH
XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32,
PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1);
XMapRaised(dpy, systray->win);
XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
XSync(dpy, False);
} else {
fprintf(stderr, "dwm: unable to obtain system tray.\n");
free(systray);
systray = NULL;
return;
}
}
for (w = 0, i = systray->icons; i; i = i->next) {
/* make sure the background color stays the same */
wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
XMapRaised(dpy, i->win);
w += systrayspacing;
i->x = systrayxpos + w;
XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
w += i->w;
if (i->mon != systray->mon)
i->mon = systray->mon;
}
}
void
updatesystrayicongeom(Client *i, int w, int h)
{
if (i) {
i->h = bh;
if (w == h)
i->w = bh;
else if (h == bh)
i->w = w;
else
i->w = (int) ((float)bh * ((float)w / (float)h));
applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
/* force icons into the systray dimensions if they don't want to */
if (i->h > bh) {
if (i->w == i->h)
i->w = bh;
else
i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
i->h = bh;
}
if (i->w > 2*bh)
i->w = bh;
}
}
void
updatesystrayiconstate(Client *i, XPropertyEvent *ev)
{
long flags;
int code = 0;
if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
!(flags = getatomprop(i, xatom[XembedInfo])))
return;
if (flags & XEMBED_MAPPED && !i->tags) {
i->tags = 1;
code = XEMBED_WINDOW_ACTIVATE;
XMapRaised(dpy, i->win);
setclientstate(i, NormalState);
}
else if (!(flags & XEMBED_MAPPED) && i->tags) {
i->tags = 0;
code = XEMBED_WINDOW_DEACTIVATE;
XUnmapWindow(dpy, i->win);
setclientstate(i, WithdrawnState);
}
else
return;
sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
systray->win, XEMBED_EMBEDDED_VERSION);
}
Client *
wintosystrayicon(Window w)
{
Client *i = NULL;
if (!showsystray || !w)
return i;
for (i = systray->icons; i && i->win != w; i = i->next);
return i;
}