dwm-tag-preview-6.3.diff - sites - public wiki contents of suckless.org
HTML git clone git://git.suckless.org/sites
DIR Log
DIR Files
DIR Refs
---
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