From 6a6d6d35b49dc994f6f426094927593101276c24 Mon Sep 17 00:00:00 2001 From: speedie Date: Tue, 6 Dec 2022 21:01:42 +0100 Subject: [PATCH] tag previews are back --- TODO | 1 - keybinds.h | 1 + speedwm.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++-- toggle.h | 2 +- 4 files changed, 138 insertions(+), 6 deletions(-) diff --git a/TODO b/TODO index ef9848c..eae306c 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ - Give proper credit to authors of patches that went into this project. - Document the bar better. - Rewrite statuscmd and powerline status syntax so that they can be used together. -- Readd tag previews - Fix setbarheight() not working properly. diff --git a/keybinds.h b/keybinds.h index 7e75196..6d4d484 100644 --- a/keybinds.h +++ b/keybinds.h @@ -35,6 +35,7 @@ /* Tag related keybinds */ #define TAGKEYS(CHAIN,KEY,TAG) { MODIFIER1, CHAIN, KEY, view, {.ui = 1 << TAG } }, \ + { MODIFIER1|SHIFT, CHAIN, KEY, previewtag, {.ui = TAG } }, \ { MODIFIER1|CONTROL, CHAIN, KEY, toggleview, {.ui = 1 << TAG } }, \ { MODIFIER1|SHIFT|CONTROL, CHAIN, KEY, tag, {.ui = 1 << TAG } }, diff --git a/speedwm.c b/speedwm.c index c331eaf..57121fb 100644 --- a/speedwm.c +++ b/speedwm.c @@ -293,9 +293,14 @@ typedef struct { typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; /* current layout symbol */ -#if USEIPC + #if USEIPC char lastltsymbol[16]; /* previous layout symbol */ -#endif + #endif + #if USETAGPREVIEW + int previewshow; + Window tagwin; + Pixmap *tagmap; + #endif float mfact; /* mfact value */ float cfact; /* cfact value */ int ltaxis[4]; @@ -718,6 +723,15 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); static void xinitvisual(); static void zoom(const Arg *arg); +/* Tag preview functions */ +#if USETAGPREVIEW +static void showtagpreview(unsigned int i); +static void takepreview(void); +#endif + +/* We will keep this one, in order to keep keybinds.h clean. */ +static void previewtag(const Arg *arg); + #include "bar/items.h" /* switcher funcs */ @@ -1101,6 +1115,10 @@ arrange(Monitor *m) restack(m); } else for (m = mons; m; m = m->next) arrangemon(m); + + #if USETAGPREVIEW + takepreview(); + #endif } void @@ -1446,6 +1464,16 @@ cleanupmon(Monitor *mon) for (m = mons; m && m->next != mon; m = m->next); m->next = mon->next; } + #if USETAGPREVIEW + size_t i; + + for (i = 0; i < LENGTH(tags); i++) + if (mon->tagmap[i]) + XFreePixmap(dpy, mon->tagmap[i]); + free(mon->tagmap); + XUnmapWindow(dpy, mon->tagwin); + XDestroyWindow(dpy, mon->tagwin); + #endif free(mon); } @@ -1727,9 +1755,15 @@ createmon(void) m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; -#if USESWITCHER + #if USETAGPREVIEW + /* map our tags */ + m->tagmap = ecalloc(LENGTH(tags), sizeof(Pixmap)); + #endif + + #if USESWITCHER + /* number of clients, defaults to 0 */ m->nclients = 0; -#endif + #endif /* pertag */ strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -3469,6 +3503,9 @@ toggleview(const Arg *arg) unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); if (newtagset) { + #if USETAGPREVIEW + takepreview(); + #endif selmon->tagset[selmon->seltags] = newtagset; focus(NULL); arrange(selmon); @@ -5565,6 +5602,15 @@ updatebars(void) }; XClassHint ch = {"speedwm", "speedwm"}; for (m = mons; m; m = m->next) { + #if USETAGPREVIEW + if (!m->tagwin) { + m->tagwin = XCreateWindow(dpy, root, m->wx, m->bar->by + bh, m->mw / scalepreview, m->mh / scalepreview, 0, + depth, CopyFromParent, visual, CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); + XUnmapWindow(dpy, m->tagwin); + } + #endif + for (bar = m->bar; bar; bar = bar->next) { if (!bar->win) { bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth, @@ -5999,6 +6045,9 @@ view(const Arg *arg) togglebar(NULL); } + #if USETAGPREVIEW + takepreview(); + #endif focus(NULL); arrange(NULL); updatecurrentdesktop(); @@ -6416,5 +6465,88 @@ inplacerotate(const Arg *arg) focus(c); } +#if USETAGPREVIEW +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) + if (!selmon->hideemptytags) + occ |= c->tags; + else + occ |= c->tags == 255 ? 0 : c->tags; + + 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; + } + + selmon->previewshow = 0; + XUnmapWindow(dpy, selmon->tagwin); + XSync(dpy, False); + + if (!(image = imlib_create_image(tw, sh))) { + fprintf(stderr, "speedwm: imlib: failed to create image, skipping."); + continue; + } + imlib_context_set_image(image); + imlib_context_set_display(dpy); + imlib_image_set_has_alpha(1); + imlib_context_set_blend(0); + imlib_context_set_visual(visual); + imlib_context_set_drawable(root); + + if (!barpreview) + 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, depth); + 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(); + } +} +#endif + +void +previewtag(const Arg *arg) +{ + #if USETAGPREVIEW + if (selmon->previewshow != (arg->ui + 1)) + selmon->previewshow = arg->ui + 1; + else + selmon->previewshow = 0; + showtagpreview(arg->ui); + #else + return; + #endif +} + + /* Layout code */ #include "layouts.c" /* Enable patched layouts */ diff --git a/toggle.h b/toggle.h index dd0ff78..9ddd153 100644 --- a/toggle.h +++ b/toggle.h @@ -32,4 +32,4 @@ Not compatible with BSDs so for those, set this to 0. */ */ #define USEIMLIB2 1 /* Whether or not to include imlib2. Required by USEWINICON and USETAGPREVIEW. */ #define USEWINICON 1 /* Whether or not to include window icons. Requires imlib to be enabled in toggle.mk and it must be installed. */ -#define USETAGPREVIEW 0 /* Whether or not to include tag previews. Requires imlib to be enabled in toggle.mk and it must be installed. */ +#define USETAGPREVIEW 1 /* Whether or not to include tag previews. Requires imlib to be enabled in toggle.mk and it must be installed. */