204 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						|
static Systray *systray = NULL;
 | 
						|
static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
 | 
						|
 | 
						|
unsigned int
 | 
						|
getsystraywidth()
 | 
						|
{
 | 
						|
	unsigned int w = 0;
 | 
						|
	Client *i;
 | 
						|
	if (showsystray)
 | 
						|
		for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
 | 
						|
	return w ? w + systrayspacing : 0;
 | 
						|
}
 | 
						|
 | 
						|
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();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
Monitor *
 | 
						|
systraytomon(Monitor *m)
 | 
						|
{
 | 
						|
	Monitor *t;
 | 
						|
	int i, n;
 | 
						|
	if (!systraypinning) {
 | 
						|
		if (!m)
 | 
						|
			return selmon;
 | 
						|
		return m == selmon ? m : NULL;
 | 
						|
	}
 | 
						|
	for (n = 1, t = mons; t && t->next; n++, t = t->next) ;
 | 
						|
	for (i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
 | 
						|
	if (systraypinningfailfirst && n < systraypinning)
 | 
						|
		return mons;
 | 
						|
	return t;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
updatesystray(void)
 | 
						|
{
 | 
						|
	XSetWindowAttributes wa;
 | 
						|
	XWindowChanges wc;
 | 
						|
	Client *i;
 | 
						|
	Monitor *m = systraytomon(NULL);
 | 
						|
	unsigned int x = m->mx + m->mw;
 | 
						|
	unsigned int w = 1, xpad = 0, ypad = 0;
 | 
						|
	#if BARPADDING_PATCH
 | 
						|
	xpad = sp;
 | 
						|
	ypad = vp;
 | 
						|
	#endif // BARPADDING_PATCH
 | 
						|
 | 
						|
	if (!showsystray)
 | 
						|
		return;
 | 
						|
	if (!systray) {
 | 
						|
		/* init systray */
 | 
						|
		if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
 | 
						|
			die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
 | 
						|
 | 
						|
		wa.override_redirect = True;
 | 
						|
		wa.event_mask = ButtonPressMask|ExposureMask;
 | 
						|
		wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
 | 
						|
		wa.border_pixel = 0;
 | 
						|
		#if ALPHA_PATCH
 | 
						|
		wa.colormap = cmap;
 | 
						|
		systray->win = XCreateWindow(dpy, root, x - xpad, m->by + ypad, w, bh, 0, depth,
 | 
						|
						InputOutput, visual,
 | 
						|
						CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa);
 | 
						|
		#else
 | 
						|
		systray->win = XCreateSimpleWindow(dpy, root, x - xpad, m->by + ypad, w, bh, 0, 0, scheme[SchemeNorm][ColBg].pixel);
 | 
						|
		XChangeWindowAttributes(dpy, systray->win, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &wa);
 | 
						|
		#endif // ALPHA_PATCH
 | 
						|
		XSelectInput(dpy, systray->win, SubstructureNotifyMask);
 | 
						|
		XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
 | 
						|
				PropModeReplace, (unsigned char *)&systrayorientation, 1);
 | 
						|
		#if ALPHA_PATCH
 | 
						|
		XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32,
 | 
						|
				PropModeReplace, (unsigned char *)&visual->visualid, 1);
 | 
						|
		#endif // 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;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	drw_setscheme(drw, scheme[SchemeNorm]);
 | 
						|
	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 = w;
 | 
						|
		XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
 | 
						|
		w += i->w;
 | 
						|
		if (i->mon != m)
 | 
						|
			i->mon = m;
 | 
						|
	}
 | 
						|
	w = w ? w + systrayspacing : 1;
 | 
						|
 	x -= w;
 | 
						|
	XMoveResizeWindow(dpy, systray->win, x - xpad, m->by + ypad, w, bh);
 | 
						|
	wc.x = x - xpad;
 | 
						|
	wc.y = m->by + ypad;
 | 
						|
	wc.width = w;
 | 
						|
	wc.height = bh;
 | 
						|
	wc.stack_mode = Above; wc.sibling = m->barwin;
 | 
						|
	XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
 | 
						|
	XMapWindow(dpy, systray->win);
 | 
						|
	XMapSubwindows(dpy, systray->win);
 | 
						|
	/* redraw background */
 | 
						|
	XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
 | 
						|
	XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
 | 
						|
	XSync(dpy, False);
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
} |