sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-alttabclass-6.4.diff (9326B)


      1 diff -up a/config.def.h b/config.def.h
      2 --- a/config.def.h	2023-08-17 17:35:28.333393605 +0400
      3 +++ b/config.def.h	2023-08-17 17:24:46.724435876 +0400
      4 @@ -3,6 +3,7 @@
      5  /* alt-tab configuration */
      6  static const unsigned int tabModKey 		= 0x40;	/* if this key is hold the alt-tab functionality stays acitve. This key must be the same as key that is used to active functin altTabStart `*/
      7  static const unsigned int tabCycleKey 		= 0x17;	/* if this key is hit the alt-tab program moves one position forward in clients stack. This key must be the same as key that is used to active functin altTabStart */
      8 +static const unsigned int tabCycleKey2 		= 0x31;	/* grave key */
      9  static const unsigned int tabPosY 			= 1;	/* tab position on Y axis, 0 = bottom, 1 = center, 2 = top */
     10  static const unsigned int tabPosX 			= 1;	/* tab position on X axis, 0 = left, 1 = center, 2 = right */
     11  static const unsigned int maxWTab 			= 600;	/* tab menu width */
     12 @@ -93,7 +94,8 @@ static const Key keys[] = {
     13  	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } },
     14  	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
     15  	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
     16 -	{ Mod1Mask,             		XK_Tab,    altTabStart,	   {0} },
     17 +	{ Mod1Mask,             		XK_Tab,    altTabStart,	   {.i = 1} },
     18 +	{ Mod1Mask,             		XK_grave,  altTabStart,	   {.i = 0} },
     19  	TAGKEYS(                        XK_1,                      0)
     20  	TAGKEYS(                        XK_2,                      1)
     21  	TAGKEYS(                        XK_3,                      2)
     22 diff -up a/dwm.c b/dwm.c
     23 --- a/dwm.c	2023-08-17 17:24:19.753640383 +0400
     24 +++ b/dwm.c	2023-08-18 09:41:00.834187121 +0400
     25 @@ -87,6 +87,7 @@ typedef struct Monitor Monitor;
     26  typedef struct Client Client;
     27  struct Client {
     28  	char name[256];
     29 +	char class[256];
     30  	float mina, maxa;
     31  	int x, y, w, h;
     32  	int oldx, oldy, oldw, oldh;
     33 @@ -121,7 +122,9 @@ struct Monitor {
     34  	int mx, my, mw, mh;   /* screen size */
     35  	int wx, wy, ww, wh;   /* window area  */
     36  	int altTabN;		  /* move that many clients forward */
     37 +	int altTabNc;		  /* move that many clients forward when using tab for same class */
     38  	int nTabs;			  /* number of active clients in tag */
     39 +	int ncTabs;			  /* number of active clients under same class in tag */
     40  	int isAlt; 			  /* 1,0 */
     41  	int maxWTab;
     42  	int maxHTab;
     43 @@ -134,6 +137,7 @@ struct Monitor {
     44  	Client *sel;
     45  	Client *stack;
     46  	Client ** altsnext; /* array of all clients in the tag */
     47 +	Client ** altsnextclass;	/* array of all clients under same class in the tag */
     48  	Monitor *next;
     49  	Window barwin;
     50  	Window tabwin;
     51 @@ -245,6 +249,7 @@ static void zoom(const Arg *arg);
     52  void drawTab(int nwins, int first, Monitor *m);
     53  void altTabStart(const Arg *arg);
     54  static void altTabEnd();
     55 +static void getclassname(Client *c);
     56  
     57  /* variables */
     58  static const char broken[] = "broken";
     59 @@ -657,6 +662,7 @@ createmon(void)
     60  	m->lt[0] = &layouts[0];
     61  	m->lt[1] = &layouts[1 % LENGTH(layouts)];
     62  	m->nTabs = 0;
     63 +	m->ncTabs = 0;
     64  	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
     65  	return m;
     66  }
     67 @@ -1059,6 +1065,7 @@ manage(Window w, XWindowAttributes *wa)
     68  	c->oldbw = wa->border_width;
     69  
     70  	updatetitle(c);
     71 +	getclassname(c);
     72  	if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
     73  		c->mon = t->mon;
     74  		c->tags = t->tags;
     75 @@ -1683,7 +1690,7 @@ altTab()
     76  			selmon->altTabN = 0; /* reset altTabN */
     77  
     78  		focus(selmon->altsnext[selmon->altTabN]);
     79 -		restack(selmon);
     80 +		/* restack(selmon); */
     81  	}
     82  
     83  	/* redraw tab */
     84 @@ -1692,8 +1699,64 @@ altTab()
     85  }
     86  
     87  void
     88 +altTabClass()
     89 +{
     90 +	/* move to next window */
     91 +	if (selmon->sel != NULL) {
     92 +		selmon->altTabNc++;
     93 +		if (selmon->altTabNc >= selmon->ncTabs)
     94 +			selmon->altTabNc = 0; /* reset altTabNc */
     95 +
     96 +		focus(selmon->altsnextclass[selmon->altTabNc]);
     97 +	}
     98 +
     99 +	/* redraw tab */
    100 +	XRaiseWindow(dpy, selmon->tabwin);
    101 +	drawTab(selmon->ncTabs, 0, selmon);
    102 +}
    103 +
    104 +void
    105 +altTabShift()
    106 +{
    107 +	/* move to prev window */
    108 +	if (selmon->sel != NULL) {
    109 +		selmon->altTabN--;
    110 +		if (selmon->altTabN < 0)
    111 +			selmon->altTabN = selmon->nTabs - 1; /* reset altTabN */
    112 +
    113 +		if (selmon->altsnext[selmon->altTabN]) {
    114 +			focus(selmon->altsnext[selmon->altTabN]);
    115 +		}
    116 + 	}
    117 + 
    118 +	/* redraw tab */
    119 +	XRaiseWindow(dpy, selmon->tabwin);
    120 +	drawTab(selmon->nTabs, 0, selmon);
    121 +}
    122 + 
    123 +void
    124 +altTabShiftClass()
    125 +{
    126 +	/* move to prev window */
    127 +	if (selmon->sel != NULL) {
    128 +		selmon->altTabNc--;
    129 +		if (selmon->altTabNc < 0)
    130 +			selmon->altTabNc = selmon->ncTabs - 1; /* reset altTabNc */
    131 +
    132 +		if (selmon->altsnextclass[selmon->altTabNc]) {
    133 +			focus(selmon->altsnextclass[selmon->altTabNc]);
    134 +		}
    135 +	}
    136 +
    137 +	/* redraw tab */
    138 +	XRaiseWindow(dpy, selmon->tabwin);
    139 +	drawTab(selmon->ncTabs, 0, selmon);
    140 +}
    141 +
    142 +void
    143  altTabEnd()
    144  {
    145 +	Client *buff = NULL;
    146  	if (selmon->isAlt == 0)
    147  		return;
    148  
    149 @@ -1703,8 +1766,15 @@ altTabEnd()
    150  	* so they remain in right order for the next time that alt-tab is used
    151  	*/
    152  	if (selmon->nTabs > 1) {
    153 -		if (selmon->altTabN != 0) { /* if user picked original client do nothing */
    154 -			Client *buff = selmon->altsnext[selmon->altTabN];
    155 +		if (selmon->altTabN != 0)
    156 +			buff = selmon->altsnext[selmon->altTabN];
    157 +		else if (selmon->altTabNc != 0) {
    158 +			buff = selmon->altsnextclass[selmon->altTabNc];
    159 +			for (; selmon->altTabN < selmon->nTabs; selmon->altTabN++)
    160 +				if (selmon->altsnext[selmon->altTabN] == selmon->altsnextclass[selmon->altTabNc])
    161 +					break;
    162 +		}
    163 +		if (buff) { /* if user picked original client do nothing */
    164  			if (selmon->altTabN > 1)
    165  				for (int i = selmon->altTabN;i > 0;i--)
    166  					selmon->altsnext[i] = selmon->altsnext[i - 1];
    167 @@ -1720,6 +1790,7 @@ altTabEnd()
    168  		}
    169  
    170  		free(selmon->altsnext); /* free list of clients */
    171 +		free(selmon->altsnextclass); /* free list of clients */
    172  	}
    173  
    174  	/* turn off/destroy the window */
    175 @@ -1779,16 +1850,17 @@ drawTab(int nwins, int first, Monitor *m
    176  
    177  	}
    178  
    179 -	h = selmon->maxHTab  / m->nTabs;
    180 +	h = selmon->maxHTab / nwins;
    181  
    182  	int y = 0;
    183 -	int n = 0;
    184 -	for (int i = 0;i < m->nTabs;i++) { /* draw all clients into tabwin */
    185 -		c = m->altsnext[i];
    186 +	for (int i = 0; i < nwins; i++) { /* draw all clients into tabwin */
    187 +		if (nwins == m->nTabs)
    188 +			c = m->altsnext[i];
    189 +		else
    190 +			c = m->altsnextclass[i];
    191  		if(!ISVISIBLE(c)) continue;
    192  		/* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
    193  
    194 -		n++;
    195  		drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]);
    196  		drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0);
    197  		y += h;
    198 @@ -1801,7 +1873,6 @@ drawTab(int nwins, int first, Monitor *m
    199  void
    200  altTabStart(const Arg *arg)
    201  {
    202 -	selmon->altsnext = NULL;
    203  	if (selmon->tabwin)
    204  		altTabEnd();
    205  
    206 @@ -1810,30 +1881,47 @@ altTabStart(const Arg *arg)
    207  	} else {
    208  		selmon->isAlt = 1;
    209  		selmon->altTabN = 0;
    210 +		selmon->altTabNc = 0;
    211  
    212  		Client *c;
    213  		Monitor *m = selmon;
    214  
    215 +		char tempclass[256] = {'\0'};
    216 +		if (selmon->sel)
    217 +			strncpy(tempclass, selmon->sel->class, 256);
    218 +
    219  		m->nTabs = 0;
    220 +		m->ncTabs = 0;
    221  		for(c = m->clients; c; c = c->next) { /* count clients */
    222  			if(!ISVISIBLE(c)) continue;
    223  			/* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
    224  
    225  			++m->nTabs;
    226 +
    227 +			if (!strcmp(c->class, tempclass))
    228 +				++m->ncTabs;
    229  		}
    230  
    231  		if (m->nTabs > 0) {
    232  			m->altsnext = (Client **) malloc(m->nTabs * sizeof(Client *));
    233 +			m->altsnextclass = (Client **) malloc(m->ncTabs * sizeof(Client *));
    234  
    235  			int listIndex = 0;
    236 +			int listIndexc = 0;
    237  			for(c = m->stack; c; c = c->snext) { /* add clients to the list */
    238  				if(!ISVISIBLE(c)) continue;
    239  				/* if (HIDDEN(c)) continue; uncomment if you're using awesomebar patch */
    240  
    241  				m->altsnext[listIndex++] = c;
    242 +
    243 +				if (!strcmp(c->class, tempclass))
    244 +					m->altsnextclass[listIndexc++] = c;
    245  			}
    246  
    247 -			drawTab(m->nTabs, 1, m);
    248 +			if (arg->i)
    249 +				drawTab(m->nTabs, 1, m);
    250 +			else
    251 +				drawTab(m->ncTabs, 1, m);
    252  
    253  			struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
    254  
    255 @@ -1848,7 +1936,10 @@ altTabStart(const Arg *arg)
    256  			}
    257  
    258  			XEvent event;
    259 -			altTab();
    260 +			if (arg->i)
    261 +				altTab();
    262 +			else
    263 +				altTabClass();
    264  			if (grabbed == 0) {
    265  				altTabEnd();
    266  			} else {
    267 @@ -1858,8 +1949,19 @@ altTabStart(const Arg *arg)
    268  						if (event.type == KeyRelease && event.xkey.keycode == tabModKey) { /* if super key is released break cycle */
    269  							break;
    270  						} else if (event.type == KeyPress) {
    271 -							if (event.xkey.keycode == tabCycleKey) {/* if XK_s is pressed move to the next window */
    272 -								altTab();
    273 +							if (event.xkey.keycode == tabCycleKey || event.xkey.keycode == tabCycleKey2 ) { /* if XK_s is pressed move to the next window */
    274 +								if (arg->i) {
    275 +									if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
    276 +										altTabShift();
    277 +									else
    278 +										altTab();
    279 +								} else {
    280 +									if (CLEANMASK((Mod1Mask|ShiftMask)) == CLEANMASK(event.xkey.state))
    281 +										altTabShiftClass();
    282 +									else
    283 +										altTabClass();
    284 +								}
    285 +								
    286  							}
    287  						}
    288  					}
    289 @@ -2231,6 +2333,15 @@ updatetitle(Client *c)
    290  		strcpy(c->name, broken);
    291  }
    292  
    293 +void
    294 +getclassname(Client *c)
    295 +{
    296 +	gettextprop(c->win, XA_WM_CLASS, c->class, sizeof c->class);
    297 +
    298 +	if (c->class[0] == '\0') /* hack to mark broken clients */
    299 +		strcpy(c->name, broken);
    300 +}
    301 +
    302  void
    303  updatewindowtype(Client *c)
    304  {