commit 993b2c6eef89253717974d588075f5b3aa423ca4
Author: steve <[email protected]>
Date:   Tue Jul 9 23:07:44 2024 +0800

    [dwm][patch][preview-all-windows] dwm patch for preview all windows

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
new file mode 100644
index 00000000..8b989201
--- /dev/null
+++ b/dwm.suckless.org/patches/preview-all-win/dwm-preview-all-windows-6.5.diff
@@ -0,0 +1,280 @@
+diff --git a/config.def.h b/config.def.h
+index 9efa774..2992668 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -95,6 +95,7 @@ static const Key keys[] = {
+       TAGKEYS(                        XK_8,                      7)
+       TAGKEYS(                        XK_9,                      8)
+       { MODKEY|ShiftMask,             XK_q,      quit,           {0} },
++      { MODKEY,                       XK_r,      previewallwin,  {0} },
+ };
+ 
+ /* button definitions */
+diff --git a/config.mk b/config.mk
+index 8efca9a..8d7c303 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 -lXrender -lXcomposite ${XINERAMALIBS} 
${FREETYPELIBS}
+ 
+ # 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..bf30141 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -40,6 +40,8 @@
+ #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 {
+ 
+ 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;
+@@ -97,6 +109,7 @@ struct Client {
+       Client *snext;
+       Monitor *mon;
+       Window win;
++  Preview pre;
+ };
+ 
+ typedef struct {
+@@ -233,6 +246,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);
++static void previewallwin();
++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";
+@@ -2140,6 +2157,205 @@ 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.
");
++    return;
++  }
++  Monitor *m = selmon;
++  Client *c;
++  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);
++    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);
++                /* 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);
++}
++
++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) {
++  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 *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[])
+ {
diff --git a/dwm.suckless.org/patches/preview-all-win/index.md 
b/dwm.suckless.org/patches/preview-all-win/index.md
new file mode 100644
index 00000000..1fa6f348
--- /dev/null
+++ b/dwm.suckless.org/patches/preview-all-win/index.md
@@ -0,0 +1,27 @@
+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
+
+![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
+
+
+> [!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
+
+> (I'm sorry because I've been using picom and this issue didn't come to me 
until I was making diff)
+
+Download
+--------
+* [dwm-preview-all-windows-6.5.diff](./dwm-preview-all-windows-6.5.diff)
+
+Author
+------
+* HJ-Zhang - <[email protected]>
diff --git a/dwm.suckless.org/patches/preview-all-win/preview-all-windows.png 
b/dwm.suckless.org/patches/preview-all-win/preview-all-windows.png
new file mode 100644
index 00000000..54d7b819
Binary files /dev/null and 
b/dwm.suckless.org/patches/preview-all-win/preview-all-windows.png differ


Reply via email to