commit 01cc1c9cfbc2fba63c3a86ef2818c5994bfd2898
Author: ViliamKovac1223 <[email protected]>
Date:   Sat Jul 9 15:10:21 2022 +0200

    add alt-tab functionality patch for dwm

diff --git a/dwm.suckless.org/patches/alt-tab/dwm-alttab-20220709-d3f93c7.diff 
b/dwm.suckless.org/patches/alt-tab/dwm-alttab-20220709-d3f93c7.diff
new file mode 100644
index 00000000..1bc77adc
--- /dev/null
+++ b/dwm.suckless.org/patches/alt-tab/dwm-alttab-20220709-d3f93c7.diff
@@ -0,0 +1,321 @@
+From ec9fcfe019623ec6aff6476b6838eb4863098cf0 Mon Sep 17 00:00:00 2001
+From: ViliamKovac1223 <[email protected]>
+Date: Sat, 9 Jul 2022 02:58:18 +0200
+Subject: [PATCH] add alt-tab functionality
+
+---
+ config.def.h |  11 ++-
+ dwm.c        | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 228 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..3760870 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -1,5 +1,13 @@
+ /* See LICENSE file for copyright and license details. */
+ 
++/* alt-tab configuration */
++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 `*/
++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 */
++static const unsigned int tabPosY                     = 1;    /* tab position 
on Y axis, 0 = bottom, 1 = center, 2 = top */
++static const unsigned int tabPosX                     = 1;    /* tab position 
on X axis, 0 = left, 1 = center, 2 = right */
++static const unsigned int maxWTab                     = 600;  /* tab menu 
width */
++static const unsigned int maxHTab                     = 200;  /* tab menu 
height */
++
+ /* appearance */
+ static const unsigned int borderpx  = 1;        /* border pixel of windows */
+ static const unsigned int snap      = 32;       /* snap pixel */
+@@ -72,7 +80,7 @@ static Key keys[] = {
+       { MODKEY,                       XK_h,      setmfact,       {.f = -0.05} 
},
+       { MODKEY,                       XK_l,      setmfact,       {.f = +0.05} 
},
+       { MODKEY,                       XK_Return, zoom,           {0} },
+-      { MODKEY,                       XK_Tab,    view,           {0} },
++      { MODKEY,                       XK_q,      view,           {0} },
+       { MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
+       { MODKEY,                       XK_t,      setlayout,      {.v = 
&layouts[0]} },
+       { MODKEY,                       XK_f,      setlayout,      {.v = 
&layouts[1]} },
+@@ -85,6 +93,7 @@ static Key keys[] = {
+       { MODKEY,                       XK_period, focusmon,       {.i = +1 } },
+       { MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
+       { MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
++      { Mod1Mask,                             XK_Tab,    altTabStart,    {0} 
},
+       TAGKEYS(                        XK_1,                      0)
+       TAGKEYS(                        XK_2,                      1)
+       TAGKEYS(                        XK_3,                      2)
+diff --git a/dwm.c b/dwm.c
+index 5646a5c..90edf9b 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -40,6 +40,7 @@
+ #include <X11/extensions/Xinerama.h>
+ #endif /* XINERAMA */
+ #include <X11/Xft/Xft.h>
++#include <time.h>
+ 
+ #include "drw.h"
+ #include "util.h"
+@@ -119,6 +120,11 @@ struct Monitor {
+       int by;               /* bar geometry */
+       int mx, my, mw, mh;   /* screen size */
+       int wx, wy, ww, wh;   /* window area  */
++      int altTabN;              /* move that many clients forward */
++      int nTabs;                        /* number of active clients in tag */
++      int isAlt;                        /* 1,0 */
++      int maxWTab;
++      int maxHTab;
+       unsigned int seltags;
+       unsigned int sellt;
+       unsigned int tagset[2];
+@@ -127,8 +133,10 @@ struct Monitor {
+       Client *clients;
+       Client *sel;
+       Client *stack;
++      Client ** altsnext; /* array of all clients in the tag */
+       Monitor *next;
+       Window barwin;
++      Window tabwin;
+       const Layout *lt[2];
+ };
+ 
+@@ -234,6 +242,9 @@ static int xerror(Display *dpy, XErrorEvent *ee);
+ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
++void drawTab(int nwins, int first, Monitor *m);
++void altTabStart(const Arg *arg);
++static void altTabEnd();
+ 
+ /* variables */
+ static const char broken[] = "broken";
+@@ -477,6 +488,7 @@ cleanup(void)
+       Monitor *m;
+       size_t i;
+ 
++      altTabEnd();
+       view(&a);
+       selmon->lt[selmon->sellt] = &foo;
+       for (m = mons; m; m = m->next)
+@@ -644,6 +656,7 @@ createmon(void)
+       m->topbar = topbar;
+       m->lt[0] = &layouts[0];
+       m->lt[1] = &layouts[1 % LENGTH(layouts)];
++      m->nTabs = 0;
+       strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+       return m;
+ }
+@@ -1659,6 +1672,211 @@ spawn(const Arg *arg)
+       }
+ }
+ 
++void
++altTab()
++{
++      /* move to next window */
++      if (selmon->sel != NULL && selmon->sel->snext != NULL) {
++              selmon->altTabN++;
++              if (selmon->altTabN >= selmon->nTabs)
++                      selmon->altTabN = 0; /* reset altTabN */
++              
++              focus(selmon->altsnext[selmon->altTabN]);
++              restack(selmon);
++      }
++
++      /* redraw tab */
++      XRaiseWindow(dpy, selmon->tabwin);
++      drawTab(selmon->nTabs, 0, selmon);
++}
++
++void
++altTabEnd()
++{
++      if (selmon->isAlt == 0)
++              return;
++
++      /* 
++      * move all clients between 1st and choosen position,
++      * one down in stack and put choosen client to the first position 
++      * so they remain in right order for the next time that alt-tab is used
++      */
++      if (selmon->nTabs > 1) {
++              if (selmon->altTabN != 0) { /* if user picked original client 
do nothing */
++                      Client *buff = selmon->altsnext[selmon->altTabN];
++                      if (selmon->altTabN > 1)
++                              for (int i = selmon->altTabN;i > 0;i--)
++                                      selmon->altsnext[i] = 
selmon->altsnext[i - 1];
++                      else /* swap them if there are just 2 clients */
++                              selmon->altsnext[selmon->altTabN] = 
selmon->altsnext[0];
++                      selmon->altsnext[0] = buff;
++              }
++
++              /* restack clients */
++              for (int i = selmon->nTabs - 1;i >= 0;i--) {
++                      focus(selmon->altsnext[i]);
++                      restack(selmon);
++              }
++
++              free(selmon->altsnext); /* free list of clients */
++      }
++
++      /* turn off/destroy the window */
++      selmon->isAlt = 0;
++      selmon->nTabs = 0;
++      XUnmapWindow(dpy, selmon->tabwin);
++      XDestroyWindow(dpy, selmon->tabwin);
++}
++
++void
++drawTab(int nwins, int first, Monitor *m)
++{
++      /* little documentation of functions */
++      /* void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int 
h, int filled, int invert); */
++      /* int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, 
unsigned int lpad, const char *text, int invert); */
++      /* void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, 
unsigned int h); */
++
++      Client *c;
++      int h;
++
++      if (first) {
++              Monitor *m = selmon;
++              XSetWindowAttributes wa = {
++                      .override_redirect = True,
++                      .background_pixmap = ParentRelative,
++                      .event_mask = ButtonPressMask|ExposureMask
++              };
++
++              selmon->maxWTab = maxWTab;
++              selmon->maxHTab = maxHTab;
++
++              /* decide position of tabwin */
++              int posX = 0;
++              int posY = 0;
++              if (tabPosX == 0)
++                      posX = 0;
++              if (tabPosX == 1)
++                      posX = (selmon->mw / 2) - (maxWTab / 2);
++              if (tabPosX == 2)
++                      posX = selmon->mw - maxWTab;
++
++              if (tabPosY == 0)
++                      posY = selmon->mh - maxHTab;
++              if (tabPosY == 1)
++                      posY = (selmon->mh / 2) - (maxHTab / 2);
++              if (tabPosY == 2)
++                      posY = 0;
++
++              h = selmon->maxHTab;
++              /* XCreateWindow(display, parent, x, y, width, height, 
border_width, depth, class, visual, valuemask, attributes); just reference */
++              m->tabwin = XCreateWindow(dpy, root, posX, posY, 
selmon->maxWTab, selmon->maxHTab, 2, DefaultDepth(dpy, screen),
++                                                              CopyFromParent, 
DefaultVisual(dpy, screen),
++                                                              
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); /* create tabwin */
++
++              XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor);
++              XMapRaised(dpy, m->tabwin);
++
++      }
++
++      h = selmon->maxHTab  / m->nTabs;
++
++      int y = 0;
++      int n = 0;
++      for (int i = 0;i < m->nTabs;i++) { /* draw all clients into tabwin */
++              c = m->altsnext[i];
++              if(!ISVISIBLE(c)) continue;
++              /* if (HIDDEN(c)) continue; uncomment if you're using 
awesomebar patch */
++
++              n++;
++              drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : 
SchemeNorm]);
++              drw_text(drw, 0, y, selmon->maxWTab, h, 0, c->name, 0);
++              y += h;
++      }
++
++      drw_setscheme(drw, scheme[SchemeNorm]);
++      drw_map(drw, m->tabwin, 0, 0, selmon->maxWTab, selmon->maxHTab);
++}
++
++void
++altTabStart(const Arg *arg)
++{
++      selmon->altsnext = NULL;
++      if (selmon->tabwin)
++              altTabEnd();
++
++      if (selmon->isAlt == 1) {
++              altTabEnd();
++      } else {
++              selmon->isAlt = 1;
++              selmon->altTabN = 0;
++
++              Client *c;
++              Monitor *m = selmon;
++
++              m->nTabs = 0;
++              for(c = m->clients; c; c = c->next) { /* count clients */
++                      if(!ISVISIBLE(c)) continue;
++                      /* if (HIDDEN(c)) continue; uncomment if you're using 
awesomebar patch */
++
++                      ++m->nTabs;
++              }
++
++              if (m->nTabs > 0) {
++                      m->altsnext = (Client **) malloc(m->nTabs * 
sizeof(Client *));
++
++                      int listIndex = 0;
++                      for(c = m->stack; c; c = c->snext) { /* add clients to 
the list */
++                              if(!ISVISIBLE(c)) continue;
++                              /* if (HIDDEN(c)) continue; uncomment if you're 
using awesomebar patch */
++
++                              m->altsnext[listIndex++] = c;
++                      }
++
++                      drawTab(m->nTabs, 1, m);
++
++                      struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 
};
++
++                      /* grab keyboard (take all input from keyboard) */
++                      int grabbed = 1;
++                      for (int i = 0;i < 1000;i++) {
++                              if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), 
True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
++                                      break;
++                              nanosleep(&ts, NULL);
++                              if (i == 1000 - 1)
++                                      grabbed = 0;
++                      }
++
++                      XEvent event;
++                      altTab();
++                      if (grabbed == 0) {
++                              altTabEnd();
++                      } else {
++                              while (grabbed) {
++                                      XNextEvent(dpy, &event);
++                                      if (event.type == KeyPress || 
event.type == KeyRelease) {
++                                              if (event.type == KeyRelease && 
event.xkey.keycode == tabModKey) { /* if super key is released break cycle */
++                                                      break;
++                                              } else if (event.type == 
KeyPress) {
++                                                      if (event.xkey.keycode 
== tabCycleKey) {/* if XK_s is pressed move to the next window */
++                                                              altTab();
++                                                      }
++                                              }
++                                      }
++                              }
++
++                              c = selmon->sel; 
++                              altTabEnd(); /* end the alt-tab functionality */
++                              /* XUngrabKeyboard(display, time); just a 
reference */
++                              XUngrabKeyboard(dpy, CurrentTime); /* stop 
taking all input from keyboard */
++                              focus(c);
++                              restack(selmon);
++                      }
++              } else {
++                      altTabEnd(); /* end the alt-tab functionality */
++              }
++      }
++}
++
+ void
+ tag(const Arg *arg)
+ {
+-- 
+2.35.1
+
diff --git a/dwm.suckless.org/patches/alt-tab/get-xkey.c 
b/dwm.suckless.org/patches/alt-tab/get-xkey.c
new file mode 100644
index 00000000..76b80f8d
--- /dev/null
+++ b/dwm.suckless.org/patches/alt-tab/get-xkey.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+ 
+int main(void) {
+       Display *dpy;
+       Window win;
+       XEvent e;
+       int s;
+ 
+       dpy = XOpenDisplay(NULL);
+       if (dpy == NULL) {
+               fprintf(stderr, "Cannot open display
");
+               exit(1);
+       }
+ 
+       s = DefaultScreen(dpy);
+       win = XCreateSimpleWindow(dpy, RootWindow(dpy, s), 10, 10, 100, 100, 0, 
0, 0);
+       XSelectInput(dpy, win, ExposureMask | KeyPressMask);
+       XMapWindow(dpy, win);
+ 
+       while (1) {
+               XNextEvent(dpy, &e);
+               if (e.type == KeyPress)
+                       printf("0x%x
",e.xkey.keycode);
+       }
+ 
+   XCloseDisplay(dpy);
+   return 0;
+}
diff --git a/dwm.suckless.org/patches/alt-tab/index.md 
b/dwm.suckless.org/patches/alt-tab/index.md
new file mode 100644
index 00000000..37c281c0
--- /dev/null
+++ b/dwm.suckless.org/patches/alt-tab/index.md
@@ -0,0 +1,50 @@
+Alt-tab
+=======
+
+Description
+-----------
+This patch add alt-tab like functionality to dwm.
+It cycles through windows/clients in their recently used order.
+
+Configuration Options
+---------------------
+* `tabModKey` - 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 
+* `tabCycleKey` - 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
+* `tabPosY` - Tab position on Y axis, 0 = bottom, 1 = center, 2 = top
+* `tabPosX` - Tab position on X axis, 0 = left, 1 = center, 2 = right
+* `maxWTab` - Tab menu width
+* `maxHTab` - Tab menu height
+
+keycode
+-------
+tabModkye and tabCycleKey are keycodes values.
+If you want to change them you can get different keycode values from 
"get-xkey" program bellow.
+
+Compile get-xkey
+```
+# compile
+gcc get-xkey.c -L/usr/X11R6/lib -lX11 -o get-xkey
+# run
+./get-xkey
+```
+Now just press desired key and watch output in stdout.
+To quit program just close the window or in the terminal press Ctrl+c.
+
+Notes
+-----
+This patch is also hosted on my 
[github](https://github.com/ViliamKovac1223/dwm-ViliamKovac1223-build/tree/main/patches).
+
+Download
+--------
+* [dwm-alttab-20220709-d3f93c7.diff](dwm-alttab-20220709-d3f93c7.diff)
+* [get-xkey.c](get-xkey.c)
+
+Authors
+-------
+* Viliam Kováč - [email protected]
+
+Fake Internet money
+-------------------
+If you like my work and want to support me by some fake internet money, here 
is my monero address
+
+85EVKkDnQMYZxmJ7Fj5dG6Lw9V3vZRxAjft3btaB2FhzTCGoGocbRTAS857tgZvy1QD5cShxxp98S6y3utG3nqMTVARnW8P


Reply via email to