[dwm][patches][preview-all-win] - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
commit eab1efe2663368fe804d099e439b0eb648ed3e44 | |
parent 415383b09670c5081f7bfe291144c80c38227722 | |
Author: elbachir-one <[email protected]> | |
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: | |
A dwm.suckless.org/patches/preview-a… | 403 +++++++++++++++++++++++++++… | |
M dwm.suckless.org/patches/preview-a… | 429 ++++++++++++++++-----------… | |
M dwm.suckless.org/patches/preview-a… | 32 ++++++++++++++++++++-------… | |
3 files changed, 643 insertions(+), 221 deletions(-) | |
--- | |
diff --git a/dwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-2… | |
@@ -0,0 +1,403 @@ | |
+From e381933255718c6ed30e1b930d8fd76d62ccda75 Mon Sep 17 00:00:00 2001 | |
+From: elbachir-one <[email protected]> | |
+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 adde… | |
++//#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=\"$… | |
+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, unsigne… | |
++static XImage *getwindowximage(Client *c); | |
++static XImage *scaledownimage(XImage *orig_image, unsigned int cw, unsigned i… | |
+ | |
+ /* 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.scaled_image->width, c->pre.sc… | |
++ 1, BlackPixel(dpy, screen), WhitePixe… | |
++ else | |
++ XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c->pre.y, | |
++ c->pre.scaled_image->width, c->pre.sc… | |
++ | |
++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorde… | |
++ XUnmapWindow(dpy, c->win); | |
++ | |
++ if (c->pre.win) { | |
++ XSelectInput(dpy, c->pre.win, ButtonPress | EnterWind… | |
++ 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… | |
++ c->pre.scaled_image->width, c->pre.sc… | |
++ } | |
++ } | |
++ | |
++ int selected_idx = 0; | |
++ | |
++ while (previewallwin) { | |
++ XNextEvent(dpy, &event); | |
++ if (event.type == ButtonPress) { | |
++ if (event.xbutton.button == Button1) { /* Left-click … | |
++ for (c = selmon->clients; c; c = c->next) { | |
++ if (event.xbutton.window == c->pre.wi… | |
++ previewallwin = 0; | |
++ selmon->tagset[selmon->seltag… | |
++ focus(c); | |
++ arrange(selmon); /* Ensure la… | |
++ 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_Re… | |
++ 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] = sel… | |
++ 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] = sel… | |
++ 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, sch… | |
++ 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, sch… | |
++ break; | |
++ } | |
++ } | |
++ } | |
++ } | |
++ for (c = selmon->clients; c; c = c->next) { /* Restore all windows wh… | |
++ 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][C… | |
++ } else { | |
++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][… | |
++ } | |
++ } | |
++} | |
++ | |
++void | |
++setpreviewwindowsizepositions(unsigned int n, Monitor *m, unsigned int gappo,… | |
++ 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, c… | |
++ 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, c… | |
++ c->next->pre.scaled_image = scaledownimage(c->next->pre.orig_… | |
++ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width - gapp… | |
++ 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 + gapp… | |
++ c->next->pre.y = m->my + (m->mh - c->next->pre.scaled_image->… | |
++ 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_imag… | |
++ c->pre.x = cx; | |
++ cmaxh = c->pre.scaled_image->height > cmaxh ? c->pre.… | |
++ 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)… | |
++ 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.alp… | |
++ XRenderPictureAttributes pa; | |
++ pa.subwindow_mode = IncludeInferiors; | |
++ Picture picture = XRenderCreatePicture( dpy, c->win, format, CPSubwin… | |
++ Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); | |
++ XRenderPictureAttributes pa2; | |
++ XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, PictStand… | |
++ Picture pixmapPicture = XRenderCreatePicture( dpy, pixmap, format2, 0… | |
++ XRenderColor color; | |
++ color.red = 0x0000; | |
++ color.green = 0x0000; | |
++ color.blue = 0x0000; | |
++ color.alpha = 0x0000; | |
++ XRenderFillRectangle (dpy, PictOpSrc, pixmapPicture, &color, 0, 0, c-… | |
++ 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, Z… | |
++ 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, DefaultSc… | |
++ orig_image->depth, | |
++ ZPixmap, 0, NULL, | |
++ scaled_width, scaled_height, | |
++ 32, 0); | |
++ scaled_image->data = malloc(scaled_image->height * scaled_image->byte… | |
++ 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, o… | |
++ 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… | |
@@ -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 adde… | |
++//#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} ${FREETYPELIB… | |
++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender | |
# flags | |
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"$… | |
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_… | |
-+ 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.… | |
-+ else | |
-+ XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c->pre.y, c->pre.scaled_im… | |
-+ 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 | LeaveWind… | |
-+ XMapWindow(dpy, c->pre.win); | |
-+ XPutImage(dpy, c->pre.win, drw->gc, c->pre.scaled_image, 0, 0, 0, 0, c-… | |
-+ } | |
-+ } | |
-+ 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][ColBord… | |
-+ 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][ColBor… | |
-+ 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,… | |
++ else | |
++ XMoveResizeWindow(dpy, c->pre.win, c->pre.x, c->pre.y… | |
++ XSetWindowBorder(dpy, c->pre.win, scheme[SchemeNorm][ColBorde… | |
++ XUnmapWindow(dpy, c->win); | |
++ if (c->pre.win){ | |
++ XSelectInput(dpy, c->pre.win, ButtonPress | EnterWind… | |
++ 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… | |
++ } | |
++ } | |
++ 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.wi… | |
++ selmon->seltags ^= 1; /* togg… | |
++ m->tagset[selmon->seltags] = … | |
++ focus_c = c; | |
++ focus(NULL); | |
++#ifdef AWESOMEBAR | |
++ if (HIDDEN(c)){ | |
++ showwin(c); | |
++ continue; | |
++ } | |
++#endif | |
++ } | |
++ /* If you hit awesomebar patch Unlock… | |
++ * And you should add the following l… | |
++ * c->pre.orig_image = getwindowximag… | |
++ * */ | |
++#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, sch… | |
++ 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, sch… | |
++ break; | |
++ } | |
++ } | |
++ arrange(m); | |
++ focus(focus_c); | |
+} | |
+ | |
+void | |
+setpreviewwindowsizepositions(unsigned int n, Monitor *m, unsigned int gappo,… | |
-+ 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, c… | |
-+ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width - gappi - c->next-… | |
-+ 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->heig… | |
-+ 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, c… | |
++ 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, c… | |
++ c->next->pre.scaled_image = scaledownimage(c->next->pre.orig_… | |
++ c->pre.x = m->mx + (m->mw - c->pre.scaled_image->width - gapp… | |
++ 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 + gapp… | |
++ c->next->pre.y = m->my + (m->mh - c->next->pre.scaled_image->… | |
++ 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_imag… | |
++ c->pre.x = cx; | |
++ cmaxh = c->pre.scaled_image->height > cmaxh ? c->pre.… | |
++ 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)… | |
++ 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, CPSubwindowMod… | |
-+ Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); | |
-+ XRenderPictureAttributes pa2; | |
-+ XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, PictStandardARG… | |
-+ 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-… | |
-+ 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.alp… | |
++ XRenderPictureAttributes pa; | |
++ pa.subwindow_mode = IncludeInferiors; | |
++ Picture picture = XRenderCreatePicture( dpy, c->win, format, CPSubwin… | |
++ Pixmap pixmap = XCreatePixmap(dpy, root, c->w, c->h, 32); | |
++ XRenderPictureAttributes pa2; | |
++ XRenderPictFormat *format2 = XRenderFindStandardFormat(dpy, PictStand… | |
++ Picture pixmapPicture = XRenderCreatePicture( dpy, pixmap, format2, 0… | |
++ XRenderColor color; | |
++ color.red = 0x0000; | |
++ color.green = 0x0000; | |
++ color.blue = 0x0000; | |
++ color.alpha = 0x0000; | |
++ XRenderFillRectangle (dpy, PictOpSrc, pixmapPicture, &color, 0, 0, c-… | |
++ 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, Z… | |
++ 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(d… | |
-+ orig_image->depth, | |
-+ ZPixmap, 0, NULL, | |
-+ scaled_width, scaled_height, | |
-+ 32, 0); | |
-+ scaled_image->data = malloc(scaled_image->height * scaled_image->bytes_per_… | |
-+ 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, DefaultSc… | |
++ orig_image->depth, | |
++ ZPixmap, 0, NULL, | |
++ scaled_width, scaled_height, | |
++ 32, 0); | |
++ scaled_image->data = malloc(scaled_image->height * scaled_image->byte… | |
++ 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, o… | |
++ 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.o… | |
@@ -3,25 +3,35 @@ preview all windows | |
Description | |
----------- | |
-Allows you to preview all window image thumbnails under the current display, a… | |
+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… | |
+[](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 commen… | |
- | |
-> The project is still in the development stage, and there are still many prob… | |
+> The project is still in development. | |
-> (I'm sorry because I've been using picom and this issue didn't come to me un… | |
+> If you're using patches like `actualfullscreen` or `awesomebar`, please unco… | |
+> 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-2025… | |
-Author | |
------- | |
+Authors | |
+------- | |
* HJ-Zhang - <[email protected]> | |
+* El Bachir - <[email protected]> |