sites

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

dwm-canvas-6.2.diff (13152B)


      1 diff --git a/config.def.h b/config.def.h
      2 index 81c3fc0..9154d29 100644
      3 --- a/config.def.h
      4 +++ b/config.def.h
      5 @@ -18,6 +18,9 @@ static const char *colors[][3]      = {
      6  	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  },
      7  };
      8  
      9 +#define MOVE_CANVAS_STEP 120
     10 +#define COORDINATES_DIVISOR 10
     11 +
     12  /* tagging */
     13  static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
     14  
     15 @@ -86,6 +89,12 @@ static const Key keys[] = {
     16  	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } },
     17  	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
     18  	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
     19 +	{ MODKEY,                       XK_r,      homecanvas,       {0} }, // Return to x:0, y:0 position
     20 +	{ MODKEY|ShiftMask,             XK_Left,   movecanvas,       {.i = 0} }, // Move your position to left
     21 +	{ MODKEY|ShiftMask,             XK_Right,  movecanvas,       {.i = 1} }, // Move your position to right
     22 +	{ MODKEY|ShiftMask,             XK_Up,     movecanvas,       {.i = 2} }, // Move your position up
     23 +	{ MODKEY|ShiftMask,             XK_Down,   movecanvas,       {.i = 3} }, // Move your position down
     24 +	{ MODKEY|ShiftMask,             XK_d,      centerwindow,     {0} },
     25  	TAGKEYS(                        XK_1,                      0)
     26  	TAGKEYS(                        XK_2,                      1)
     27  	TAGKEYS(                        XK_3,                      2)
     28 @@ -113,5 +122,7 @@ static const Button buttons[] = {
     29  	{ ClkTagBar,            0,              Button3,        toggleview,     {0} },
     30  	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} },
     31  	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },
     32 +	{ ClkRootWin,      MODKEY|ShiftMask,         Button1,        manuallymovecanvas,     {0} },
     33 +	{ ClkClientWin,    MODKEY|ShiftMask,         Button1,        manuallymovecanvas,     {0} }
     34  };
     35  
     36 diff --git a/dwm.c b/dwm.c
     37 index ab3a84c..c70ff19 100644
     38 --- a/dwm.c
     39 +++ b/dwm.c
     40 @@ -56,6 +56,11 @@
     41  #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
     42  #define TEXTW(X)                (drw_fontset_getwidth(drw, (X)) + lrpad)
     43  
     44 +#if !WINDOWMAP
     45 +	#undef WINDOWMAP
     46 +	#define WINDOWMAP 1
     47 +#endif
     48 +
     49  /* enums */
     50  enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
     51  enum { SchemeNorm, SchemeSel }; /* color schemes */
     52 @@ -96,6 +101,10 @@ struct Client {
     53  	Client *snext;
     54  	Monitor *mon;
     55  	Window win;
     56 +	int saved_cx, saved_cy;
     57 +	int saved_cw, saved_ch;
     58 +	int was_on_canvas;
     59 +	int ismapped;
     60  };
     61  
     62  typedef struct {
     63 @@ -110,6 +119,11 @@ typedef struct {
     64  	void (*arrange)(Monitor *);
     65  } Layout;
     66  
     67 +typedef struct {
     68 +	int cx, cy;
     69 +	int saved_cx, saved_cy;
     70 +} CanvasOffset;
     71 +
     72  struct Monitor {
     73  	char ltsymbol[16];
     74  	float mfact;
     75 @@ -129,6 +143,7 @@ struct Monitor {
     76  	Monitor *next;
     77  	Window barwin;
     78  	const Layout *lt[2];
     79 +	CanvasOffset *canvas;
     80  };
     81  
     82  typedef struct {
     83 @@ -267,8 +282,11 @@ static Drw *drw;
     84  static Monitor *mons, *selmon;
     85  static Window root, wmcheckwin;
     86  
     87 +#include "infinitetags.h"
     88 +
     89  /* configuration, allows nested code to access above variables */
     90  #include "config.h"
     91 +#include "infinitetags.c"
     92  
     93  /* compile-time check if all tags fit into an unsigned int bit array. */
     94  struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
     95 @@ -643,6 +661,12 @@ createmon(void)
     96  	m->lt[0] = &layouts[0];
     97  	m->lt[1] = &layouts[1 % LENGTH(layouts)];
     98  	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
     99 +	m->canvas = ecalloc(LENGTH(tags), sizeof(CanvasOffset));
    100 +	unsigned int i;
    101 +	for (i = 0; i < LENGTH(tags); i++){
    102 +		m->canvas[i].cx = 0;
    103 +		m->canvas[i].cy = 0;
    104 +	}
    105  	return m;
    106  }
    107  
    108 @@ -719,6 +743,7 @@ drawbar(Monitor *m)
    109  			urg |= c->tags;
    110  	}
    111  	x = 0;
    112 +	
    113  	for (i = 0; i < LENGTH(tags); i++) {
    114  		w = TEXTW(tags[i]);
    115  		drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
    116 @@ -732,6 +757,20 @@ drawbar(Monitor *m)
    117  	w = TEXTW(m->ltsymbol);
    118  	drw_setscheme(drw, scheme[SchemeNorm]);
    119  	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
    120 +	
    121 +	/* Draw the coordinates in canvas mode */
    122 +	if (selmon->lt[selmon->sellt]->arrange == NULL){
    123 +		int tagidx = getcurrenttag(m);
    124 +		char coords[64];
    125 +		snprintf(coords, sizeof(coords), "[x%d y%d]",
    126 +			m->canvas[tagidx].cx / COORDINATES_DIVISOR,
    127 +			m->canvas[tagidx].cy / COORDINATES_DIVISOR);
    128 +		w = TEXTW(coords);
    129 +		drw_setscheme(drw, scheme[SchemeNorm]);
    130 +		drw_text(drw, x, 0, w, bh, lrpad / 2, coords, 0);
    131 +		x += w;
    132 +	}
    133 +	
    134  
    135  	if ((w = m->ww - tw - x) > bh) {
    136  		if (m->sel) {
    137 @@ -744,6 +783,7 @@ drawbar(Monitor *m)
    138  			drw_rect(drw, x, 0, w, bh, 1, 1);
    139  		}
    140  	}
    141 +	
    142  	drw_map(drw, m->barwin, 0, 0, m->ww, bh);
    143  }
    144  
    145 @@ -856,7 +896,7 @@ focusstack(const Arg *arg)
    146  	}
    147  	if (c) {
    148  		focus(c);
    149 -		restack(selmon);
    150 +		centerwindow(NULL);
    151  	}
    152  }
    153  
    154 @@ -1510,10 +1550,32 @@ setfullscreen(Client *c, int fullscreen)
    155  void
    156  setlayout(const Arg *arg)
    157  {
    158 +	const Layout *temp_new_layout = (arg && arg->v) ? (Layout *)arg->v : selmon->lt[selmon->sellt ^ 1];
    159 +	if (temp_new_layout == selmon->lt[selmon->sellt]) return;
    160 +
    161 +	const Layout *old_layout = selmon->lt[selmon->sellt];
    162 +
    163  	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
    164  		selmon->sellt ^= 1;
    165  	if (arg && arg->v)
    166  		selmon->lt[selmon->sellt] = (Layout *)arg->v;
    167 +
    168 +	const Layout *new_layout = selmon->lt[selmon->sellt];
    169 +	if (old_layout->arrange == NULL && new_layout->arrange != NULL) {
    170 +		save_canvas_positions(selmon);
    171 +		homecanvas(NULL);
    172 +		Client *c;
    173 +		for (c = selmon->clients; c; c = c->next)
    174 +			if (!c->isfixed) c->isfloating = 0;
    175 +	}
    176 +
    177 +	if (new_layout->arrange == NULL) {
    178 +		restore_canvas_positions(selmon);
    179 +		Client *c;
    180 +		for (c = selmon->clients; c; c = c->next)
    181 +			c->isfloating = 1;
    182 +	}
    183 +
    184  	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
    185  	if (selmon->sel)
    186  		arrange(selmon);
    187 @@ -1670,6 +1732,21 @@ void
    188  tag(const Arg *arg)
    189  {
    190  	if (selmon->sel && arg->ui & TAGMASK) {
    191 +		Client *c = selmon->sel;
    192 +		unsigned int target_tag_mask = arg->ui & TAGMASK;
    193 +		int i;
    194 +
    195 +		for (i = 0; i < LENGTH(tags); i++) {
    196 +			if (target_tag_mask & (1 << i)) {
    197 +				c->saved_cx = selmon->canvas[i].cx + (selmon->ww - WIDTH(c)) / 2;
    198 +				c->saved_cy = selmon->canvas[i].cy + (selmon->wh - HEIGHT(c)) / 2;
    199 +				c->saved_cw = c->w;
    200 +				c->saved_ch = c->h;
    201 +				c->was_on_canvas = 1;
    202 +				break;
    203 +			}
    204 +		}
    205 +
    206  		selmon->sel->tags = arg->ui & TAGMASK;
    207  		focus(NULL);
    208  		arrange(selmon);
    209 @@ -2053,11 +2130,26 @@ updatewmhints(Client *c)
    210  void
    211  view(const Arg *arg)
    212  {
    213 +	if (selmon->lt[selmon->sellt]->arrange == NULL)
    214 +		save_canvas_positions(selmon);
    215 +
    216  	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
    217  		return;
    218  	selmon->seltags ^= 1; /* toggle sel tagset */
    219  	if (arg->ui & TAGMASK)
    220  		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
    221 +
    222 +	int newtag = getcurrenttag(selmon);
    223 +	if (selmon->lt[selmon->sellt]->arrange != NULL){
    224 +		selmon->canvas[newtag].cx = 0;
    225 +		selmon->canvas[newtag].cy = 0;
    226 +	} else {
    227 +		restore_canvas_positions(selmon);
    228 +		Client *c;
    229 +		for (c = selmon->clients;c; c = c->next)
    230 +			if (ISVISIBLE(c))
    231 +				c->isfloating = 1;
    232 +	}
    233  	focus(NULL);
    234  	arrange(selmon);
    235  }
    236 diff --git a/infinitetags.c b/infinitetags.c
    237 new file mode 100644
    238 index 0000000..46267ee
    239 --- /dev/null
    240 +++ b/infinitetags.c
    241 @@ -0,0 +1,206 @@
    242 +int
    243 +getcurrenttag(Monitor *m) {
    244 +    unsigned int i;
    245 +    for (i = 0; i < LENGTH(tags) && !(m->tagset[m->seltags] & (1 << i)); i++);
    246 +    return i < LENGTH(tags) ? i : 0;
    247 +}
    248 +
    249 +void
    250 +homecanvas(const Arg *arg) {
    251 +    Client *c;
    252 +    int tagidx = getcurrenttag(selmon);
    253 +    int cx = selmon->canvas[tagidx].cx;
    254 +    int cy = selmon->canvas[tagidx].cy;
    255 +    
    256 +    for (c = selmon->clients; c; c = c->next) {
    257 +        if (c->tags & (1 << tagidx)) {
    258 +            c->x -= cx;
    259 +            c->y -= cy;
    260 +            XMoveWindow(dpy, c->win, c->x, c->y);
    261 +        }
    262 +    }
    263 +    
    264 +    selmon->canvas[tagidx].cx = 0;
    265 +    selmon->canvas[tagidx].cy = 0;
    266 +    drawbar(selmon); 
    267 +    XFlush(dpy);
    268 +}
    269 +
    270 +void
    271 +movecanvas(const Arg *arg)
    272 +{
    273 +	if (selmon->lt[selmon->sellt]->arrange != NULL)
    274 +		return;
    275 +  if (selmon->sel && selmon->sel->isfullscreen)
    276 +    return;
    277 +
    278 +	int tagidx = getcurrenttag(selmon);
    279 +	int dx = 0, dy = 0;
    280 +	
    281 +#ifndef MOVE_CANVAS_STEP
    282 +#define MOVE_CANVAS_STEP 120
    283 +#endif
    284 +
    285 +	switch(arg->i) {
    286 +    case 0: dx = -MOVE_CANVAS_STEP; break;
    287 +		case 1: dx =  MOVE_CANVAS_STEP; break;
    288 +    case 2: dy = -MOVE_CANVAS_STEP; break;
    289 +		case 3: dy =  MOVE_CANVAS_STEP; break;
    290 +	}
    291 +
    292 +	selmon->canvas[tagidx].cx -= dx;
    293 +	selmon->canvas[tagidx].cy -= dy;
    294 +
    295 +	Client *c;
    296 +	for (c = selmon->clients; c; c = c->next) {
    297 +		if (ISVISIBLE(c)) {
    298 +			c->x -= dx;
    299 +			c->y -= dy;
    300 +			XMoveWindow(dpy, c->win, c->x, c->y);
    301 +		}
    302 +	}
    303 +
    304 +	drawbar(selmon);
    305 +}
    306 +
    307 +void
    308 +manuallymovecanvas(const Arg *arg) {
    309 +    if (selmon->lt[selmon->sellt]->arrange != NULL)
    310 +      return;
    311 +    if (selmon->sel && selmon->sel->isfullscreen)
    312 +      return;
    313 +    int start_x, start_y;
    314 +    Window dummy;
    315 +    int di;
    316 +    unsigned int dui;
    317 +    int tagidx = getcurrenttag(selmon);
    318 +#if LOCK_MOVE_RESIZE_REFRESH_RATE
    319 +    Time lasttime = 0;
    320 +#endif
    321 +
    322 +    if (!XQueryPointer(dpy, root, &dummy, &dummy, &start_x, &start_y, &di, &di, &dui))
    323 +        return;
    324 +    
    325 +    if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
    326 +        None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
    327 +        return;
    328 +    
    329 +    XEvent ev;
    330 +    do {
    331 +        XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
    332 +        
    333 +        switch (ev.type) {
    334 +        case MotionNotify:
    335 +        {
    336 +#if LOCK_MOVE_RESIZE_REFRESH_RATE
    337 +            if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate))
    338 +                continue;
    339 +            lasttime = ev.xmotion.time;
    340 +#endif
    341 +            int nx = ev.xmotion.x - start_x;
    342 +            int ny = ev.xmotion.y - start_y;
    343 +            
    344 +            for (Client *c = selmon->clients; c; c = c->next) {
    345 +                if (c->tags & (1 << tagidx)) {
    346 +                    c->x += nx;
    347 +                    c->y += ny;
    348 +                    XMoveWindow(dpy, c->win, c->x, c->y);
    349 +                }
    350 +            }
    351 +            
    352 +            selmon->canvas[tagidx].cx += nx;
    353 +            selmon->canvas[tagidx].cy += ny;
    354 +            drawbar(selmon); 
    355 +            start_x = ev.xmotion.x;
    356 +            start_y = ev.xmotion.y;
    357 +        }   break;
    358 +        }
    359 +    } while (ev.type != ButtonRelease);
    360 +    
    361 +    XUngrabPointer(dpy, CurrentTime);
    362 +}
    363 +
    364 +void
    365 +save_canvas_positions(Monitor *m) {
    366 +    Client *c;
    367 +    int tagidx = getcurrenttag(m);
    368 +    
    369 +    m->canvas[tagidx].saved_cx = m->canvas[tagidx].cx;
    370 +    m->canvas[tagidx].saved_cy = m->canvas[tagidx].cy;
    371 +
    372 +    for (c = m->clients; c; c = c->next) {
    373 +        if (ISVISIBLE(c)) {
    374 +            c->saved_cx = c->x + m->canvas[tagidx].cx;
    375 +            c->saved_cy = c->y + m->canvas[tagidx].cy;
    376 +            c->saved_cw = c->w;
    377 +            c->saved_ch = c->h;
    378 +            c->was_on_canvas = 1;
    379 +        }
    380 +    }
    381 +}
    382 +
    383 +void
    384 +restore_canvas_positions(Monitor *m) {
    385 +    Client *c;
    386 +    int tagidx = getcurrenttag(m);
    387 +
    388 +    m->canvas[tagidx].cx = m->canvas[tagidx].saved_cx;
    389 +    m->canvas[tagidx].cy = m->canvas[tagidx].saved_cy;
    390 +
    391 +    for (c = m->clients; c; c = c->next) {
    392 +        if (ISVISIBLE(c) && c->was_on_canvas) {
    393 +            c->isfloating = 1;
    394 +            
    395 +            int target_x = c->saved_cx - m->canvas[tagidx].cx;
    396 +            int target_y = c->saved_cy - m->canvas[tagidx].cy;
    397 +
    398 +            c->x = target_x;
    399 +            c->y = target_y;
    400 +            c->w = c->saved_cw;
    401 +            c->h = c->saved_ch;
    402 +
    403 +            XMoveResizeWindow(dpy, c->win, target_x, target_y, c->w, c->h);
    404 +
    405 +            configure(c);
    406 +        }
    407 +    }
    408 +    XSync(dpy, False);
    409 +}
    410 +
    411 +void
    412 +centerwindow(const Arg *arg)
    413 +{
    414 +    Client *c = (arg && arg->v) ? (Client *)arg->v : selmon->sel;
    415 +
    416 +    if (!c || !c->mon || c->mon->lt[c->mon->sellt]->arrange != NULL)
    417 +        return;
    418 +
    419 +    Monitor *m = c->mon;
    420 +    int tagidx = getcurrenttag(m);
    421 +
    422 +    int screen_center_x = m->wx + (m->ww / 2);
    423 +    int screen_center_y = m->wy + (m->wh / 2);
    424 +
    425 +    int win_center_x = c->x + (c->w + 2 * c->bw) / 2;
    426 +    int win_center_y = c->y + (c->h + 2 * c->bw) / 2;
    427 +
    428 +    int dx = screen_center_x - win_center_x;
    429 +    int dy = screen_center_y - win_center_y;
    430 +
    431 +    if (dx == 0 && dy == 0)
    432 +        return;
    433 +
    434 +    Client *tmp;
    435 +    for (tmp = m->clients; tmp; tmp = tmp->next) {
    436 +        if (ISVISIBLE(tmp)) {
    437 +            tmp->x += dx;
    438 +            tmp->y += dy;
    439 +            XMoveWindow(dpy, tmp->win, tmp->x, tmp->y);
    440 +        }
    441 +    }
    442 +
    443 +    m->canvas[tagidx].cx += dx;
    444 +    m->canvas[tagidx].cy += dy;
    445 +
    446 +    drawbar(m);
    447 +}
    448 diff --git a/infinitetags.h b/infinitetags.h
    449 new file mode 100644
    450 index 0000000..adcb69e
    451 --- /dev/null
    452 +++ b/infinitetags.h
    453 @@ -0,0 +1,7 @@
    454 +static void movecanvas(const Arg *arg);
    455 +static void manuallymovecanvas(const Arg *arg);
    456 +static void homecanvas(const Arg *arg);
    457 +static int getcurrenttag(Monitor *m);
    458 +static void save_canvas_positions(Monitor *m);
    459 +static void restore_canvas_positions(Monitor *m);
    460 +static void centerwindow(const Arg *arg);