sites

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

dwm-tag-preview-6.2.diff (9776B)


      1 From 64c79048e03345937c66fbee01b871e44cd579bc Mon Sep 17 00:00:00 2001
      2 From: explosion-mental <explosion0mental@gmail.com>
      3 Date: Tue, 12 Oct 2021 11:57:54 -0500
      4 Subject: [PATCH] [update] fixed scale preview on `XCreateWindow` and added
      5  some comments Allows you to see the contents of an already viewed tag. So a
      6  more accurate description would be to re-view a tag.
      7 
      8 ---
      9  config.def.h |   1 +
     10  config.mk    |   5 +-
     11  dwm.c        | 164 ++++++++++++++++++++++++++++++++++++++++++++-------
     12  3 files changed, 147 insertions(+), 23 deletions(-)
     13 
     14 diff --git a/config.def.h b/config.def.h
     15 index 1c0b587..897bf0c 100644
     16 --- a/config.def.h
     17 +++ b/config.def.h
     18 @@ -3,6 +3,7 @@
     19  /* appearance */
     20  static const unsigned int borderpx  = 1;        /* border pixel of windows */
     21  static const unsigned int snap      = 32;       /* snap pixel */
     22 +static const int scalepreview       = 4;        /* tag preview scaling */
     23  static const int showbar            = 1;        /* 0 means no bar */
     24  static const int topbar             = 1;        /* 0 means bottom bar */
     25  static const char *fonts[]          = { "monospace:size=10" };
     26 diff --git a/config.mk b/config.mk
     27 index 6d36cb7..699007f 100644
     28 --- a/config.mk
     29 +++ b/config.mk
     30 @@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2
     31  # OpenBSD (uncomment)
     32  #FREETYPEINC = ${X11INC}/freetype2
     33  
     34 +# Imlib2 (tag previews)
     35 +IMLIB2LIBS = -lImlib2
     36 +
     37  # includes and libs
     38  INCS = -I${X11INC} -I${FREETYPEINC}
     39 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
     40 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS}
     41  
     42  # flags
     43  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
     44 diff --git a/dwm.c b/dwm.c
     45 index 4465af1..878abc1 100644
     46 --- a/dwm.c
     47 +++ b/dwm.c
     48 @@ -40,6 +40,7 @@
     49  #include <X11/extensions/Xinerama.h>
     50  #endif /* XINERAMA */
     51  #include <X11/Xft/Xft.h>
     52 +#include <Imlib2.h>
     53  
     54  #include "drw.h"
     55  #include "util.h"
     56 @@ -111,27 +112,6 @@ typedef struct {
     57  	void (*arrange)(Monitor *);
     58  } Layout;
     59  
     60 -struct Monitor {
     61 -	char ltsymbol[16];
     62 -	float mfact;
     63 -	int nmaster;
     64 -	int num;
     65 -	int by;               /* bar geometry */
     66 -	int mx, my, mw, mh;   /* screen size */
     67 -	int wx, wy, ww, wh;   /* window area  */
     68 -	unsigned int seltags;
     69 -	unsigned int sellt;
     70 -	unsigned int tagset[2];
     71 -	int showbar;
     72 -	int topbar;
     73 -	Client *clients;
     74 -	Client *sel;
     75 -	Client *stack;
     76 -	Monitor *next;
     77 -	Window barwin;
     78 -	const Layout *lt[2];
     79 -};
     80 -
     81  typedef struct {
     82  	const char *class;
     83  	const char *instance;
     84 @@ -204,8 +184,10 @@ static void setmfact(const Arg *arg);
     85  static void setup(void);
     86  static void seturgent(Client *c, int urg);
     87  static void showhide(Client *c);
     88 +static void showtagpreview(int tag);
     89  static void sigchld(int unused);
     90  static void spawn(const Arg *arg);
     91 +static void switchtag(void);
     92  static void tag(const Arg *arg);
     93  static void tagmon(const Arg *arg);
     94  static void tile(Monitor *);
     95 @@ -224,6 +206,7 @@ static void updatenumlockmask(void);
     96  static void updatesizehints(Client *c);
     97  static void updatestatus(void);
     98  static void updatetitle(Client *c);
     99 +static void updatepreview(void);
    100  static void updatewindowtype(Client *c);
    101  static void updatewmhints(Client *c);
    102  static void view(const Arg *arg);
    103 @@ -271,6 +254,36 @@ static Window root, wmcheckwin;
    104  /* configuration, allows nested code to access above variables */
    105  #include "config.h"
    106  
    107 +/* We only move this here to get the length of the `tags` array, which probably
    108 + * will generate compatibility issues with other patches. To avoid it, I
    109 + * reccomend patching this at the end or continue with the comment below */
    110 +struct Monitor {
    111 +	char ltsymbol[16];
    112 +	float mfact;
    113 +	int nmaster;
    114 +	int num;
    115 +	int by;               /* bar geometry */
    116 +	int mx, my, mw, mh;   /* screen size */
    117 +	int wx, wy, ww, wh;   /* window area  */
    118 +	unsigned int seltags;
    119 +	unsigned int sellt;
    120 +	unsigned int tagset[2];
    121 +	int previewshow;
    122 +	int showbar;
    123 +	int topbar;
    124 +	Client *clients;
    125 +	Client *sel;
    126 +	Client *stack;
    127 +	Monitor *next;
    128 +	Window barwin;
    129 +	Window tagwin;
    130 +	//change 'LENGTH(tags)' to the actual number of tags you have (9 by def)
    131 +	//if you wish to move this below config.h
    132 +	Pixmap tagmap[LENGTH(tags)];
    133 +	const Layout *lt[2];
    134 +};
    135 +
    136 +
    137  /* compile-time check if all tags fit into an unsigned int bit array. */
    138  struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
    139  
    140 @@ -430,6 +443,10 @@ buttonpress(XEvent *e)
    141  		focus(NULL);
    142  	}
    143  	if (ev->window == selmon->barwin) {
    144 +		if (selmon->previewshow) {
    145 +			XUnmapWindow(dpy, selmon->tagwin);
    146 +				selmon->previewshow = 0;
    147 +		}
    148  		i = x = 0;
    149  		do
    150  			x += TEXTW(tags[i]);
    151 @@ -497,6 +514,7 @@ void
    152  cleanupmon(Monitor *mon)
    153  {
    154  	Monitor *m;
    155 +	size_t i;
    156  
    157  	if (mon == mons)
    158  		mons = mons->next;
    159 @@ -504,8 +522,13 @@ cleanupmon(Monitor *mon)
    160  		for (m = mons; m && m->next != mon; m = m->next);
    161  		m->next = mon->next;
    162  	}
    163 +	for (i = 0; i < LENGTH(tags); i++)
    164 +		if (mon->tagmap[i])
    165 +			XFreePixmap(dpy, mon->tagmap[i]);
    166  	XUnmapWindow(dpy, mon->barwin);
    167  	XDestroyWindow(dpy, mon->barwin);
    168 +	XUnmapWindow(dpy, mon->tagwin);
    169 +	XDestroyWindow(dpy, mon->tagwin);
    170  	free(mon);
    171  }
    172  
    173 @@ -1121,7 +1144,30 @@ motionnotify(XEvent *e)
    174  	static Monitor *mon = NULL;
    175  	Monitor *m;
    176  	XMotionEvent *ev = &e->xmotion;
    177 +	unsigned int i, x;
    178 +
    179 +	if (ev->window == selmon->barwin) {
    180 +		i = x = 0;
    181 +		do
    182 +			x += TEXTW(tags[i]);
    183 +		while (ev->x >= x && ++i < LENGTH(tags));
    184  
    185 +		if (i < LENGTH(tags)) {
    186 +			if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) {
    187 +				selmon->previewshow = i + 1;
    188 +				showtagpreview(i);
    189 +			} else if (selmon->tagset[selmon->seltags] & 1 << i) {
    190 +				selmon->previewshow = 0;
    191 +				showtagpreview(0);
    192 +			}
    193 +		} else if (selmon->previewshow != 0) {
    194 +			selmon->previewshow = 0;
    195 +			showtagpreview(0);
    196 +		}
    197 +	} else if (selmon->previewshow != 0) {
    198 +		selmon->previewshow = 0;
    199 +		showtagpreview(0);
    200 +	}
    201  	if (ev->window != root)
    202  		return;
    203  	if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
    204 @@ -1573,6 +1619,7 @@ setup(void)
    205  	/* init bars */
    206  	updatebars();
    207  	updatestatus();
    208 +	updatepreview();
    209  	/* supporting window for NetWMCheck */
    210  	wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
    211  	XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
    212 @@ -1628,6 +1675,23 @@ showhide(Client *c)
    213  	}
    214  }
    215  
    216 +void
    217 +showtagpreview(int tag)
    218 +{
    219 +	if (!selmon->previewshow) {
    220 +		XUnmapWindow(dpy, selmon->tagwin);
    221 +		return;
    222 +	}
    223 +
    224 +        if (selmon->tagmap[tag]) {
    225 +		XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[tag]);
    226 +		XCopyArea(dpy, selmon->tagmap[tag], selmon->tagwin, drw->gc, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview, 0, 0);
    227 +		XSync(dpy, False);
    228 +		XMapWindow(dpy, selmon->tagwin);
    229 +	} else
    230 +		XUnmapWindow(dpy, selmon->tagwin);
    231 +}
    232 +
    233  void
    234  sigchld(int unused)
    235  {
    236 @@ -1652,6 +1716,40 @@ spawn(const Arg *arg)
    237  	}
    238  }
    239  
    240 +void
    241 +switchtag(void)
    242 +{
    243 +	int i;
    244 +	unsigned int occ = 0;
    245 +	Client *c;
    246 +	Imlib_Image image;
    247 +
    248 +	for (c = selmon->clients; c; c = c->next)
    249 +		occ |= c->tags;
    250 +	for (i = 0; i < LENGTH(tags); i++) {
    251 +		if (selmon->tagset[selmon->seltags] & 1 << i) {
    252 +			if (selmon->tagmap[i] != 0) {
    253 +				XFreePixmap(dpy, selmon->tagmap[i]);
    254 +				selmon->tagmap[i] = 0;
    255 +			}
    256 +			if (occ & 1 << i) {
    257 +				image = imlib_create_image(sw, sh);
    258 +				imlib_context_set_image(image);
    259 +				imlib_context_set_display(dpy);
    260 +				imlib_context_set_visual(DefaultVisual(dpy, screen));
    261 +				imlib_context_set_drawable(RootWindow(dpy, screen));
    262 +				//uncomment the following line and comment the other imlin_copy.. line if you don't want the bar showing on the preview
    263 +				//imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww ,selmon->wh, 0, 0, 1);
    264 +				imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1);
    265 +				selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen));
    266 +				imlib_context_set_drawable(selmon->tagmap[i]);
    267 +				imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview);
    268 +				imlib_free_image();
    269 +			}
    270 +		}
    271 +	}
    272 +}
    273 +
    274  void
    275  tag(const Arg *arg)
    276  {
    277 @@ -1740,6 +1838,7 @@ toggleview(const Arg *arg)
    278  	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
    279  
    280  	if (newtagset) {
    281 +		switchtag();
    282  		selmon->tagset[selmon->seltags] = newtagset;
    283  		focus(NULL);
    284  		arrange(selmon);
    285 @@ -1805,7 +1904,7 @@ updatebars(void)
    286  	XSetWindowAttributes wa = {
    287  		.override_redirect = True,
    288  		.background_pixmap = ParentRelative,
    289 -		.event_mask = ButtonPressMask|ExposureMask
    290 +		.event_mask = ButtonPressMask|ExposureMask|PointerMotionMask
    291  	};
    292  	XClassHint ch = {"dwm", "dwm"};
    293  	for (m = mons; m; m = m->next) {
    294 @@ -2001,6 +2100,26 @@ updatetitle(Client *c)
    295  		strcpy(c->name, broken);
    296  }
    297  
    298 +void
    299 +updatepreview(void)
    300 +{
    301 +	Monitor *m;
    302 +
    303 +	XSetWindowAttributes wa = {
    304 +		.override_redirect = True,
    305 +		.background_pixmap = ParentRelative,
    306 +		.event_mask = ButtonPressMask|ExposureMask
    307 +	};
    308 +	for (m = mons; m; m = m->next) {
    309 +		m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, m->mw / scalepreview, m->mh / scalepreview, 0,
    310 +				DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
    311 +				CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
    312 +		XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor);
    313 +		XMapRaised(dpy, m->tagwin);
    314 +		XUnmapWindow(dpy, m->tagwin);
    315 +	}
    316 +}
    317 +
    318  void
    319  updatewindowtype(Client *c)
    320  {
    321 @@ -2037,6 +2156,7 @@ view(const Arg *arg)
    322  {
    323  	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    324  		return;
    325 +	switchtag();
    326  	selmon->seltags ^= 1; /* toggle sel tagset */
    327  	if (arg->ui & TAGMASK)
    328  		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
    329 -- 
    330 2.33.0
    331