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:
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.
-
-
-I used two x11 extensions, xcomposite's off-screen storage feature and xrender to get the window image
+[](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>