sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit eab1efe2663368fe804d099e439b0eb648ed3e44
parent 415383b09670c5081f7bfe291144c80c38227722
Author: elbachir-one <bachiralfa@gmail.com>
Date:   Mon,  7 Apr 2025 05:05:02 +0100

[dwm][patches][preview-all-win]

* Updated index.md
* Updating the patch to fix some issues

Diffstat:
Adwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-20250407-e381933.diff | 403+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-6.5.diff | 429++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mdwm.suckless.org/patches/preview-all-win/index.md | 32+++++++++++++++++++++-----------
3 files changed, 643 insertions(+), 221 deletions(-)

diff --git a/dwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-20250407-e381933.diff b/dwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-20250407-e381933.diff @@ -0,0 +1,403 @@ +From e381933255718c6ed30e1b930d8fd76d62ccda75 Mon Sep 17 00:00:00 2001 +From: elbachir-one <bachiralfa@gmail.com> +Date: Mon, 7 Apr 2025 06:02:14 +0100 +Subject: [PATCH] Added some keys to move/select around windows in the preview + +--- + config.def.h | 4 + + config.mk | 2 +- + dwm.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 312 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 4412cb1..37feaf7 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -1,5 +1,8 @@ + /* See LICENSE file for copyright and license details. */ + ++//#define ACTUALFULLSCREEN /* Uncomment if the actualfullscreen patch is added */ ++//#define AWESOMEBAR /* Uncommnet if the awesomebar patch is used */ ++ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ +@@ -95,6 +98,7 @@ static const Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY, XK_r, togglepreviewallwin, {0} }, + }; + + /* button definitions */ +diff --git a/config.mk b/config.mk +index 8efca9a..8df2978 100644 +--- a/config.mk ++++ b/config.mk +@@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index 1443802..6d38874 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,7 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <X11/extensions/Xrender.h> + + #include "drw.h" + #include "util.h" +@@ -83,6 +84,16 @@ typedef struct { + + typedef struct Monitor Monitor; + typedef struct Client Client; ++ ++typedef struct Preview Preview; ++struct Preview { ++ XImage *orig_image; ++ XImage *scaled_image; ++ Window win; ++ unsigned int x, y; ++ Preview *next; ++}; ++ + struct Client { + char name[256]; + float mina, maxa; +@@ -96,6 +107,7 @@ struct Client { + Client *snext; + Monitor *mon; + Window win; ++ Preview pre; + }; + + typedef struct { +@@ -232,8 +244,14 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void togglepreviewallwin(); ++static void highlightwindow(int idx, Monitor *m); ++static void setpreviewwindowsizepositions(unsigned int n, Monitor *m, unsigned int gappo, unsigned int gappi); ++static XImage *getwindowximage(Client *c); ++static XImage *scaledownimage(XImage *orig_image, unsigned int cw, unsigned int ch); + + /* variables */ ++ + static const char broken[] = "broken"; + static char stext[256]; + static int screen; +@@ -266,6 +284,7 @@ static Display *dpy; + static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; ++static int previewallwin = 0; + + /* configuration, allows nested code to access above variables */ + #include "config.h" +@@ -2139,6 +2158,294 @@ zoom(const Arg *arg) + pop(c); + } + ++void ++togglepreviewallwin() { ++ if (previewallwin) { /* If already active, disable preview */ ++ previewallwin = 0; ++ for (Client *c = selmon->clients; c; c = c->next) { ++ XUnmapWindow(dpy, c->pre.win); ++ XMapWindow(dpy, c->win); ++ if (c->pre.orig_image) ++ XDestroyImage(c->pre.orig_image); ++ if (c->pre.scaled_image) ++ XDestroyImage(c->pre.scaled_image); ++ } ++ arrange(selmon); ++ focus(NULL); ++ return; /* Exit function early to prevent running again */ ++ } ++ ++ previewallwin = 1; /* Enable preview mode */ ++ Monitor *m = selmon; ++ Client *c, *focus_c = NULL; ++ unsigned int n = 0; ++ ++ for (c = m->clients; c; c = c->next, n++) { ++#ifdef ACTUALFULLSCREEN ++ if (c->isfullscreen) ++ togglefullscr(&(Arg){0}); ++#endif ++#ifdef AWESOMEBAR ++ if (HIDDEN(c)) ++ continue; ++#endif ++ c->pre.orig_image = getwindowximage(c); ++ } ++ ++ if (n == 0) return; ++ ++ setpreviewwindowsizepositions(n, m, 60, 15); ++ XEvent event; ++ ++ for (c = m->clients; c; c = c->next) { ++ if (!c->pre.win) ++ c->pre.win = XCreateSimpleWindow(dpy, root, c->pre.x, c->pre.y, ++ c->pre.scaled_image->width, c->pre.scaled_image->height, ++ 1, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); ++ else ++ XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c->pre.y, ++ c->pre.scaled_image->width, c->pre.scaled_image->height); ++ ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); ++ XUnmapWindow(dpy, c->win); ++ ++ if (c->pre.win) { ++ XSelectInput(dpy, c->pre.win, ButtonPress | EnterWindowMask | LeaveWindowMask); ++ XMapWindow(dpy, c->pre.win); ++ GC gc = XCreateGC(dpy, c->pre.win, 0, NULL); ++ XPutImage(dpy, c->pre.win, gc, c->pre.scaled_image, 0, 0, 0, 0, ++ c->pre.scaled_image->width, c->pre.scaled_image->height); ++ } ++ } ++ ++ int selected_idx = 0; ++ ++ while (previewallwin) { ++ XNextEvent(dpy, &event); ++ if (event.type == ButtonPress) { ++ if (event.xbutton.button == Button1) { /* Left-click to select a window */ ++ for (c = selmon->clients; c; c = c->next) { ++ if (event.xbutton.window == c->pre.win) { ++ previewallwin = 0; ++ selmon->tagset[selmon->seltags] = c->tags; ++ focus(c); ++ arrange(selmon); /* Ensure layout updates correctly */ ++ break; ++ } ++ } ++ } ++ } ++ if (event.type == KeyPress) { ++ if (event.xkey.keycode == XKeysymToKeycode(dpy, XK_j)) { ++ if (selected_idx < n - 1) { ++ selected_idx++; ++ } ++ highlightwindow(selected_idx, m); ++ } ++ if (event.xkey.keycode == XKeysymToKeycode(dpy, XK_k)) { ++ if (selected_idx > 0) { ++ selected_idx--; ++ } ++ highlightwindow(selected_idx, m); ++ } ++ if (event.xkey.keycode == XKeysymToKeycode(dpy, XK_Return)) { ++ previewallwin = 0; ++ Client *selected_client = NULL; ++ int idx = 0; ++ ++ for (c = m->clients; c; c = c->next, idx++) { ++ if (idx == selected_idx) { ++ selected_client = c; ++ break; ++ } ++ } ++ if (selected_client) { ++ selmon->tagset[selmon->seltags] = selected_client->tags; ++ focus(selected_client); ++ arrange(selmon); ++ } ++ } ++ if (event.xkey.keycode == XKeysymToKeycode(dpy, XK_r)) { ++ previewallwin = 0; ++ Client *selected_client = NULL; ++ int idx = 0; ++ ++ for (c = m->clients; c; c = c->next, idx++) { ++ if (idx == selected_idx) { ++ selected_client = c; ++ break; ++ } ++ } ++ if (selected_client) { ++ selmon->tagset[selmon->seltags] = selected_client->tags; ++ focus(selected_client); ++ arrange(selmon); ++ } ++ } ++ } ++ ++ if (event.type == EnterNotify) { ++ for (c = m->clients; c; c = c->next) { ++ if (event.xcrossing.window == c->pre.win) { ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeSel][ColBorder].pixel); ++ break; ++ } ++ } ++ } ++ if (event.type == LeaveNotify) { ++ for (c = m->clients; c; c = c->next) { ++ if (event.xcrossing.window == c->pre.win) { ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); ++ break; ++ } ++ } ++ } ++ } ++ for (c = selmon->clients; c; c = c->next) { /* Restore all windows when exiting */ ++ XUnmapWindow(dpy, c->pre.win); ++ XMapWindow(dpy, c->win); ++ if (c->pre.orig_image) ++ XDestroyImage(c->pre.orig_image); ++ if (c->pre.scaled_image) ++ XDestroyImage(c->pre.scaled_image); ++ } ++ arrange(m); ++ focus(focus_c); ++} ++ ++void ++highlightwindow(int idx, Monitor *m) { ++ int i = 0; ++ Client *c; ++ for (c = m->clients; c; c = c->next, i++) { ++ if (i == idx) { ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeSel][ColBorder].pixel); /* Highlight selected window */ ++ } else { ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); /* Reset border for other windows */ ++ } ++ } ++} ++ ++void ++setpreviewwindowsizepositions(unsigned int n, Monitor *m, unsigned int gappo, unsigned int gappi){ ++ unsigned int i, j; ++ unsigned int cx, cy, cw, ch, cmaxh; ++ unsigned int cols, rows; ++ Client *c, *tmpc; ++ ++ if (n == 1) { ++ c = m->clients; ++ cw = (m->ww - 2 * gappo) * 0.8; ++ ch = (m->wh - 2 * gappo) * 0.9; ++ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); ++ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width) / 2; ++ c->pre.y = m->my + (m->mh - c->pre.scaled_image->height) / 2; ++ return; ++ } ++ if (n == 2) { ++ c = m->clients; ++ cw = (m->ww - 2 * gappo - gappi) / 2; ++ ch = (m->wh - 2 * gappo) * 0.7; ++ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); ++ c->next->pre.scaled_image = scaledownimage(c->next->pre.orig_image, cw, ch); ++ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width - gappi - c->next->pre.scaled_image->width) / 2; ++ c->pre.y = m->my + (m->mh - c->pre.scaled_image->height) / 2; ++ c->next->pre.x = c->pre.x + c->pre.scaled_image->width + gappi; ++ c->next->pre.y = m->my + (m->mh - c->next->pre.scaled_image->height) / 2; ++ return; ++ } ++ for (cols = 0; cols <= n / 2; cols++) ++ if (cols * cols >= n) ++ break; ++ rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols; ++ ch = (m->wh - 2 * gappo) / rows; ++ cw = (m->ww - 2 * gappo) / cols; ++ c = m->clients; ++ cy = 0; ++ for (i = 0; i < rows; i++) { ++ cx = 0; ++ cmaxh = 0; ++ tmpc = c; ++ for (int j = 0; j < cols; j++) { ++ if (!c) ++ break; ++ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); ++ c->pre.x = cx; ++ cmaxh = c->pre.scaled_image->height > cmaxh ? c->pre.scaled_image->height : cmaxh; ++ cx += c->pre.scaled_image->width + gappi; ++ c = c->next; ++ } ++ c = tmpc; ++ cx = m->wx + (m->ww - cx) / 2; ++ for (j = 0; j < cols; j++) { ++ if (!c) ++ break; ++ c->pre.x += cx; ++ c->pre.y = cy + (cmaxh - c->pre.scaled_image->height) / 2; ++ c = c->next; ++ } ++ cy += cmaxh + gappi; ++ } ++ cy = m->wy + (m->wh - cy) / 2; ++ for (c = m->clients; c; c = c->next) ++ c->pre.y += cy; ++} ++ ++XImage* ++getwindowximage(Client *c) { ++ XWindowAttributes attr; ++ XGetWindowAttributes( dpy, c->win, &attr ); ++ XRenderPictFormat *format = XRenderFindVisualFormat( dpy, attr.visual ); ++ int hasAlpha = ( format->type == PictTypeDirect && format->direct.alphaMask ); ++ XRenderPictureAttributes pa; ++ pa.subwindow_mode = IncludeInferiors; ++ Picture picture = XRenderCreatePicture( dpy, c->win, format, CPSubwindowMode, &pa ); ++ Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); ++ XRenderPictureAttributes pa2; ++ XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, PictStandardARGB32); ++ Picture pixmapPicture = XRenderCreatePicture( dpy, pixmap, format2, 0, &pa2 ); ++ XRenderColor color; ++ color.red = 0x0000; ++ color.green = 0x0000; ++ color.blue = 0x0000; ++ color.alpha = 0x0000; ++ XRenderFillRectangle (dpy, PictOpSrc, pixmapPicture, &color, 0, 0, c->w, c->h); ++ XRenderComposite(dpy, hasAlpha ? PictOpOver : PictOpSrc, picture, 0, ++ pixmapPicture, 0, 0, 0, 0, 0, 0, ++ c->w, c->h); ++ XImage* temp = XGetImage( dpy, pixmap, 0, 0, c->w, c->h, AllPlanes, ZPixmap ); ++ temp->red_mask = format2->direct.redMask << format2->direct.red; ++ temp->green_mask = format2->direct.greenMask << format2->direct.green; ++ temp->blue_mask = format2->direct.blueMask << format2->direct.blue; ++ temp->depth = DefaultDepth(dpy, screen); ++ return temp; ++} ++ ++XImage* ++scaledownimage(XImage *orig_image, unsigned int cw, unsigned int ch) { ++ int factor_w = orig_image->width / cw + 1; ++ int factor_h = orig_image->height / ch + 1; ++ int scale_factor = factor_w > factor_h ? factor_w : factor_h; ++ int scaled_width = orig_image->width / scale_factor; ++ int scaled_height = orig_image->height / scale_factor; ++ XImage *scaled_image = XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), ++ orig_image->depth, ++ ZPixmap, 0, NULL, ++ scaled_width, scaled_height, ++ 32, 0); ++ scaled_image->data = malloc(scaled_image->height * scaled_image->bytes_per_line); ++ for (int y = 0; y < scaled_height; y++) { ++ for (int x = 0; x < scaled_width; x++) { ++ int orig_x = x * scale_factor; ++ int orig_y = y * scale_factor; ++ unsigned long pixel = XGetPixel(orig_image, orig_x, orig_y); ++ XPutPixel(scaled_image, x, y, pixel); ++ } ++ } ++ scaled_image->depth = orig_image->depth; ++ return scaled_image; ++} ++ + int + main(int argc, char *argv[]) + { +-- +2.48.1 + diff --git a/dwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-6.5.diff b/dwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-6.5.diff @@ -1,8 +1,17 @@ diff --git a/config.def.h b/config.def.h -index 9efa774..f462e32 100644 +index 4412cb1..24f39a7 100644 --- a/config.def.h +++ b/config.def.h -@@ -95,6 +95,7 @@ static const Key keys[] = { +@@ -1,5 +1,8 @@ + /* See LICENSE file for copyright and license details. */ + ++//#define ACTUALFULLSCREEN /* Uncomment if the actualfullscreen patch is added */ ++//#define AWESOMEBAR /* Uncommnet if the awesomebar patch is used */ ++ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ +@@ -95,6 +98,7 @@ static const Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, @@ -11,7 +20,7 @@ index 9efa774..f462e32 100644 /* button definitions */ diff --git a/config.mk b/config.mk -index 8efca9a..8d7c303 100644 +index 8efca9a..8df2978 100644 --- a/config.mk +++ b/config.mk @@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2 @@ -19,49 +28,48 @@ index 8efca9a..8d7c303 100644 # includes and libs INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+LIBS = -L${X11LIB} -lX11 -lXrender -lXcomposite ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/dwm.c b/dwm.c -index 67c6b2b..0ddd58e 100644 +index 1443802..ac561fa 100644 --- a/dwm.c +++ b/dwm.c -@@ -40,6 +40,8 @@ +@@ -40,6 +40,7 @@ #include <X11/extensions/Xinerama.h> #endif /* XINERAMA */ #include <X11/Xft/Xft.h> -+#include <X11/extensions/Xcomposite.h> +#include <X11/extensions/Xrender.h> #include "drw.h" #include "util.h" -@@ -84,6 +86,16 @@ typedef struct { +@@ -83,6 +84,16 @@ typedef struct { typedef struct Monitor Monitor; typedef struct Client Client; + +typedef struct Preview Preview; +struct Preview { -+ XImage *orig_image; -+ XImage *scaled_image; -+ Window win; -+ unsigned int x, y; -+ Preview *next; ++ XImage *orig_image; ++ XImage *scaled_image; ++ Window win; ++ unsigned int x, y; ++ Preview *next; +}; + struct Client { char name[256]; float mina, maxa; -@@ -97,6 +109,7 @@ struct Client { +@@ -96,6 +107,7 @@ struct Client { Client *snext; Monitor *mon; Window win; -+ Preview pre; ++ Preview pre; }; typedef struct { -@@ -233,6 +246,10 @@ static int xerror(Display *dpy, XErrorEvent *ee); +@@ -232,6 +244,10 @@ static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); @@ -72,216 +80,217 @@ index 67c6b2b..0ddd58e 100644 /* variables */ static const char broken[] = "broken"; -@@ -2140,6 +2157,212 @@ zoom(const Arg *arg) +@@ -2139,6 +2155,210 @@ zoom(const Arg *arg) pop(c); } +void +previewallwin(){ -+ int composite_event_base, composite_error_base; -+ if (!XCompositeQueryExtension(dpy, &composite_event_base, &composite_error_base)) { -+ fprintf(stderr, "Error: XComposite extension not available.\n"); -+ return; -+ } -+ Monitor *m = selmon; -+ Client *c, *focus_c = NULL; -+ unsigned int n; -+ for (n = 0, c = m->clients; c; c = c->next, n++){ -+ /* If you hit actualfullscreen patch Unlock the notes below */ -+ // if (c->isfullscreen) -+ // togglefullscr(&(Arg){0}); -+ /* If you hit awesomebar patch Unlock the notes below */ -+ // if (HIDDEN(c)) -+ // continue; -+ c->pre.orig_image = getwindowximage(c); -+ } -+ if (n == 0) -+ return; -+ setpreviewwindowsizepositions(n, m, 60, 15); -+ XEvent event; -+ for(c = m->clients; c; c = c->next){ -+ if (!c->pre.win) -+ c->pre.win = XCreateSimpleWindow(dpy, root, c->pre.x, c->pre.y, c->pre.scaled_image->width, c->pre.scaled_image->height, 1, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); -+ else -+ XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c->pre.y, c->pre.scaled_image->width, c->pre.scaled_image->height); -+ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); -+ XSetWindowBorderWidth(dpy, c->pre.win, borderpx); -+ XUnmapWindow(dpy, c->win); -+ if (c->pre.win){ -+ XSelectInput(dpy, c->pre.win, ButtonPress | EnterWindowMask | LeaveWindowMask ); -+ XMapWindow(dpy, c->pre.win); -+ XPutImage(dpy, c->pre.win, drw->gc, c->pre.scaled_image, 0, 0, 0, 0, c->pre.scaled_image->width, c->pre.scaled_image->height); -+ } -+ } -+ while (1) { -+ XNextEvent(dpy, &event); -+ if (event.type == ButtonPress) -+ if (event.xbutton.button == Button1){ -+ for(c = m->clients; c; c = c->next){ -+ XUnmapWindow(dpy, c->pre.win); -+ if (event.xbutton.window == c->pre.win){ -+ selmon->seltags ^= 1; /* toggle sel tagset */ -+ m->tagset[selmon->seltags] = c->tags; -+ focus_c = c; -+ focus(NULL); -+ /* If you hit awesomebar patch Unlock the notes below */ -+ // if (HIDDEN(c)){ -+ // showwin(c); -+ // continue; -+ // } -+ } -+ /* If you hit awesomebar patch Unlock the notes below; -+ * And you should add the following line to "hidewin" Function -+ * c->pre.orig_image = getwindowximage(c); -+ * */ -+ // if (HIDDEN(c)){ -+ // continue; -+ // } -+ XMapWindow(dpy, c->win); -+ XDestroyImage(c->pre.orig_image); -+ XDestroyImage(c->pre.scaled_image); -+ } -+ break; -+ } -+ if (event.type == EnterNotify) -+ for(c = m->clients; c; c = c->next) -+ if (event.xcrossing.window == c->pre.win){ -+ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeSel][ColBorder].pixel); -+ break; -+ } -+ if (event.type == LeaveNotify) -+ for(c = m->clients; c; c = c->next) -+ if (event.xcrossing.window == c->pre.win){ -+ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); -+ break; -+ } -+ } -+ arrange(m); -+ focus(focus_c); ++ Monitor *m = selmon; ++ Client *c, *focus_c = NULL; ++ unsigned int n; ++ for (n = 0, c = m->clients; c; c = c->next, n++){ ++#ifdef ACTUALFULLSCREEN ++ if (c->isfullscreen) ++ togglefullscr(&(Arg){0}); ++#endif ++#ifdef AWESOMEBAR ++ if (HIDDEN(c)) ++ continue; ++#endif ++ c->pre.orig_image = getwindowximage(c); ++ } ++ if (n == 0) ++ return; ++ setpreviewwindowsizepositions(n, m, 60, 15); ++ XEvent event; ++ for(c = m->clients; c; c = c->next){ ++ if (!c->pre.win) ++ c->pre.win = XCreateSimpleWindow(dpy, root, c->pre.x, c->pre.y, c->pre.scaled_image->width, c->pre.scaled_image->height, 1, BlackPixel(dpy, screen), WhitePixel(dpy, screen)); ++ else ++ XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c->pre.y, c->pre.scaled_image->width, c->pre.scaled_image->height); ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); ++ XUnmapWindow(dpy, c->win); ++ if (c->pre.win){ ++ XSelectInput(dpy, c->pre.win, ButtonPress | EnterWindowMask | LeaveWindowMask ); ++ XMapWindow(dpy, c->pre.win); ++ GC gc = XCreateGC(dpy, c->pre.win, 0, NULL); ++ XPutImage(dpy, c->pre.win, gc, c->pre.scaled_image, 0, 0, 0, 0, c->pre.scaled_image->width, c->pre.scaled_image->height); ++ } ++ } ++ while (1) { ++ XNextEvent(dpy, &event); ++ if (event.type == ButtonPress) ++ if (event.xbutton.button == Button1){ ++ for(c = m->clients; c; c = c->next){ ++ XUnmapWindow(dpy, c->pre.win); ++ if (event.xbutton.window == c->pre.win){ ++ selmon->seltags ^= 1; /* toggle sel tagset */ ++ m->tagset[selmon->seltags] = c->tags; ++ focus_c = c; ++ focus(NULL); ++#ifdef AWESOMEBAR ++ if (HIDDEN(c)){ ++ showwin(c); ++ continue; ++ } ++#endif ++ } ++ /* If you hit awesomebar patch Unlock the notes below; ++ * And you should add the following line to "hidewin" Function ++ * c->pre.orig_image = getwindowximage(c); ++ * */ ++#ifdef AWESOMEBAR ++ if (HIDDEN(c)){ ++ continue; ++ } ++#endif ++ XMapWindow(dpy, c->win); ++ XDestroyImage(c->pre.orig_image); ++ XDestroyImage(c->pre.scaled_image); ++ } ++ break; ++ } ++ if (event.type == EnterNotify) ++ for(c = m->clients; c; c = c->next) ++ if (event.xcrossing.window == c->pre.win){ ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeSel][ColBorder].pixel); ++ break; ++ } ++ if (event.type == LeaveNotify) ++ for(c = m->clients; c; c = c->next) ++ if (event.xcrossing.window == c->pre.win){ ++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorder].pixel); ++ break; ++ } ++ } ++ arrange(m); ++ focus(focus_c); +} + +void +setpreviewwindowsizepositions(unsigned int n, Monitor *m, unsigned int gappo, unsigned int gappi){ -+ unsigned int i, j; -+ unsigned int cx, cy, cw, ch, cmaxh; -+ unsigned int cols, rows; -+ Client *c, *tmpc; ++ unsigned int i, j; ++ unsigned int cx, cy, cw, ch, cmaxh; ++ unsigned int cols, rows; ++ Client *c, *tmpc; + -+ if (n == 1) { -+ c = m->clients; -+ cw = (m->ww - 2 * gappo) * 0.8; -+ ch = (m->wh - 2 * gappo) * 0.9; -+ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); -+ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width) / 2; -+ c->pre.y = m->my + (m->mh - c->pre.scaled_image->height) / 2; -+ return; -+ } -+ if (n == 2) { -+ c = m->clients; -+ cw = (m->ww - 2 * gappo - gappi) / 2; -+ ch = (m->wh - 2 * gappo) * 0.7; -+ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); -+ c->next->pre.scaled_image = scaledownimage(c->next->pre.orig_image, cw, ch); -+ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width - gappi - c->next->pre.scaled_image->width) / 2; -+ c->pre.y = m->my + (m->mh - c->pre.scaled_image->height) / 2; -+ c->next->pre.x = c->pre.x + c->pre.scaled_image->width + gappi; -+ c->next->pre.y = m->my + (m->mh - c->next->pre.scaled_image->height) / 2; -+ return; -+ } -+ for (cols = 0; cols <= n / 2; cols++) -+ if (cols * cols >= n) -+ break; -+ rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols; -+ ch = (m->wh - 2 * gappo) / rows; -+ cw = (m->ww - 2 * gappo) / cols; -+ c = m->clients; -+ cy = 0; -+ for (i = 0; i < rows; i++) { -+ cx = 0; -+ cmaxh = 0; -+ tmpc = c; -+ for (int j = 0; j < cols; j++) { -+ if (!c) -+ break; -+ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); -+ c->pre.x = cx; -+ cmaxh = c->pre.scaled_image->height > cmaxh ? c->pre.scaled_image->height : cmaxh; -+ cx += c->pre.scaled_image->width + gappi; -+ c = c->next; -+ } -+ c = tmpc; -+ cx = m->wx + (m->ww - cx) / 2; -+ for (j = 0; j < cols; j++) { -+ if (!c) -+ break; -+ c->pre.x += cx; -+ c->pre.y = cy + (cmaxh - c->pre.scaled_image->height) / 2; -+ c = c->next; -+ } -+ cy += cmaxh + gappi; -+ } -+ cy = m->wy + (m->wh - cy) / 2; -+ for (c = m->clients; c; c = c->next) -+ c->pre.y += cy; ++ if (n == 1) { ++ c = m->clients; ++ cw = (m->ww - 2 * gappo) * 0.8; ++ ch = (m->wh - 2 * gappo) * 0.9; ++ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); ++ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width) / 2; ++ c->pre.y = m->my + (m->mh - c->pre.scaled_image->height) / 2; ++ return; ++ } ++ if (n == 2) { ++ c = m->clients; ++ cw = (m->ww - 2 * gappo - gappi) / 2; ++ ch = (m->wh - 2 * gappo) * 0.7; ++ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); ++ c->next->pre.scaled_image = scaledownimage(c->next->pre.orig_image, cw, ch); ++ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width - gappi - c->next->pre.scaled_image->width) / 2; ++ c->pre.y = m->my + (m->mh - c->pre.scaled_image->height) / 2; ++ c->next->pre.x = c->pre.x + c->pre.scaled_image->width + gappi; ++ c->next->pre.y = m->my + (m->mh - c->next->pre.scaled_image->height) / 2; ++ return; ++ } ++ for (cols = 0; cols <= n / 2; cols++) ++ if (cols * cols >= n) ++ break; ++ rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols; ++ ch = (m->wh - 2 * gappo) / rows; ++ cw = (m->ww - 2 * gappo) / cols; ++ c = m->clients; ++ cy = 0; ++ for (i = 0; i < rows; i++) { ++ cx = 0; ++ cmaxh = 0; ++ tmpc = c; ++ for (int j = 0; j < cols; j++) { ++ if (!c) ++ break; ++ c->pre.scaled_image = scaledownimage(c->pre.orig_image, cw, ch); ++ c->pre.x = cx; ++ cmaxh = c->pre.scaled_image->height > cmaxh ? c->pre.scaled_image->height : cmaxh; ++ cx += c->pre.scaled_image->width + gappi; ++ c = c->next; ++ } ++ c = tmpc; ++ cx = m->wx + (m->ww - cx) / 2; ++ for (j = 0; j < cols; j++) { ++ if (!c) ++ break; ++ c->pre.x += cx; ++ c->pre.y = cy + (cmaxh - c->pre.scaled_image->height) / 2; ++ c = c->next; ++ } ++ cy += cmaxh + gappi; ++ } ++ cy = m->wy + (m->wh - cy) / 2; ++ for (c = m->clients; c; c = c->next) ++ c->pre.y += cy; +} + -+XImage -+*getwindowximage(Client *c) { -+ XCompositeRedirectWindow(dpy, c->win, CompositeRedirectAutomatic); -+ XWindowAttributes attr; -+ XGetWindowAttributes( dpy, c->win, &attr ); -+ XRenderPictFormat *format = XRenderFindVisualFormat( dpy, attr.visual ); -+ int hasAlpha = ( format->type == PictTypeDirect && format->direct.alphaMask ); -+ XRenderPictureAttributes pa; -+ pa.subwindow_mode = IncludeInferiors; -+ Picture picture = XRenderCreatePicture( dpy, c->win, format, CPSubwindowMode, &pa ); -+ Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); -+ XRenderPictureAttributes pa2; -+ XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, PictStandardARGB32); -+ Picture pixmapPicture = XRenderCreatePicture( dpy, pixmap, format2, 0, &pa2 ); -+ XRenderColor color; -+ color.red = 0x0000; -+ color.green = 0x0000; -+ color.blue = 0x0000; -+ color.alpha = 0x0000; -+ XRenderFillRectangle (dpy, PictOpSrc, pixmapPicture, &color, 0, 0, c->w, c->h); -+ XRenderComposite(dpy, hasAlpha ? PictOpOver : PictOpSrc, picture, 0, -+ pixmapPicture, 0, 0, 0, 0, 0, 0, -+ c->w, c->h); -+ XImage* temp = XGetImage( dpy, pixmap, 0, 0, c->w, c->h, AllPlanes, ZPixmap ); -+ temp->red_mask = format2->direct.redMask << format2->direct.red; -+ temp->green_mask = format2->direct.greenMask << format2->direct.green; -+ temp->blue_mask = format2->direct.blueMask << format2->direct.blue; -+ temp->depth = DefaultDepth(dpy, screen); -+ XCompositeUnredirectWindow(dpy, c->win, CompositeRedirectAutomatic); -+ return temp; ++XImage* ++getwindowximage(Client *c) { ++ XWindowAttributes attr; ++ XGetWindowAttributes( dpy, c->win, &attr ); ++ XRenderPictFormat *format = XRenderFindVisualFormat( dpy, attr.visual ); ++ int hasAlpha = ( format->type == PictTypeDirect && format->direct.alphaMask ); ++ XRenderPictureAttributes pa; ++ pa.subwindow_mode = IncludeInferiors; ++ Picture picture = XRenderCreatePicture( dpy, c->win, format, CPSubwindowMode, &pa ); ++ Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); ++ XRenderPictureAttributes pa2; ++ XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, PictStandardARGB32); ++ Picture pixmapPicture = XRenderCreatePicture( dpy, pixmap, format2, 0, &pa2 ); ++ XRenderColor color; ++ color.red = 0x0000; ++ color.green = 0x0000; ++ color.blue = 0x0000; ++ color.alpha = 0x0000; ++ XRenderFillRectangle (dpy, PictOpSrc, pixmapPicture, &color, 0, 0, c->w, c->h); ++ XRenderComposite(dpy, hasAlpha ? PictOpOver : PictOpSrc, picture, 0, ++ pixmapPicture, 0, 0, 0, 0, 0, 0, ++ c->w, c->h); ++ XImage* temp = XGetImage( dpy, pixmap, 0, 0, c->w, c->h, AllPlanes, ZPixmap ); ++ temp->red_mask = format2->direct.redMask << format2->direct.red; ++ temp->green_mask = format2->direct.greenMask << format2->direct.green; ++ temp->blue_mask = format2->direct.blueMask << format2->direct.blue; ++ temp->depth = DefaultDepth(dpy, screen); ++ return temp; +} + -+XImage -+*scaledownimage(XImage *orig_image, unsigned int cw, unsigned int ch) { -+ int factor_w = orig_image->width / cw + 1; -+ int factor_h = orig_image->height / ch + 1; -+ int scale_factor = factor_w > factor_h ? factor_w : factor_h; -+ int scaled_width = orig_image->width / scale_factor; -+ int scaled_height = orig_image->height / scale_factor; -+ XImage *scaled_image = XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), -+ orig_image->depth, -+ ZPixmap, 0, NULL, -+ scaled_width, scaled_height, -+ 32, 0); -+ scaled_image->data = malloc(scaled_image->height * scaled_image->bytes_per_line); -+ for (int y = 0; y < scaled_height; y++) { -+ for (int x = 0; x < scaled_width; x++) { -+ int orig_x = x * scale_factor; -+ int orig_y = y * scale_factor; -+ unsigned long pixel = XGetPixel(orig_image, orig_x, orig_y); -+ XPutPixel(scaled_image, x, y, pixel); -+ } -+ } -+ scaled_image->depth = orig_image->depth; -+ return scaled_image; ++XImage* ++scaledownimage(XImage *orig_image, unsigned int cw, unsigned int ch) { ++ int factor_w = orig_image->width / cw + 1; ++ int factor_h = orig_image->height / ch + 1; ++ int scale_factor = factor_w > factor_h ? factor_w : factor_h; ++ int scaled_width = orig_image->width / scale_factor; ++ int scaled_height = orig_image->height / scale_factor; ++ XImage *scaled_image = XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), ++ orig_image->depth, ++ ZPixmap, 0, NULL, ++ scaled_width, scaled_height, ++ 32, 0); ++ scaled_image->data = malloc(scaled_image->height * scaled_image->bytes_per_line); ++ for (int y = 0; y < scaled_height; y++) { ++ for (int x = 0; x < scaled_width; x++) { ++ int orig_x = x * scale_factor; ++ int orig_y = y * scale_factor; ++ unsigned long pixel = XGetPixel(orig_image, orig_x, orig_y); ++ XPutPixel(scaled_image, x, y, pixel); ++ } ++ } ++ scaled_image->depth = orig_image->depth; ++ return scaled_image; +} + int main(int argc, char *argv[]) { +-- +2.48.1 + diff --git a/dwm.suckless.org/patches/preview-all-win/index.md b/dwm.suckless.org/patches/preview-all-win/index.md @@ -3,25 +3,35 @@ preview all windows Description ----------- -Allows you to preview all window image thumbnails under the current display, and when clicked, it will jump to the corresponding application window +Allows you to preview all window image thumbnails under the current display, +and when clicked, it will jump to the corresponding application window. -![preview all windows](./preview-all-windows.png) - -I used two x11 extensions, xcomposite's off-screen storage feature and xrender to get the window image +[![preview all windows](preview-all-windows.png)](preview-all-windows.png) +I used two X11 extensions — XComposite's off-screen storage feature +and XRender — to capture the window image. > [!WARNING] -> If you're using patches for fullscreen and hidewin, please follow the comments in my patches and adjust the code to suit the effects of other patches - -> The project is still in the development stage, and there are still many problems, such as: without using a renderer like picom, the window image will not be available, but fortunately there is no crash +> The project is still in development. -> (I'm sorry because I've been using picom and this issue didn't come to me until I was making diff) +> If you're using patches like `actualfullscreen` or `awesomebar`, please uncomment +> the corresponding one in `config.def.h`. +``` +#define ACTUALFULLSCREEN +#define AWESOMEBAR +``` Download -------- -* [dwm-preview-all-windows-6.5.diff](./dwm-preview-all-windows-6.5.diff) +* [dwm-preview-all-windows-6.5.diff](dwm-preview-all-windows-6.5.diff) + +This patch is like the above, with keys to select windows in the preview. +`Mod + j`/`Mod + k` to setect a window, `Mod + Return` to open it. + +* [dwm-preview-all-windows-20250407-e381933.diff](dwm-preview-all-windows-20250407-e381933.diff) -Author ------- +Authors +------- * HJ-Zhang - <hjzhang216@gmail.com> +* El Bachir - <bachiralfa@gmail.com>