dwm-tag-preview-6.3.diff (10565B)
1 From 841ad7d5767f945ee9da6c5afc8cff98ca2f8231 Mon Sep 17 00:00:00 2001 2 From: explosion-mental <explosion0mental@gmail.com> 3 Date: Thu, 1 Sep 2022 16:21:58 -0500 4 Subject: [PATCH] [PATCH] tag previews: free() tagmap and add previewtag func 5 6 Allows you to see the contents of an already viewed tag. So a more 7 accurate description would be to re-view a tag. 8 9 Allows you to see the contents of an already viewed tag. So a more 10 accurate description would be to re-view a tag. 11 12 Compatibility with the alpha patch (replacing DefaultDepth() and 13 DefaultVisual() with depth and visual + window masks) and hide vacants can be 14 achieved, I left some lines to uncomment. 15 16 added: 17 * more compact structure, more probable to patch on top of other patches 18 or easier to patch manually (like not moving the Monitor struct..) 19 * create the window preview in updatebars() 20 * renamed switchtag() -> takepreview(), makes more sense since it's 21 "taking" the preview (basically a screenshot). 22 * option previewbar, whether to show the bar in the preview or not. 23 * previewtag which takes a tag (unsigned int from 0 to the last tag) and 24 previews it. This allows to preview tags without using the 25 cursor/mouse (which avoids a recursive previews preview). 26 adding it to the TAGKEYS macro makes more sense so I've added it 27 replacing (keybinding wise, not functionality) toggletag. 28 ``` 29 \#define TAGKEYS(KEY,TAG) \ 30 { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ 31 { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 32 { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ 33 -> { MODKEY|ControlMask|ShiftMask, KEY, previewtag, {.ui = TAG } }, 34 ``` 35 --- 36 config.def.h | 4 +- 37 config.mk | 5 +- 38 dwm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++- 39 3 files changed, 145 insertions(+), 3 deletions(-) 40 41 diff --git a/config.def.h b/config.def.h 42 index a2ac963..eb70348 100644 43 --- a/config.def.h 44 +++ b/config.def.h 45 @@ -3,6 +3,8 @@ 46 /* appearance */ 47 static const unsigned int borderpx = 1; /* border pixel of windows */ 48 static const unsigned int snap = 32; /* snap pixel */ 49 +static const int scalepreview = 4; /* preview scaling (display w and h / scalepreview) */ 50 +static const int previewbar = 1; /* show the bar in the preview window */ 51 static const int showbar = 1; /* 0 means no bar */ 52 static const int topbar = 1; /* 0 means bottom bar */ 53 static const char *fonts[] = { "monospace:size=10" }; 54 @@ -50,7 +52,7 @@ static const Layout layouts[] = { 55 { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ 56 { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 57 { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ 58 - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, 59 + { MODKEY|ControlMask|ShiftMask, KEY, previewtag, {.ui = TAG } }, \ 60 61 /* helper for spawning shell commands in the pre dwm-5.0 fashion */ 62 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 63 diff --git a/config.mk b/config.mk 64 index b6eb7e0..6f5129e 100644 65 --- a/config.mk 66 +++ b/config.mk 67 @@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2 68 # OpenBSD (uncomment) 69 #FREETYPEINC = ${X11INC}/freetype2 70 71 +# Imlib2 (tag previews) 72 +IMLIB2LIBS = -lImlib2 73 + 74 # includes and libs 75 INCS = -I${X11INC} -I${FREETYPEINC} 76 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} 77 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS} 78 79 # flags 80 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 81 diff --git a/dwm.c b/dwm.c 82 index a96f33c..0c0ba12 100644 83 --- a/dwm.c 84 +++ b/dwm.c 85 @@ -40,6 +40,7 @@ 86 #include <X11/extensions/Xinerama.h> 87 #endif /* XINERAMA */ 88 #include <X11/Xft/Xft.h> 89 +#include <Imlib2.h> 90 91 #include "drw.h" 92 #include "util.h" 93 @@ -112,6 +113,9 @@ typedef struct { 94 } Layout; 95 96 struct Monitor { 97 + int previewshow; 98 + Window tagwin; 99 + Pixmap *tagmap; 100 char ltsymbol[16]; 101 float mfact; 102 int nmaster; 103 @@ -235,6 +239,10 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); 104 static int xerrorstart(Display *dpy, XErrorEvent *ee); 105 static void zoom(const Arg *arg); 106 107 +static void showtagpreview(unsigned int i); 108 +static void takepreview(void); 109 +static void previewtag(const Arg *arg); 110 + 111 /* variables */ 112 static const char broken[] = "broken"; 113 static char stext[256]; 114 @@ -438,6 +446,11 @@ buttonpress(XEvent *e) 115 if (i < LENGTH(tags)) { 116 click = ClkTagBar; 117 arg.ui = 1 << i; 118 + /* hide preview if we click the bar */ 119 + if (selmon->previewshow) { 120 + selmon->previewshow = 0; 121 + XUnmapWindow(dpy, selmon->tagwin); 122 + } 123 } else if (ev->x < x + blw) 124 click = ClkLtSymbol; 125 else if (ev->x > selmon->ww - (int)TEXTW(stext)) 126 @@ -498,6 +511,7 @@ void 127 cleanupmon(Monitor *mon) 128 { 129 Monitor *m; 130 + size_t i; 131 132 if (mon == mons) 133 mons = mons->next; 134 @@ -505,8 +519,14 @@ cleanupmon(Monitor *mon) 135 for (m = mons; m && m->next != mon; m = m->next); 136 m->next = mon->next; 137 } 138 + for (i = 0; i < LENGTH(tags); i++) 139 + if (mon->tagmap[i]) 140 + XFreePixmap(dpy, mon->tagmap[i]); 141 + free(mon->tagmap); 142 XUnmapWindow(dpy, mon->barwin); 143 XDestroyWindow(dpy, mon->barwin); 144 + XUnmapWindow(dpy, mon->tagwin); 145 + XDestroyWindow(dpy, mon->tagwin); 146 free(mon); 147 } 148 149 @@ -641,6 +661,7 @@ createmon(void) 150 m->topbar = topbar; 151 m->lt[0] = &layouts[0]; 152 m->lt[1] = &layouts[1 % LENGTH(layouts)]; 153 + m->tagmap = ecalloc(LENGTH(tags), sizeof(Pixmap)); 154 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); 155 return m; 156 } 157 @@ -1125,6 +1146,36 @@ motionnotify(XEvent *e) 158 static Monitor *mon = NULL; 159 Monitor *m; 160 XMotionEvent *ev = &e->xmotion; 161 + unsigned int i, x; 162 + 163 + if (ev->window == selmon->barwin) { 164 + i = x = 0; 165 + do 166 + x += TEXTW(tags[i]); 167 + while (ev->x >= x && ++i < LENGTH(tags)); 168 + /* FIXME when hovering the mouse over the tags and we view the tag, 169 + * the preview window get's in the preview shot */ 170 + 171 + if (i < LENGTH(tags)) { 172 + if (selmon->previewshow != (i + 1) 173 + && !(selmon->tagset[selmon->seltags] & 1 << i)) { 174 + selmon->previewshow = i + 1; 175 + showtagpreview(i); 176 + } else if (selmon->tagset[selmon->seltags] & 1 << i) { 177 + selmon->previewshow = 0; 178 + XUnmapWindow(dpy, selmon->tagwin); 179 + } 180 + } else if (selmon->previewshow) { 181 + selmon->previewshow = 0; 182 + XUnmapWindow(dpy, selmon->tagwin); 183 + } 184 + } else if (ev->window == selmon->tagwin) { 185 + selmon->previewshow = 0; 186 + XUnmapWindow(dpy, selmon->tagwin); 187 + } else if (selmon->previewshow) { 188 + selmon->previewshow = 0; 189 + XUnmapWindow(dpy, selmon->tagwin); 190 + } 191 192 if (ev->window != root) 193 return; 194 @@ -1530,6 +1581,82 @@ setmfact(const Arg *arg) 195 arrange(selmon); 196 } 197 198 +void 199 +showtagpreview(unsigned int i) 200 +{ 201 + if (!selmon->previewshow || !selmon->tagmap[i]) { 202 + XUnmapWindow(dpy, selmon->tagwin); 203 + return; 204 + } 205 + 206 + XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]); 207 + XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0, 208 + selmon->mw / scalepreview, selmon->mh / scalepreview, 209 + 0, 0); 210 + XSync(dpy, False); 211 + XMapRaised(dpy, selmon->tagwin); 212 +} 213 + 214 +void 215 +takepreview(void) 216 +{ 217 + Client *c; 218 + Imlib_Image image; 219 + unsigned int occ = 0, i; 220 + 221 + for (c = selmon->clients; c; c = c->next) 222 + occ |= c->tags; 223 + //occ |= c->tags == 255 ? 0 : c->tags; /* hide vacants */ 224 + 225 + for (i = 0; i < LENGTH(tags); i++) { 226 + /* searching for tags that are occupied && selected */ 227 + if (!(occ & 1 << i) || !(selmon->tagset[selmon->seltags] & 1 << i)) 228 + continue; 229 + 230 + if (selmon->tagmap[i]) { /* tagmap exist, clean it */ 231 + XFreePixmap(dpy, selmon->tagmap[i]); 232 + selmon->tagmap[i] = 0; 233 + } 234 + 235 + /* try to unmap the window so it doesn't show the preview on the preview */ 236 + selmon->previewshow = 0; 237 + XUnmapWindow(dpy, selmon->tagwin); 238 + XSync(dpy, False); 239 + 240 + if (!(image = imlib_create_image(sw, sh))) { 241 + fprintf(stderr, "dwm: imlib: failed to create image, skipping."); 242 + continue; 243 + } 244 + imlib_context_set_image(image); 245 + imlib_context_set_display(dpy); 246 + /* uncomment if using alpha patch */ 247 + //imlib_image_set_has_alpha(1); 248 + //imlib_context_set_blend(0); 249 + //imlib_context_set_visual(visual); 250 + imlib_context_set_visual(DefaultVisual(dpy, screen)); 251 + imlib_context_set_drawable(root); 252 + 253 + if (previewbar) 254 + imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww, selmon->wh, 0, 0, 1); 255 + else 256 + imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1); 257 + selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen)); 258 + imlib_context_set_drawable(selmon->tagmap[i]); 259 + imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview); 260 + imlib_free_image(); 261 + } 262 +} 263 + 264 +void 265 +previewtag(const Arg *arg) 266 +{ 267 + if (selmon->previewshow != (arg->ui + 1)) 268 + selmon->previewshow = arg->ui + 1; 269 + else 270 + selmon->previewshow = 0; 271 + showtagpreview(arg->ui); 272 +} 273 + 274 void 275 setup(void) 276 { 277 @@ -1746,6 +1873,7 @@ toggleview(const Arg *arg) 278 unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); 279 280 if (newtagset) { 281 + takepreview(); 282 selmon->tagset[selmon->seltags] = newtagset; 283 focus(NULL); 284 arrange(selmon); 285 @@ -1811,10 +1939,18 @@ updatebars(void) 286 XSetWindowAttributes wa = { 287 .override_redirect = True, 288 .background_pixmap = ParentRelative, 289 - .event_mask = ButtonPressMask|ExposureMask 290 + .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask 291 }; 292 + 293 XClassHint ch = {"dwm", "dwm"}; 294 for (m = mons; m; m = m->next) { 295 + if (!m->tagwin) { 296 + m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, m->mw / scalepreview, 297 + m->mh / scalepreview, 0, DefaultDepth(dpy, screen), CopyFromParent, 298 + DefaultVisual(dpy, screen), CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); 299 + XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); 300 + XUnmapWindow(dpy, m->tagwin); 301 + } 302 if (m->barwin) 303 continue; 304 m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), 305 @@ -2043,6 +2179,7 @@ view(const Arg *arg) 306 { 307 if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) 308 return; 309 + takepreview(); 310 selmon->seltags ^= 1; /* toggle sel tagset */ 311 if (arg->ui & TAGMASK) 312 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; 313 -- 314 2.37.3 315