commit 58e164fcad444582bf29fbe744cdd03c9fd14adb
Author: explosion-mental <[email protected]>
Date:   Thu Sep 1 11:41:14 2022 -0500

    [patch][dwm] add tag preview for 6.3

diff --git a/dwm.suckless.org/patches/tag-previews/dwm-tag-preview-6.3.diff 
b/dwm.suckless.org/patches/tag-previews/dwm-tag-preview-6.3.diff
new file mode 100644
index 00000000..92f4ad0a
--- /dev/null
+++ b/dwm.suckless.org/patches/tag-previews/dwm-tag-preview-6.3.diff
@@ -0,0 +1,278 @@
+From 0e8deaa65e5193815a883bd1b9f9f74b97d68186 Mon Sep 17 00:00:00 2001
+From: explosion-mental <[email protected]>
+Date: Thu, 1 Sep 2022 11:27:44 -0500
+Subject: [PATCH] [PATCH] tag previews: easier to patch patch
+
+Allows you to see the contents of an already viewed tag. So a more
+accurate description would be to re-view a tag.
+Compatibility with the alpha patch (replacing DefaultDepth() and
+DefaultVisual() with depth and visual + window masks) and hide vacants can be
+achieved, I left some lines to uncomment.
+
+added:
+- more compact structure, more probable to patch on top of other patches
+  or easier to patch manually (like not moving the Monitor struct..)
+- create the window preview in updatebars()
+- renamed switchtag() -> takepreview(), makes more sense since it's
+  "taking" the preview (basically a screenshot).
+- option previewbar, whether to show the bar in the preview or not.
+---
+ config.def.h |   2 +
+ config.mk    |   5 +-
+ dwm.c        | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 132 insertions(+), 2 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..abd6521 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -3,6 +3,8 @@
+ /* appearance */
+ static const unsigned int borderpx  = 1;        /* border pixel of windows */
+ static const unsigned int snap      = 32;       /* snap pixel */
++static const int scalepreview       = 4;        /* preview scaling (display w 
and h / scalepreview) */
++static const int previewbar         = 1;        /* show the bar in the 
preview window */
+ static const int showbar            = 1;        /* 0 means no bar */
+ static const int topbar             = 1;        /* 0 means bottom bar */
+ static const char *fonts[]          = { "monospace:size=10" };
+diff --git a/config.mk b/config.mk
+index b6eb7e0..6f5129e 100644
+--- a/config.mk
++++ b/config.mk
+@@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2
+ # OpenBSD (uncomment)
+ #FREETYPEINC = ${X11INC}/freetype2
+ 
++# Imlib2 (tag previews)
++IMLIB2LIBS = -lImlib2
++
+ # includes and libs
+ INCS = -I${X11INC} -I${FREETYPEINC}
+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS}
+ 
+ # flags
+ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L 
-DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+diff --git a/dwm.c b/dwm.c
+index a96f33c..3d8aac7 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -40,6 +40,7 @@
+ #include <X11/extensions/Xinerama.h>
+ #endif /* XINERAMA */
+ #include <X11/Xft/Xft.h>
++#include <Imlib2.h>
+ 
+ #include "drw.h"
+ #include "util.h"
+@@ -112,6 +113,9 @@ typedef struct {
+ } Layout;
+ 
+ struct Monitor {
++      int previewshow;
++      Window tagwin;
++      Pixmap *tagmap;
+       char ltsymbol[16];
+       float mfact;
+       int nmaster;
+@@ -235,6 +239,9 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
+ 
++static void showtagpreview(unsigned int i);
++static void takepreview(void);
++
+ /* variables */
+ static const char broken[] = "broken";
+ static char stext[256];
+@@ -438,6 +445,11 @@ buttonpress(XEvent *e)
+               if (i < LENGTH(tags)) {
+                       click = ClkTagBar;
+                       arg.ui = 1 << i;
++                      /* hide preview if we click the bar */
++                      if (selmon->previewshow) {
++                              selmon->previewshow = 0;
++                              XUnmapWindow(dpy, selmon->tagwin);
++                      }
+               } else if (ev->x < x + blw)
+                       click = ClkLtSymbol;
+               else if (ev->x > selmon->ww - (int)TEXTW(stext))
+@@ -498,6 +510,7 @@ void
+ cleanupmon(Monitor *mon)
+ {
+       Monitor *m;
++      size_t i;
+ 
+       if (mon == mons)
+               mons = mons->next;
+@@ -505,8 +518,13 @@ cleanupmon(Monitor *mon)
+               for (m = mons; m && m->next != mon; m = m->next);
+               m->next = mon->next;
+       }
++      for (i = 0; i < LENGTH(tags); i++)
++              if (mon->tagmap[i])
++                      XFreePixmap(dpy, mon->tagmap[i]);
+       XUnmapWindow(dpy, mon->barwin);
+       XDestroyWindow(dpy, mon->barwin);
++      XUnmapWindow(dpy, mon->tagwin);
++      XDestroyWindow(dpy, mon->tagwin);
+       free(mon);
+ }
+ 
+@@ -641,6 +659,7 @@ createmon(void)
+       m->topbar = topbar;
+       m->lt[0] = &layouts[0];
+       m->lt[1] = &layouts[1 % LENGTH(layouts)];
++      m->tagmap = ecalloc(LENGTH(tags), sizeof(Pixmap));
+       strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+       return m;
+ }
+@@ -1125,6 +1144,36 @@ motionnotify(XEvent *e)
+       static Monitor *mon = NULL;
+       Monitor *m;
+       XMotionEvent *ev = &e->xmotion;
++      unsigned int i, x;
++
++      if (ev->window == selmon->barwin) {
++              i = x = 0;
++              do
++                      x += TEXTW(tags[i]);
++              while (ev->x >= x && ++i < LENGTH(tags));
++      /* FIXME when hovering the mouse over the tags and we view the tag,
++       *       the preview window get's in the preview shot */
++
++              if (i < LENGTH(tags)) {
++                      if (selmon->previewshow != (i + 1)
++                      && !(selmon->tagset[selmon->seltags] & 1 << i)) {
++                              selmon->previewshow = i + 1;
++                              showtagpreview(i);
++                      } else if (selmon->tagset[selmon->seltags] & 1 << i) {
++                              selmon->previewshow = 0;
++                              XUnmapWindow(dpy, selmon->tagwin);
++                      }
++              } else if (selmon->previewshow) {
++                      selmon->previewshow = 0;
++                      XUnmapWindow(dpy, selmon->tagwin);
++              }
++      } else if (ev->window == selmon->tagwin) {
++              selmon->previewshow = 0;
++              XUnmapWindow(dpy, selmon->tagwin);
++      } else if (selmon->previewshow) {
++              selmon->previewshow = 0;
++              XUnmapWindow(dpy, selmon->tagwin);
++      }
+ 
+       if (ev->window != root)
+               return;
+@@ -1530,6 +1579,72 @@ setmfact(const Arg *arg)
+       arrange(selmon);
+ }
+ 
++void
++showtagpreview(unsigned int i)
++{
++      if (!selmon->previewshow || !selmon->tagmap[i]) {
++              XUnmapWindow(dpy, selmon->tagwin);
++              return;
++      }
++
++      XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]);
++      XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0,
++                      selmon->mw / scalepreview, selmon->mh / scalepreview,
++                      0, 0);
++      XSync(dpy, False);
++      XMapRaised(dpy, selmon->tagwin);
++}
++
++void
++takepreview(void)
++{
++      Client *c;
++      Imlib_Image image;
++      unsigned int occ = 0, i;
++
++      for (c = selmon->clients; c; c = c->next)
++              occ |= c->tags;
++              //occ |= c->tags == 255 ? 0 : c->tags; /* hide vacants */
++
++      for (i = 0; i < LENGTH(tags); i++) {
++              /* searching for tags that are occupied && selected */
++              if (!(occ & 1 << i) || !(selmon->tagset[selmon->seltags] & 1 << 
i))
++                      continue;
++
++              if (selmon->tagmap[i]) { /* tagmap exist, clean it */
++                      XFreePixmap(dpy, selmon->tagmap[i]);
++                      selmon->tagmap[i] = 0;
++              }
++
++              /* try to unmap the window so it doesn't show the preview on 
the preview */
++              selmon->previewshow = 0;
++              XUnmapWindow(dpy, selmon->tagwin);
++              XSync(dpy, False);
++
++              if (!(image = imlib_create_image(sw, sh))) {
++                      fprintf(stderr, "dwm: imlib: failed to create image, 
skipping.");
++                      continue;
++              }
++              imlib_context_set_image(image);
++              imlib_context_set_display(dpy);
++              /* uncomment if using alpha patch */
++              //imlib_image_set_has_alpha(1);
++              //imlib_context_set_blend(0);
++              //imlib_context_set_visual(visual);
++              imlib_context_set_visual(DefaultVisual(dpy, screen));
++              imlib_context_set_drawable(root);
++
++              if (previewbar)
++                      imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, 
selmon->ww, selmon->wh, 0, 0, 1);
++              else
++                      imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, 
selmon->mw ,selmon->mh, 0, 0, 1);
++              selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, 
selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, 
screen));
++              imlib_context_set_drawable(selmon->tagmap[i]);
++              imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, 
selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview);
++              imlib_free_image();
++      }
++}
++
+ void
+ setup(void)
+ {
+@@ -1746,6 +1861,7 @@ toggleview(const Arg *arg)
+       unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & 
TAGMASK);
+ 
+       if (newtagset) {
++              takepreview();
+               selmon->tagset[selmon->seltags] = newtagset;
+               focus(NULL);
+               arrange(selmon);
+@@ -1811,10 +1927,18 @@ updatebars(void)
+       XSetWindowAttributes wa = {
+               .override_redirect = True,
+               .background_pixmap = ParentRelative,
+-              .event_mask = ButtonPressMask|ExposureMask
++              .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask
+       };
++
+       XClassHint ch = {"dwm", "dwm"};
+       for (m = mons; m; m = m->next) {
++              if (!m->tagwin) {
++                      m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, 
m->mw / scalepreview,
++                              m->mh / scalepreview, 0, DefaultDepth(dpy, 
screen), CopyFromParent,
++                              DefaultVisual(dpy, screen), 
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
++                      XDefineCursor(dpy, m->tagwin, 
cursor[CurNormal]->cursor);
++                      XUnmapWindow(dpy, m->tagwin);
++              }
+               if (m->barwin)
+                       continue;
+               m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 
0, DefaultDepth(dpy, screen),
+@@ -2043,6 +2167,7 @@ view(const Arg *arg)
+ {
+       if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+               return;
++      takepreview();
+       selmon->seltags ^= 1; /* toggle sel tagset */
+       if (arg->ui & TAGMASK)
+               selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+-- 
+2.37.3
+


Reply via email to