Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Tag win icons patch #318

Open
Vinschers opened this issue Dec 29, 2022 · 1 comment
Open

Feature request: Tag win icons patch #318

Vinschers opened this issue Dec 29, 2022 · 1 comment

Comments

@Vinschers
Copy link

Hey, I don't know it this is OK or if this is the place to do something like that, but I was wondering if I could share a patch I did some time ago and maybe add it to the project.

I am no C programmer; I just put some stuff together and it worked. I would be happy to change anything if necessary.

The basic idea of the patch is showing the icon of the main window in its tag, dynamically. Something like this.

I coded it on top of the BAR_WINICON_PATCH and tagicons patches.

This is the basic diff file for it:

diff '--color=auto' -r dwm-d/config.def.h dwm/config.def.h
146,150c146,164
< static char *tagicons[][NUMTAGS] =
< {
< 	[DEFAULT_TAGS]        = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
< 	[ALTERNATIVE_TAGS]    = { "A", "B", "C", "D", "E", "F", "G", "H", "I" },
< 	[ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" },
---
> static char *tagicons[][NUMTAGS] = {
> 	[IconsDefault]        		= { "" },
> 	[IconsVacant]        		= { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
> 	[IconsOccupied]		       	= { "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨" },
> };
> 
> static char occupiedicons[][3][50] = {
> 	{ "vim",		    "",    "#019833" },
> 	{ "neovim",		    "",    "#019833" },
>     { "htop",           "",    "#BA9FD7" },
>     { "gtop",           "",    "#BA9FD7" },
> 	{ "pdf", 		    "",    "#DC1D00" },
> 	{ "zathura", 		"",    "#DC1D00" },
> 	{ "okular", 		"",    "#DC1D00" },
> 	{ "sxiv", 		    "",    "" },
> 	{ "ncspot", 		"",    "#1DB954" },
> 	{ "spotify", 		"",    "#1DB954" },
> 	{ "zotero",		    "📚",   "" },
> 	{ "webcam",		    "犯",   "" },
diff '--color=auto' -r dwm-d/patch/bar_tagicons.c dwm/patch/bar_tagicons.c
0a1,7
> #include <ctype.h>
> #include <string.h>
> #include <stdio.h>
> #include <stdlib.h>
> 
> static char currenticons[NUMTAGS][10];
> 
2c9
< tagicon(Monitor *m, int tag)
---
> geticon(Monitor *m, int tag, int iconset)
3a11
> 	int i;
5,7c13,92
< 	if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS]))
< 		tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]);
< 	return tagicons[DEFAULT_TAGS][tagindex];
---
> 	for (i = 0; i < LENGTH(tagicons[iconset]) && tagicons[iconset][i] != NULL; ++i);
> 	if (i == 0)
> 		tagindex = 0;
> 	else if (tagindex >= i)
> 		tagindex = tagindex % i;
> 
> 	return tagicons[iconset][tagindex];
> }
> 
> void
> tolowerstr(char *dest, const char *src)
> {
> 	unsigned char *p = NULL;
> 
> 	for (p = (unsigned char *)src; *p; ++p)
> 		*(dest++) = tolower(*p);
> 	*dest = 0;
> }
> 
> char *
> gettagsuperscript(int tag)
> {
> 	switch (tag) {
> 		case 0:
> 			return "¹";
> 		case 1:
> 			return "²";
> 		case 2:
> 			return "³";
> 		case 3:
> 			return "⁴";
> 		case 4:
> 			return "⁵";
> 		case 5:
> 			return "⁶";
> 		case 6:
> 			return "⁷";
> 		case 7:
> 			return "⁸";
> 		case 8:
> 			return "⁹";
> 	}
> 
> 	return "";
> }
> 
> unsigned char
> hex_to_dec(const char *hex)
> {
>     unsigned char ret = 0;
> 
>     if (hex[0] >= 'a')
>         ret += hex[0] - 'a' + 10;
>     else
>         ret += hex[0] - '0';
>     ret <<= 4;
> 
>     if (hex[1] >= 'a')
>         ret += hex[1] - 'a' + 10;
>     else
>         ret += hex[1] - '0';
> 
>     return ret;
> }
> 
> void
> change_scheme(char *color, Clr *scheme)
> {
>     char lowercolor[10];
>     unsigned short red, green, blue;
> 
>     tolowerstr(lowercolor, color + 1); // Remove #
> 
>     red = hex_to_dec(lowercolor);
>     green = hex_to_dec(lowercolor + 2);
>     blue = hex_to_dec(lowercolor + 4);
> 
>     scheme->color.red = red << 8;
>     scheme->color.green = green << 8;
>     scheme->color.blue = blue << 8;
9a95,167
> unsigned char
> containsstr(char *str1, char *str2)
> {
>     char *ptr;
> 
>     for (ptr = str1; *ptr; ++ptr) {
>         if (ptr == str1 || *(ptr - 1) == ' ')
>             if (strncmp(ptr, str2, strlen(str2)) == 0)
>                 return 1;
>     }
> 
>     return 0;
> }
> 
> void
> setoccupiedicon(Monitor *m, int tag, Picture *img, int *imgw, int *imgh)
> {
>     Client *c;
>     unsigned short i = 0;
> 	char *tagsuperscript = gettagsuperscript(tag), lowername[200], currentname[200];
>     char *icon = currenticons[tag];
> 
>     *imgw = 0;
>     *imgh = 0;
> 
>     for (c = m->clients; c && !(c->tags & 1 << tag); c = c->next) {}
> 	if (!c) {
>         *icon = '\0';
>         return;
>     }
> 
> 	tolowerstr(lowername, c->name);
> 
> 	for (i = 0; i < LENGTH(occupiedicons); ++i) {
> 		tolowerstr(currentname, occupiedicons[i][0]);
> 
> 		if (containsstr(lowername, currentname)) {
>             sprintf(icon, "%s%s", occupiedicons[i][1], tagsuperscript);
> 
>             if (occupiedicons[i][2][0] != '\0') // if there is a new color for the icon
>                 change_scheme(occupiedicons[i][2], scheme[SchemeTagsNorm]);
> 
>             return;
> 		}
> 	}
> 
>     if (c->icon) {
>         *img = c->icon;
>         *imgw = c->icw;
>         *imgh = c->ich;
>         strcpy(icon, tagsuperscript);
>     } else {
>         strcpy(icon, geticon(m, tag, IconsOccupied));
>     }
> }
> 
> char *
> tagicon(Monitor *m, int tag, Picture *img, int *imgw, int *imgh)
> {
>     char *icon = currenticons[tag];
> 
>     change_scheme(colors[SchemeTagsNorm][0], scheme[SchemeTagsNorm]);
> 	setoccupiedicon(m, tag, img, imgw, imgh);
> 
> 	if (*icon == '\0') {
>         strcpy(icon, geticon(m, tag, IconsDefault));
> 
> 		if (TEXTW(icon) <= lrpad && m->tagset[m->seltags] & 1 << tag)
>             strcpy(icon, geticon(m, tag, IconsVacant));
> 	}
> 
> 	return icon;
> }
diff '--color=auto' -r dwm-d/patch/bar_tagicons.h dwm/patch/bar_tagicons.h
2,5c2,6
< 	DEFAULT_TAGS,
< 	ALTERNATIVE_TAGS,
< 	ALT_TAGS_DECORATION,
< };
---
> 	IconsDefault,
> 	IconsVacant,
> 	IconsOccupied,
> 	IconsLast
> }; /* icon sets */
7c8
< static char * tagicon(Monitor *m, int tag);
---
> static char * tagicon(Monitor *m, int tag, Picture *img, int *imgw, int *imgh);
diff '--color=auto' -r dwm-d/patch/bar_tags.c dwm/patch/bar_tags.c
0a1,22
> #define BAR_OFFSET 2
> 
> int
> width_tag(Bar *bar, int tag)
> {
>     Monitor *m = bar->mon;
>     int w = 0, tw, imgw, imgh;
>     Picture img;
> 
>     tw = TEXTW(tagicon(m, tag, &img, &imgw, &imgh));
> 
>     if (tw <= lrpad)
>         return 0;
> 
>     tw += imgw;
> 
>     if (tw > lrpad)
>         w += tw;
> 
>     return w;
> }
> 
7c29
< 		w += TEXTW(tagicon(bar->mon, i));
---
>         w += width_tag(bar, i);
9c31,32
< 	return w;
---
> 
> 	return w + BAR_OFFSET;
19d41
< 	Client *c;
20a43,46
> 	Client *c;
>     Picture img;
>     int imgw, imgh;
>     int offset;
27d52
< 	for (i = 0; i < NUMTAGS; i++) {
29c54,55
< 		icon = tagicon(bar->mon, i);
---
> 	for (i = 0; i < NUMTAGS; i++) {
> 		icon = tagicon(bar->mon, i, &img, &imgw, &imgh);
31a58,64
> 
>         if (imgw > 0)
>             w += imgw;
> 
>         if (w <= lrpad)
>             continue;
> 
39c72,87
< 		drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False);
---
> 
>         drw_text(drw, x, a->y, w, a->h, lrpad / 2, "", invert, False);
> 
>         if (i == 0)
>             offset = BAR_OFFSET;
>         else
>             offset = BAR_OFFSET / 2;
> 
>         if (imgw > 0) {
>             drw_text(drw, x + offset + imgw, a->y, TEXTW(icon), a->h, lrpad / 2, icon, invert, False);
>             drw_pic(drw, x + offset + lrpad / 2, a->y + (a->h - imgh)/2, imgw, imgh, img);
>         } else {
>             drw_text(drw, x + offset, a->y, w, a->h, lrpad / 2, icon, invert, False);
>             drw_text(drw, x + w, a->y, w, a->h, lrpad / 2, "", invert, False);
>         }
> 
41,42c89,94
< 		if (ulineall || m->tagset[m->seltags] & 1 << i)
< 			drw_rect(drw, x + ulinepad, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0);
---
> 		if (ulineall || m->tagset[m->seltags] & 1 << i) {
>             if (i == 0)
> 			    drw_rect(drw, x + ulinepad + offset, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0);
>             else
> 			    drw_rect(drw, x + ulinepad + offset, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0);
>         }
55c107
< 		x += TEXTW(tagicon(bar->mon, i));
---
>         x += width_tag(bar, i);
74c126
< 		x += TEXTW(tagicon(bar->mon, i));
---
>         x += width_tag(bar, i);

What do you think?

@bakkeby
Copy link
Owner

bakkeby commented Dec 30, 2022

Thanks for that. There are not a lot of novel ideas coming up for dwm these days so something new is always welcome.

To be honest I think this is likely going to be too specific to include in dwm-flexipatch, but I'll have a tinker in any case.

Some thoughts / feedback that you may consider for your personal build:

  • gettagsuperscript function - wouldn't it make more sense to use the IconsOccupied array of icons instead to hold the super scripts? (I do see that you are using those as a fallback for when there is no client icon, but that could be handled differently)
  • occupiedicons[][3][50] array - you could define the custom icon and associated colour code as client rule options
  • containsstr - maybe you want to use the strstr function which searches for a needle in a haystack (and is used in the applyrules function if you need examples)
  • change_scheme - that is an interesting way to hack the current colour scheme
  • in general it looks like you are mixing tabs and spaces, at least the diff seems a bit off

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants