dwm-tag-preview-6.2.diff (9776B)
1 From 64c79048e03345937c66fbee01b871e44cd579bc Mon Sep 17 00:00:00 2001 2 From: explosion-mental <explosion0mental@gmail.com> 3 Date: Tue, 12 Oct 2021 11:57:54 -0500 4 Subject: [PATCH] [update] fixed scale preview on `XCreateWindow` and added 5 some comments Allows you to see the contents of an already viewed tag. So a 6 more accurate description would be to re-view a tag. 7 8 --- 9 config.def.h | 1 + 10 config.mk | 5 +- 11 dwm.c | 164 ++++++++++++++++++++++++++++++++++++++++++++------- 12 3 files changed, 147 insertions(+), 23 deletions(-) 13 14 diff --git a/config.def.h b/config.def.h 15 index 1c0b587..897bf0c 100644 16 --- a/config.def.h 17 +++ b/config.def.h 18 @@ -3,6 +3,7 @@ 19 /* appearance */ 20 static const unsigned int borderpx = 1; /* border pixel of windows */ 21 static const unsigned int snap = 32; /* snap pixel */ 22 +static const int scalepreview = 4; /* tag preview scaling */ 23 static const int showbar = 1; /* 0 means no bar */ 24 static const int topbar = 1; /* 0 means bottom bar */ 25 static const char *fonts[] = { "monospace:size=10" }; 26 diff --git a/config.mk b/config.mk 27 index 6d36cb7..699007f 100644 28 --- a/config.mk 29 +++ b/config.mk 30 @@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2 31 # OpenBSD (uncomment) 32 #FREETYPEINC = ${X11INC}/freetype2 33 34 +# Imlib2 (tag previews) 35 +IMLIB2LIBS = -lImlib2 36 + 37 # includes and libs 38 INCS = -I${X11INC} -I${FREETYPEINC} 39 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} 40 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS} 41 42 # flags 43 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} 44 diff --git a/dwm.c b/dwm.c 45 index 4465af1..878abc1 100644 46 --- a/dwm.c 47 +++ b/dwm.c 48 @@ -40,6 +40,7 @@ 49 #include <X11/extensions/Xinerama.h> 50 #endif /* XINERAMA */ 51 #include <X11/Xft/Xft.h> 52 +#include <Imlib2.h> 53 54 #include "drw.h" 55 #include "util.h" 56 @@ -111,27 +112,6 @@ typedef struct { 57 void (*arrange)(Monitor *); 58 } Layout; 59 60 -struct Monitor { 61 - char ltsymbol[16]; 62 - float mfact; 63 - int nmaster; 64 - int num; 65 - int by; /* bar geometry */ 66 - int mx, my, mw, mh; /* screen size */ 67 - int wx, wy, ww, wh; /* window area */ 68 - unsigned int seltags; 69 - unsigned int sellt; 70 - unsigned int tagset[2]; 71 - int showbar; 72 - int topbar; 73 - Client *clients; 74 - Client *sel; 75 - Client *stack; 76 - Monitor *next; 77 - Window barwin; 78 - const Layout *lt[2]; 79 -}; 80 - 81 typedef struct { 82 const char *class; 83 const char *instance; 84 @@ -204,8 +184,10 @@ static void setmfact(const Arg *arg); 85 static void setup(void); 86 static void seturgent(Client *c, int urg); 87 static void showhide(Client *c); 88 +static void showtagpreview(int tag); 89 static void sigchld(int unused); 90 static void spawn(const Arg *arg); 91 +static void switchtag(void); 92 static void tag(const Arg *arg); 93 static void tagmon(const Arg *arg); 94 static void tile(Monitor *); 95 @@ -224,6 +206,7 @@ static void updatenumlockmask(void); 96 static void updatesizehints(Client *c); 97 static void updatestatus(void); 98 static void updatetitle(Client *c); 99 +static void updatepreview(void); 100 static void updatewindowtype(Client *c); 101 static void updatewmhints(Client *c); 102 static void view(const Arg *arg); 103 @@ -271,6 +254,36 @@ static Window root, wmcheckwin; 104 /* configuration, allows nested code to access above variables */ 105 #include "config.h" 106 107 +/* We only move this here to get the length of the `tags` array, which probably 108 + * will generate compatibility issues with other patches. To avoid it, I 109 + * reccomend patching this at the end or continue with the comment below */ 110 +struct Monitor { 111 + char ltsymbol[16]; 112 + float mfact; 113 + int nmaster; 114 + int num; 115 + int by; /* bar geometry */ 116 + int mx, my, mw, mh; /* screen size */ 117 + int wx, wy, ww, wh; /* window area */ 118 + unsigned int seltags; 119 + unsigned int sellt; 120 + unsigned int tagset[2]; 121 + int previewshow; 122 + int showbar; 123 + int topbar; 124 + Client *clients; 125 + Client *sel; 126 + Client *stack; 127 + Monitor *next; 128 + Window barwin; 129 + Window tagwin; 130 + //change 'LENGTH(tags)' to the actual number of tags you have (9 by def) 131 + //if you wish to move this below config.h 132 + Pixmap tagmap[LENGTH(tags)]; 133 + const Layout *lt[2]; 134 +}; 135 + 136 + 137 /* compile-time check if all tags fit into an unsigned int bit array. */ 138 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; 139 140 @@ -430,6 +443,10 @@ buttonpress(XEvent *e) 141 focus(NULL); 142 } 143 if (ev->window == selmon->barwin) { 144 + if (selmon->previewshow) { 145 + XUnmapWindow(dpy, selmon->tagwin); 146 + selmon->previewshow = 0; 147 + } 148 i = x = 0; 149 do 150 x += TEXTW(tags[i]); 151 @@ -497,6 +514,7 @@ void 152 cleanupmon(Monitor *mon) 153 { 154 Monitor *m; 155 + size_t i; 156 157 if (mon == mons) 158 mons = mons->next; 159 @@ -504,8 +522,13 @@ cleanupmon(Monitor *mon) 160 for (m = mons; m && m->next != mon; m = m->next); 161 m->next = mon->next; 162 } 163 + for (i = 0; i < LENGTH(tags); i++) 164 + if (mon->tagmap[i]) 165 + XFreePixmap(dpy, mon->tagmap[i]); 166 XUnmapWindow(dpy, mon->barwin); 167 XDestroyWindow(dpy, mon->barwin); 168 + XUnmapWindow(dpy, mon->tagwin); 169 + XDestroyWindow(dpy, mon->tagwin); 170 free(mon); 171 } 172 173 @@ -1121,7 +1144,30 @@ motionnotify(XEvent *e) 174 static Monitor *mon = NULL; 175 Monitor *m; 176 XMotionEvent *ev = &e->xmotion; 177 + unsigned int i, x; 178 + 179 + if (ev->window == selmon->barwin) { 180 + i = x = 0; 181 + do 182 + x += TEXTW(tags[i]); 183 + while (ev->x >= x && ++i < LENGTH(tags)); 184 185 + if (i < LENGTH(tags)) { 186 + if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) { 187 + selmon->previewshow = i + 1; 188 + showtagpreview(i); 189 + } else if (selmon->tagset[selmon->seltags] & 1 << i) { 190 + selmon->previewshow = 0; 191 + showtagpreview(0); 192 + } 193 + } else if (selmon->previewshow != 0) { 194 + selmon->previewshow = 0; 195 + showtagpreview(0); 196 + } 197 + } else if (selmon->previewshow != 0) { 198 + selmon->previewshow = 0; 199 + showtagpreview(0); 200 + } 201 if (ev->window != root) 202 return; 203 if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { 204 @@ -1573,6 +1619,7 @@ setup(void) 205 /* init bars */ 206 updatebars(); 207 updatestatus(); 208 + updatepreview(); 209 /* supporting window for NetWMCheck */ 210 wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); 211 XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, 212 @@ -1628,6 +1675,23 @@ showhide(Client *c) 213 } 214 } 215 216 +void 217 +showtagpreview(int tag) 218 +{ 219 + if (!selmon->previewshow) { 220 + XUnmapWindow(dpy, selmon->tagwin); 221 + return; 222 + } 223 + 224 + if (selmon->tagmap[tag]) { 225 + XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[tag]); 226 + XCopyArea(dpy, selmon->tagmap[tag], selmon->tagwin, drw->gc, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview, 0, 0); 227 + XSync(dpy, False); 228 + XMapWindow(dpy, selmon->tagwin); 229 + } else 230 + XUnmapWindow(dpy, selmon->tagwin); 231 +} 232 + 233 void 234 sigchld(int unused) 235 { 236 @@ -1652,6 +1716,40 @@ spawn(const Arg *arg) 237 } 238 } 239 240 +void 241 +switchtag(void) 242 +{ 243 + int i; 244 + unsigned int occ = 0; 245 + Client *c; 246 + Imlib_Image image; 247 + 248 + for (c = selmon->clients; c; c = c->next) 249 + occ |= c->tags; 250 + for (i = 0; i < LENGTH(tags); i++) { 251 + if (selmon->tagset[selmon->seltags] & 1 << i) { 252 + if (selmon->tagmap[i] != 0) { 253 + XFreePixmap(dpy, selmon->tagmap[i]); 254 + selmon->tagmap[i] = 0; 255 + } 256 + if (occ & 1 << i) { 257 + image = imlib_create_image(sw, sh); 258 + imlib_context_set_image(image); 259 + imlib_context_set_display(dpy); 260 + imlib_context_set_visual(DefaultVisual(dpy, screen)); 261 + imlib_context_set_drawable(RootWindow(dpy, screen)); 262 + //uncomment the following line and comment the other imlin_copy.. line if you don't want the bar showing on the preview 263 + //imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww ,selmon->wh, 0, 0, 1); 264 + imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1); 265 + selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen)); 266 + imlib_context_set_drawable(selmon->tagmap[i]); 267 + imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview); 268 + imlib_free_image(); 269 + } 270 + } 271 + } 272 +} 273 + 274 void 275 tag(const Arg *arg) 276 { 277 @@ -1740,6 +1838,7 @@ toggleview(const Arg *arg) 278 unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); 279 280 if (newtagset) { 281 + switchtag(); 282 selmon->tagset[selmon->seltags] = newtagset; 283 focus(NULL); 284 arrange(selmon); 285 @@ -1805,7 +1904,7 @@ 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 XClassHint ch = {"dwm", "dwm"}; 293 for (m = mons; m; m = m->next) { 294 @@ -2001,6 +2100,26 @@ updatetitle(Client *c) 295 strcpy(c->name, broken); 296 } 297 298 +void 299 +updatepreview(void) 300 +{ 301 + Monitor *m; 302 + 303 + XSetWindowAttributes wa = { 304 + .override_redirect = True, 305 + .background_pixmap = ParentRelative, 306 + .event_mask = ButtonPressMask|ExposureMask 307 + }; 308 + for (m = mons; m; m = m->next) { 309 + m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, m->mw / scalepreview, m->mh / scalepreview, 0, 310 + DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), 311 + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); 312 + XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); 313 + XMapRaised(dpy, m->tagwin); 314 + XUnmapWindow(dpy, m->tagwin); 315 + } 316 +} 317 + 318 void 319 updatewindowtype(Client *c) 320 { 321 @@ -2037,6 +2156,7 @@ view(const Arg *arg) 322 { 323 if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) 324 return; 325 + switchtag(); 326 selmon->seltags ^= 1; /* toggle sel tagset */ 327 if (arg->ui & TAGMASK) 328 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; 329 -- 330 2.33.0 331