summaryrefslogtreecommitdiff
path: root/patch/bar_systray.c
diff options
context:
space:
mode:
authorBear <bear@bengtsson.win>2021-12-27 09:29:58 +0000
committerBear <bear@bengtsson.win>2021-12-27 09:29:58 +0000
commit69262b01ced79c2d776fab9b889926d1816a1e7a (patch)
treef304cd6fa8734e83a7772d07dc9b484781565155 /patch/bar_systray.c
Added DWM
Diffstat (limited to 'patch/bar_systray.c')
-rw-r--r--patch/bar_systray.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/patch/bar_systray.c b/patch/bar_systray.c
new file mode 100644
index 0000000..67d1d2d
--- /dev/null
+++ b/patch/bar_systray.c
@@ -0,0 +1,198 @@
+static Systray *systray = NULL;
+static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
+
+int
+width_systray(Bar *bar, BarArg *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 + lrpad - systrayspacing : 0;
+}
+
+int
+draw_systray(Bar *bar, BarArg *a)
+{
+ if (!showsystray)
+ return 0;
+
+ XSetWindowAttributes wa;
+ XWindowChanges wc;
+ Client *i;
+ unsigned int w;
+
+ 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.border_pixel = 0;
+ systray->h = MIN(a->h, drw->fonts->h);
+ #if BAR_ALPHA_PATCH
+ wa.background_pixel = 0;
+ wa.colormap = cmap;
+ systray->win = XCreateWindow(dpy, root, bar->bx + a->x + lrpad / 2, bar->by + a->y + (a->h - systray->h) / 2, MAX(a->w + 40, 1), systray->h, 0, depth,
+ InputOutput, visual,
+ CWOverrideRedirect|CWBorderPixel|CWBackPixel|CWColormap|CWEventMask, &wa); // CWBackPixmap
+ #else
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ systray->win = XCreateSimpleWindow(dpy, root, bar->bx + a->x + lrpad / 2, bar->by + a->y + (a->h - systray->h) / 2, MIN(a->w, 1), systray->h, 0, 0, scheme[SchemeNorm][ColBg].pixel);
+ XChangeWindowAttributes(dpy, systray->win, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &wa);
+ #endif // BAR_ALPHA_PATCH
+
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
+ 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 0;
+ }
+ }
+
+ systray->bar = bar;
+
+ wc.stack_mode = Above;
+ wc.sibling = bar->win;
+ XConfigureWindow(dpy, systray->win, CWSibling|CWStackMode, &wc);
+
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ for (w = 0, i = systray->icons; i; i = i->next) {
+ #if BAR_ALPHA_PATCH
+ wa.background_pixel = 0;
+ #else
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ #endif // BAR_ALPHA_PATCH
+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
+ XMapRaised(dpy, i->win);
+ i->x = w;
+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
+ w += i->w;
+ if (i->next)
+ w += systrayspacing;
+ if (i->mon != bar->mon)
+ i->mon = bar->mon;
+ }
+
+ XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by + a->y + (a->h - systray->h) / 2: -bar->by - a->y), MAX(w, 1), systray->h);
+ return w;
+}
+
+int
+click_systray(Bar *bar, Arg *arg, BarArg *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);
+ drawbarwin(systray->bar);
+}
+
+void
+resizerequest(XEvent *e)
+{
+ XResizeRequestEvent *ev = &e->xresizerequest;
+ Client *i;
+
+ if ((i = wintosystrayicon(ev->window))) {
+ updatesystrayicongeom(i, ev->width, ev->height);
+ drawbarwin(systray->bar);
+ }
+}
+
+void
+updatesystrayicongeom(Client *i, int w, int h)
+{
+ if (!systray)
+ return;
+
+ int icon_height = systray->h;
+ if (i) {
+ i->h = icon_height;
+ if (w == h)
+ i->w = icon_height;
+ else if (h == icon_height)
+ i->w = w;
+ else
+ i->w = (int) ((float)icon_height * ((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 > icon_height) {
+ if (i->w == i->h)
+ i->w = icon_height;
+ else
+ i->w = (int) ((float)icon_height * ((float)i->w / (float)i->h));
+ i->h = icon_height;
+ }
+ if (i->w > 2 * icon_height)
+ i->w = icon_height;
+ }
+}
+
+void
+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
+{
+ long flags;
+ int code = 0;
+
+ if (!showsystray || !systray || !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)
+{
+ if (!systray)
+ return NULL;
+ Client *i = NULL;
+ if (!showsystray || !w)
+ return i;
+ for (i = systray->icons; i && i->win != w; i = i->next);
+ return i;
+}
+