dwm

Kris's build of dwm
git clone git clone https://git.krisyotam.com/krisyotam/dwm.git
Log | Files | Refs | README | LICENSE

bar_systray.c (5654B)


      1 static Systray *systray = NULL;
      2 static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
      3 
      4 int
      5 width_systray(Bar *bar, BarArg *a)
      6 {
      7 	unsigned int w = 0;
      8 	Client *i;
      9 	if (!systray)
     10 		return 1;
     11 	if (showsystray) {
     12 		for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
     13 		if (!w)
     14 			XMoveWindow(dpy, systray->win, -systray->h, bar->by);
     15 	}
     16 	return w ? w + lrpad - systrayspacing : 0;
     17 }
     18 
     19 int
     20 draw_systray(Bar *bar, BarArg *a)
     21 {
     22 	if (!showsystray)
     23 		return 0;
     24 
     25 	XSetWindowAttributes wa;
     26 	XWindowChanges wc;
     27 	Client *i;
     28 	unsigned int w;
     29 
     30 	if (!systray) {
     31 		/* init systray */
     32 		if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
     33 			die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
     34 
     35 		wa.override_redirect = True;
     36 		wa.event_mask = ButtonPressMask|ExposureMask;
     37 		wa.border_pixel = 0;
     38 		systray->h = MIN(a->h, drw->fonts->h);
     39 		#if BAR_ALPHA_PATCH
     40 		wa.background_pixel = 0;
     41 		wa.colormap = cmap;
     42 		systray->win = XCreateWindow(dpy, root, bar->bx + a->x + lrpad / 2, -systray->h, MAX(a->w + 40, 1), systray->h, 0, depth,
     43 						InputOutput, visual,
     44 						CWOverrideRedirect|CWBorderPixel|CWBackPixel|CWColormap|CWEventMask, &wa); // CWBackPixmap
     45 		#else
     46 		wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
     47 		systray->win = XCreateSimpleWindow(dpy, root, bar->bx + a->x + lrpad / 2, -systray->h, MIN(a->w, 1), systray->h, 0, 0, scheme[SchemeNorm][ColBg].pixel);
     48 		XChangeWindowAttributes(dpy, systray->win, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &wa);
     49 		#endif // BAR_ALPHA_PATCH
     50 
     51 		XSelectInput(dpy, systray->win, SubstructureNotifyMask);
     52 		XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
     53 				PropModeReplace, (unsigned char *)&systrayorientation, 1);
     54 		#if BAR_ALPHA_PATCH
     55 		XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32,
     56 				PropModeReplace, (unsigned char *)&visual->visualid, 1);
     57 		#endif // BAR_ALPHA_PATCH
     58 		XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32,
     59 				PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1);
     60 		XMapRaised(dpy, systray->win);
     61 		XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
     62 		if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
     63 			sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
     64 			XSync(dpy, False);
     65 		} else {
     66 			fprintf(stderr, "dwm: unable to obtain system tray.\n");
     67 			free(systray);
     68 			systray = NULL;
     69 			return 0;
     70 		}
     71 	}
     72 
     73 	systray->bar = bar;
     74 
     75 	wc.stack_mode = Above;
     76 	wc.sibling = bar->win;
     77 	XConfigureWindow(dpy, systray->win, CWSibling|CWStackMode, &wc);
     78 
     79 	drw_setscheme(drw, scheme[SchemeNorm]);
     80 	for (w = 0, i = systray->icons; i; i = i->next) {
     81 		#if BAR_ALPHA_PATCH
     82 		wa.background_pixel = 0;
     83 		#else
     84 		wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
     85 		#endif // BAR_ALPHA_PATCH
     86 		XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
     87 		XMapRaised(dpy, i->win);
     88 		i->x = w;
     89 		XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
     90 		w += i->w;
     91 		if (i->next)
     92 			w += systrayspacing;
     93 		if (i->mon != bar->mon)
     94 			i->mon = bar->mon;
     95 	}
     96 
     97 	#if !BAR_ALPHA_PATCH
     98 	wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
     99 	XChangeWindowAttributes(dpy, systray->win, CWBackPixel, &wa);
    100 	XClearWindow(dpy, systray->win);
    101 	#endif // BAR_ALPHA_PATCH
    102 
    103 	XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by + a->y + (a->h - systray->h) / 2: -systray->h), MAX(w, 1), systray->h);
    104 	return w;
    105 }
    106 
    107 int
    108 click_systray(Bar *bar, Arg *arg, BarArg *a)
    109 {
    110 	return -1;
    111 }
    112 
    113 void
    114 removesystrayicon(Client *i)
    115 {
    116 	Client **ii;
    117 
    118 	if (!showsystray || !i)
    119 		return;
    120 	for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
    121 	if (ii)
    122 		*ii = i->next;
    123 	XReparentWindow(dpy, i->win, root, 0, 0);
    124 	free(i);
    125 	drawbarwin(systray->bar);
    126 }
    127 
    128 void
    129 resizerequest(XEvent *e)
    130 {
    131 	XResizeRequestEvent *ev = &e->xresizerequest;
    132 	Client *i;
    133 
    134 	if ((i = wintosystrayicon(ev->window))) {
    135 		updatesystrayicongeom(i, ev->width, ev->height);
    136 		drawbarwin(systray->bar);
    137 	}
    138 }
    139 
    140 void
    141 updatesystrayicongeom(Client *i, int w, int h)
    142 {
    143 	if (!systray)
    144 		return;
    145 
    146 	int icon_height = systray->h;
    147 	if (i) {
    148 		i->h = icon_height;
    149 		if (w == h)
    150 			i->w = icon_height;
    151 		else if (h == icon_height)
    152 			i->w = w;
    153 		else
    154 			i->w = (int) ((float)icon_height * ((float)w / (float)h));
    155 		applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
    156 		/* force icons into the systray dimensions if they don't want to */
    157 		if (i->h > icon_height) {
    158 			if (i->w == i->h)
    159 				i->w = icon_height;
    160 			else
    161 				i->w = (int) ((float)icon_height * ((float)i->w / (float)i->h));
    162 			i->h = icon_height;
    163 		}
    164 		if (i->w > 2 * icon_height)
    165 			i->w = icon_height;
    166 	}
    167 }
    168 
    169 void
    170 updatesystrayiconstate(Client *i, XPropertyEvent *ev)
    171 {
    172 	long flags;
    173 	int code = 0;
    174 
    175 	if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] ||
    176 			!(flags = getatomprop(i, xatom[XembedInfo], xatom[XembedInfo])))
    177 		return;
    178 
    179 	if (flags & XEMBED_MAPPED && !i->tags) {
    180 		i->tags = 1;
    181 		code = XEMBED_WINDOW_ACTIVATE;
    182 		XMapRaised(dpy, i->win);
    183 		setclientstate(i, NormalState);
    184 	}
    185 	else if (!(flags & XEMBED_MAPPED) && i->tags) {
    186 		i->tags = 0;
    187 		code = XEMBED_WINDOW_DEACTIVATE;
    188 		XUnmapWindow(dpy, i->win);
    189 		setclientstate(i, WithdrawnState);
    190 	}
    191 	else
    192 		return;
    193 	sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
    194 			systray->win, XEMBED_EMBEDDED_VERSION);
    195 }
    196 
    197 Client *
    198 wintosystrayicon(Window w)
    199 {
    200 	if (!systray)
    201 		return NULL;
    202 	Client *i = NULL;
    203 	if (!showsystray || !w)
    204 		return i;
    205 	for (i = systray->icons; i && i->win != w; i = i->next);
    206 	return i;
    207 }
    208