| dwm-preview-all-windows-20250407-e381933.diff - sites - public wiki contents of… | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| dwm-preview-all-windows-20250407-e381933.diff (12466B) | |
| --- | |
| 1 From e381933255718c6ed30e1b930d8fd76d62ccda75 Mon Sep 17 00:00:00 2001 | |
| 2 From: elbachir-one <[email protected]> | |
| 3 Date: Mon, 7 Apr 2025 06:02:14 +0100 | |
| 4 Subject: [PATCH] Added some keys to move/select around windows in the pr… | |
| 5 | |
| 6 --- | |
| 7 config.def.h | 4 + | |
| 8 config.mk | 2 +- | |
| 9 dwm.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++++ | |
| 10 3 files changed, 312 insertions(+), 1 deletion(-) | |
| 11 | |
| 12 diff --git a/config.def.h b/config.def.h | |
| 13 index 4412cb1..37feaf7 100644 | |
| 14 --- a/config.def.h | |
| 15 +++ b/config.def.h | |
| 16 @@ -1,5 +1,8 @@ | |
| 17 /* See LICENSE file for copyright and license details. */ | |
| 18 | |
| 19 +//#define ACTUALFULLSCREEN /* Uncomment if the actualfullscreen patch i… | |
| 20 +//#define AWESOMEBAR /* Uncommnet if the awesomebar patch is used */ | |
| 21 + | |
| 22 /* appearance */ | |
| 23 static const unsigned int borderpx = 1; /* border pixel of wind… | |
| 24 static const unsigned int snap = 32; /* snap pixel */ | |
| 25 @@ -95,6 +98,7 @@ static const Key keys[] = { | |
| 26 TAGKEYS( XK_8, 7) | |
| 27 TAGKEYS( XK_9, 8) | |
| 28 { MODKEY|ShiftMask, XK_q, quit, {0} … | |
| 29 + { MODKEY, XK_r, togglepreviewallwin,… | |
| 30 }; | |
| 31 | |
| 32 /* button definitions */ | |
| 33 diff --git a/config.mk b/config.mk | |
| 34 index 8efca9a..8df2978 100644 | |
| 35 --- a/config.mk | |
| 36 +++ b/config.mk | |
| 37 @@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2 | |
| 38 | |
| 39 # includes and libs | |
| 40 INCS = -I${X11INC} -I${FREETYPEINC} | |
| 41 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} | |
| 42 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender | |
| 43 | |
| 44 # flags | |
| 45 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSI… | |
| 46 diff --git a/dwm.c b/dwm.c | |
| 47 index 1443802..6d38874 100644 | |
| 48 --- a/dwm.c | |
| 49 +++ b/dwm.c | |
| 50 @@ -40,6 +40,7 @@ | |
| 51 #include <X11/extensions/Xinerama.h> | |
| 52 #endif /* XINERAMA */ | |
| 53 #include <X11/Xft/Xft.h> | |
| 54 +#include <X11/extensions/Xrender.h> | |
| 55 | |
| 56 #include "drw.h" | |
| 57 #include "util.h" | |
| 58 @@ -83,6 +84,16 @@ typedef struct { | |
| 59 | |
| 60 typedef struct Monitor Monitor; | |
| 61 typedef struct Client Client; | |
| 62 + | |
| 63 +typedef struct Preview Preview; | |
| 64 +struct Preview { | |
| 65 + XImage *orig_image; | |
| 66 + XImage *scaled_image; | |
| 67 + Window win; | |
| 68 + unsigned int x, y; | |
| 69 + Preview *next; | |
| 70 +}; | |
| 71 + | |
| 72 struct Client { | |
| 73 char name[256]; | |
| 74 float mina, maxa; | |
| 75 @@ -96,6 +107,7 @@ struct Client { | |
| 76 Client *snext; | |
| 77 Monitor *mon; | |
| 78 Window win; | |
| 79 + Preview pre; | |
| 80 }; | |
| 81 | |
| 82 typedef struct { | |
| 83 @@ -232,8 +244,14 @@ static int xerror(Display *dpy, XErrorEvent *ee); | |
| 84 static int xerrordummy(Display *dpy, XErrorEvent *ee); | |
| 85 static int xerrorstart(Display *dpy, XErrorEvent *ee); | |
| 86 static void zoom(const Arg *arg); | |
| 87 +static void togglepreviewallwin(); | |
| 88 +static void highlightwindow(int idx, Monitor *m); | |
| 89 +static void setpreviewwindowsizepositions(unsigned int n, Monitor *m, u… | |
| 90 +static XImage *getwindowximage(Client *c); | |
| 91 +static XImage *scaledownimage(XImage *orig_image, unsigned int cw, unsi… | |
| 92 | |
| 93 /* variables */ | |
| 94 + | |
| 95 static const char broken[] = "broken"; | |
| 96 static char stext[256]; | |
| 97 static int screen; | |
| 98 @@ -266,6 +284,7 @@ static Display *dpy; | |
| 99 static Drw *drw; | |
| 100 static Monitor *mons, *selmon; | |
| 101 static Window root, wmcheckwin; | |
| 102 +static int previewallwin = 0; | |
| 103 | |
| 104 /* configuration, allows nested code to access above variables */ | |
| 105 #include "config.h" | |
| 106 @@ -2139,6 +2158,294 @@ zoom(const Arg *arg) | |
| 107 pop(c); | |
| 108 } | |
| 109 | |
| 110 +void | |
| 111 +togglepreviewallwin() { | |
| 112 + if (previewallwin) { /* If already active, disable preview */ | |
| 113 + previewallwin = 0; | |
| 114 + for (Client *c = selmon->clients; c; c = c->next) { | |
| 115 + XUnmapWindow(dpy, c->pre.win); | |
| 116 + XMapWindow(dpy, c->win); | |
| 117 + if (c->pre.orig_image) | |
| 118 + XDestroyImage(c->pre.orig_image); | |
| 119 + if (c->pre.scaled_image) | |
| 120 + XDestroyImage(c->pre.scaled_image); | |
| 121 + } | |
| 122 + arrange(selmon); | |
| 123 + focus(NULL); | |
| 124 + return; /* Exit function early to prevent running agai… | |
| 125 + } | |
| 126 + | |
| 127 + previewallwin = 1; /* Enable preview mode */ | |
| 128 + Monitor *m = selmon; | |
| 129 + Client *c, *focus_c = NULL; | |
| 130 + unsigned int n = 0; | |
| 131 + | |
| 132 + for (c = m->clients; c; c = c->next, n++) { | |
| 133 +#ifdef ACTUALFULLSCREEN | |
| 134 + if (c->isfullscreen) | |
| 135 + togglefullscr(&(Arg){0}); | |
| 136 +#endif | |
| 137 +#ifdef AWESOMEBAR | |
| 138 + if (HIDDEN(c)) | |
| 139 + continue; | |
| 140 +#endif | |
| 141 + c->pre.orig_image = getwindowximage(c); | |
| 142 + } | |
| 143 + | |
| 144 + if (n == 0) return; | |
| 145 + | |
| 146 + setpreviewwindowsizepositions(n, m, 60, 15); | |
| 147 + XEvent event; | |
| 148 + | |
| 149 + for (c = m->clients; c; c = c->next) { | |
| 150 + if (!c->pre.win) | |
| 151 + c->pre.win = XCreateSimpleWindow(dpy, root, c->… | |
| 152 + c->pre.scaled_image->width, c->… | |
| 153 + 1, BlackPixel(dpy, screen), Whi… | |
| 154 + else | |
| 155 + XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c-… | |
| 156 + c->pre.scaled_image->width, c->… | |
| 157 + | |
| 158 + XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][Co… | |
| 159 + XUnmapWindow(dpy, c->win); | |
| 160 + | |
| 161 + if (c->pre.win) { | |
| 162 + XSelectInput(dpy, c->pre.win, ButtonPress | Ent… | |
| 163 + XMapWindow(dpy, c->pre.win); | |
| 164 + GC gc = XCreateGC(dpy, c->pre.win, 0, NULL); | |
| 165 + XPutImage(dpy, c->pre.win, gc, c->pre.scaled_im… | |
| 166 + c->pre.scaled_image->width, c->… | |
| 167 + } | |
| 168 + } | |
| 169 + | |
| 170 + int selected_idx = 0; | |
| 171 + | |
| 172 + while (previewallwin) { | |
| 173 + XNextEvent(dpy, &event); | |
| 174 + if (event.type == ButtonPress) { | |
| 175 + if (event.xbutton.button == Button1) { /* Left-… | |
| 176 + for (c = selmon->clients; c; c = c->nex… | |
| 177 + if (event.xbutton.window == c->… | |
| 178 + previewallwin = 0; | |
| 179 + selmon->tagset[selmon->… | |
| 180 + focus(c); | |
| 181 + arrange(selmon); /* Ens… | |
| 182 + break; | |
| 183 + } | |
| 184 + } | |
| 185 + } | |
| 186 + } | |
| 187 + if (event.type == KeyPress) { | |
| 188 + if (event.xkey.keycode == XKeysymToKeycode(dpy,… | |
| 189 + if (selected_idx < n - 1) { | |
| 190 + selected_idx++; | |
| 191 + } | |
| 192 + highlightwindow(selected_idx, m); | |
| 193 + } | |
| 194 + if (event.xkey.keycode == XKeysymToKeycode(dpy,… | |
| 195 + if (selected_idx > 0) { | |
| 196 + selected_idx--; | |
| 197 + } | |
| 198 + highlightwindow(selected_idx, m); | |
| 199 + } | |
| 200 + if (event.xkey.keycode == XKeysymToKeycode(dpy,… | |
| 201 + previewallwin = 0; | |
| 202 + Client *selected_client = NULL; | |
| 203 + int idx = 0; | |
| 204 + | |
| 205 + for (c = m->clients; c; c = c->next, id… | |
| 206 + if (idx == selected_idx) { | |
| 207 + selected_client = c; | |
| 208 + break; | |
| 209 + } | |
| 210 + } | |
| 211 + if (selected_client) { | |
| 212 + selmon->tagset[selmon->seltags]… | |
| 213 + focus(selected_client); | |
| 214 + arrange(selmon); | |
| 215 + } | |
| 216 + } | |
| 217 + if (event.xkey.keycode == XKeysymToKeycode(dpy,… | |
| 218 + previewallwin = 0; | |
| 219 + Client *selected_client = NULL; | |
| 220 + int idx = 0; | |
| 221 + | |
| 222 + for (c = m->clients; c; c = c->next, id… | |
| 223 + if (idx == selected_idx) { | |
| 224 + selected_client = c; | |
| 225 + break; | |
| 226 + } | |
| 227 + } | |
| 228 + if (selected_client) { | |
| 229 + selmon->tagset[selmon->seltags]… | |
| 230 + focus(selected_client); | |
| 231 + arrange(selmon); | |
| 232 + } | |
| 233 + } | |
| 234 + } | |
| 235 + | |
| 236 + if (event.type == EnterNotify) { | |
| 237 + for (c = m->clients; c; c = c->next) { | |
| 238 + if (event.xcrossing.window == c->pre.wi… | |
| 239 + XSetWindowBorder(dpy, c->pre.wi… | |
| 240 + break; | |
| 241 + } | |
| 242 + } | |
| 243 + } | |
| 244 + if (event.type == LeaveNotify) { | |
| 245 + for (c = m->clients; c; c = c->next) { | |
| 246 + if (event.xcrossing.window == c->pre.wi… | |
| 247 + XSetWindowBorder(dpy, c->pre.wi… | |
| 248 + break; | |
| 249 + } | |
| 250 + } | |
| 251 + } | |
| 252 + } | |
| 253 + for (c = selmon->clients; c; c = c->next) { /* Restore all wind… | |
| 254 + XUnmapWindow(dpy, c->pre.win); | |
| 255 + XMapWindow(dpy, c->win); | |
| 256 + if (c->pre.orig_image) | |
| 257 + XDestroyImage(c->pre.orig_image); | |
| 258 + if (c->pre.scaled_image) | |
| 259 + XDestroyImage(c->pre.scaled_image); | |
| 260 + } | |
| 261 + arrange(m); | |
| 262 + focus(focus_c); | |
| 263 +} | |
| 264 + | |
| 265 +void | |
| 266 +highlightwindow(int idx, Monitor *m) { | |
| 267 + int i = 0; | |
| 268 + Client *c; | |
| 269 + for (c = m->clients; c; c = c->next, i++) { | |
| 270 + if (i == idx) { | |
| 271 + XSetWindowBorder(dpy, c->pre.win, scheme[Scheme… | |
| 272 + } else { | |
| 273 + XSetWindowBorder(dpy, c->pre.win, scheme[Scheme… | |
| 274 + } | |
| 275 + } | |
| 276 +} | |
| 277 + | |
| 278 +void | |
| 279 +setpreviewwindowsizepositions(unsigned int n, Monitor *m, unsigned int … | |
| 280 + unsigned int i, j; | |
| 281 + unsigned int cx, cy, cw, ch, cmaxh; | |
| 282 + unsigned int cols, rows; | |
| 283 + Client *c, *tmpc; | |
| 284 + | |
| 285 + if (n == 1) { | |
| 286 + c = m->clients; | |
| 287 + cw = (m->ww - 2 * gappo) * 0.8; | |
| 288 + ch = (m->wh - 2 * gappo) * 0.9; | |
| 289 + c->pre.scaled_image = scaledownimage(c->pre.orig_image,… | |
| 290 + c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width)… | |
| 291 + c->pre.y = m->my + (m->mh - c->pre.scaled_image->height… | |
| 292 + return; | |
| 293 + } | |
| 294 + if (n == 2) { | |
| 295 + c = m->clients; | |
| 296 + cw = (m->ww - 2 * gappo - gappi) / 2; | |
| 297 + ch = (m->wh - 2 * gappo) * 0.7; | |
| 298 + c->pre.scaled_image = scaledownimage(c->pre.orig_image,… | |
| 299 + c->next->pre.scaled_image = scaledownimage(c->next->pre… | |
| 300 + c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width … | |
| 301 + c->pre.y = m->my + (m->mh - c->pre.scaled_image->height… | |
| 302 + c->next->pre.x = c->pre.x + c->pre.scaled_image->width … | |
| 303 + c->next->pre.y = m->my + (m->mh - c->next->pre.scaled_i… | |
| 304 + return; | |
| 305 + } | |
| 306 + for (cols = 0; cols <= n / 2; cols++) | |
| 307 + if (cols * cols >= n) | |
| 308 + break; | |
| 309 + rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols; | |
| 310 + ch = (m->wh - 2 * gappo) / rows; | |
| 311 + cw = (m->ww - 2 * gappo) / cols; | |
| 312 + c = m->clients; | |
| 313 + cy = 0; | |
| 314 + for (i = 0; i < rows; i++) { | |
| 315 + cx = 0; | |
| 316 + cmaxh = 0; | |
| 317 + tmpc = c; | |
| 318 + for (int j = 0; j < cols; j++) { | |
| 319 + if (!c) | |
| 320 + break; | |
| 321 + c->pre.scaled_image = scaledownimage(c->pre.ori… | |
| 322 + c->pre.x = cx; | |
| 323 + cmaxh = c->pre.scaled_image->height > cmaxh ? c… | |
| 324 + cx += c->pre.scaled_image->width + gappi; | |
| 325 + c = c->next; | |
| 326 + } | |
| 327 + c = tmpc; | |
| 328 + cx = m->wx + (m->ww - cx) / 2; | |
| 329 + for (j = 0; j < cols; j++) { | |
| 330 + if (!c) | |
| 331 + break; | |
| 332 + c->pre.x += cx; | |
| 333 + c->pre.y = cy + (cmaxh - c->pre.scaled_image->h… | |
| 334 + c = c->next; | |
| 335 + } | |
| 336 + cy += cmaxh + gappi; | |
| 337 + } | |
| 338 + cy = m->wy + (m->wh - cy) / 2; | |
| 339 + for (c = m->clients; c; c = c->next) | |
| 340 + c->pre.y += cy; | |
| 341 +} | |
| 342 + | |
| 343 +XImage* | |
| 344 +getwindowximage(Client *c) { | |
| 345 + XWindowAttributes attr; | |
| 346 + XGetWindowAttributes( dpy, c->win, &attr ); | |
| 347 + XRenderPictFormat *format = XRenderFindVisualFormat( dpy, attr.… | |
| 348 + int hasAlpha = ( format->type == PictTypeDirect && format->dire… | |
| 349 + XRenderPictureAttributes pa; | |
| 350 + pa.subwindow_mode = IncludeInferiors; | |
| 351 + Picture picture = XRenderCreatePicture( dpy, c->win, format, CP… | |
| 352 + Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); | |
| 353 + XRenderPictureAttributes pa2; | |
| 354 + XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, Pic… | |
| 355 + Picture pixmapPicture = XRenderCreatePicture( dpy, pixmap, form… | |
| 356 + XRenderColor color; | |
| 357 + color.red = 0x0000; | |
| 358 + color.green = 0x0000; | |
| 359 + color.blue = 0x0000; | |
| 360 + color.alpha = 0x0000; | |
| 361 + XRenderFillRectangle (dpy, PictOpSrc, pixmapPicture, &color, 0,… | |
| 362 + XRenderComposite(dpy, hasAlpha ? PictOpOver : PictOpSrc, pictur… | |
| 363 + pixmapPicture, 0, 0, 0, 0, 0, 0, | |
| 364 + c->w, c->h); | |
| 365 + XImage* temp = XGetImage( dpy, pixmap, 0, 0, c->w, c->h, AllPla… | |
| 366 + temp->red_mask = format2->direct.redMask << format2->direct.red; | |
| 367 + temp->green_mask = format2->direct.greenMask << format2->direct… | |
| 368 + temp->blue_mask = format2->direct.blueMask << format2->direct.b… | |
| 369 + temp->depth = DefaultDepth(dpy, screen); | |
| 370 + return temp; | |
| 371 +} | |
| 372 + | |
| 373 +XImage* | |
| 374 +scaledownimage(XImage *orig_image, unsigned int cw, unsigned int ch) { | |
| 375 + int factor_w = orig_image->width / cw + 1; | |
| 376 + int factor_h = orig_image->height / ch + 1; | |
| 377 + int scale_factor = factor_w > factor_h ? factor_w : factor_h; | |
| 378 + int scaled_width = orig_image->width / scale_factor; | |
| 379 + int scaled_height = orig_image->height / scale_factor; | |
| 380 + XImage *scaled_image = XCreateImage(dpy, DefaultVisual(dpy, Def… | |
| 381 + orig_image->depth, | |
| 382 + ZPixmap, 0, NULL, | |
| 383 + scaled_width, scaled_height, | |
| 384 + 32, 0); | |
| 385 + scaled_image->data = malloc(scaled_image->height * scaled_image… | |
| 386 + for (int y = 0; y < scaled_height; y++) { | |
| 387 + for (int x = 0; x < scaled_width; x++) { | |
| 388 + int orig_x = x * scale_factor; | |
| 389 + int orig_y = y * scale_factor; | |
| 390 + unsigned long pixel = XGetPixel(orig_image, ori… | |
| 391 + XPutPixel(scaled_image, x, y, pixel); | |
| 392 + } | |
| 393 + } | |
| 394 + scaled_image->depth = orig_image->depth; | |
| 395 + return scaled_image; | |
| 396 +} | |
| 397 + | |
| 398 int | |
| 399 main(int argc, char *argv[]) | |
| 400 { | |
| 401 -- | |
| 402 2.48.1 | |
| 403 |