dwm-exresize-r1606.diff (12751B)
1 diff --git a/config.def.h b/config.def.h 2 index 7fb4d82..959a119 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -88,6 +88,33 @@ static Key keys[] = { 6 TAGKEYS( XK_8, 7) 7 TAGKEYS( XK_9, 8) 8 { MODKEY|ShiftMask, XK_q, quit, {0} }, 9 + 10 + { MODKEY, XK_KP_7, explace, {.ui = EX_NW }}, 11 + { MODKEY, XK_KP_8, explace, {.ui = EX_N }}, 12 + { MODKEY, XK_KP_9, explace, {.ui = EX_NE }}, 13 + { MODKEY, XK_KP_4, explace, {.ui = EX_W }}, 14 + { MODKEY, XK_KP_5, explace, {.ui = EX_C }}, 15 + { MODKEY, XK_KP_6, explace, {.ui = EX_E }}, 16 + { MODKEY, XK_KP_1, explace, {.ui = EX_SW }}, 17 + { MODKEY, XK_KP_2, explace, {.ui = EX_S }}, 18 + { MODKEY, XK_KP_3, explace, {.ui = EX_SE }}, 19 + 20 + { MODKEY|ShiftMask, XK_KP_8, exresize, {.v = (int []){ 0, 25 }}}, 21 + { MODKEY|ShiftMask, XK_KP_2, exresize, {.v = (int []){ 0, -25 }}}, 22 + { MODKEY|ShiftMask, XK_KP_6, exresize, {.v = (int []){ 25, 0 }}}, 23 + { MODKEY|ShiftMask, XK_KP_4, exresize, {.v = (int []){ -25, 0 }}}, 24 + { MODKEY|ShiftMask, XK_KP_5, exresize, {.v = (int []){ 25, 25 }}}, 25 + { MODKEY|ShiftMask|ControlMask, XK_KP_5, exresize, {.v = (int []){ -25, -25 }}}, 26 + 27 + { MODKEY|ControlMask, XK_KP_6, togglehorizontalexpand, {.i = +1} }, 28 + { MODKEY|ControlMask, XK_KP_3, togglehorizontalexpand, {.i = 0} }, 29 + { MODKEY|ControlMask, XK_KP_4, togglehorizontalexpand, {.i = -1} }, 30 + { MODKEY|ControlMask, XK_KP_8, toggleverticalexpand, {.i = +1} }, 31 + { MODKEY|ControlMask, XK_KP_1, toggleverticalexpand, {.i = 0} }, 32 + { MODKEY|ControlMask, XK_KP_2, toggleverticalexpand, {.i = -1} }, 33 + { MODKEY|ControlMask, XK_KP_9, togglemaximize, {.i = -1} }, 34 + { MODKEY|ControlMask, XK_KP_7, togglemaximize, {.i = +1} }, 35 + { MODKEY|ControlMask, XK_KP_5, togglemaximize, {.i = 0} }, 36 }; 37 38 /* button definitions */ 39 diff --git a/dwm.c b/dwm.c 40 index 4986b07..8fc0c57 100644 41 --- a/dwm.c 42 +++ b/dwm.c 43 @@ -89,11 +89,14 @@ struct Client { 44 char name[256]; 45 float mina, maxa; 46 int x, y, w, h; 47 + int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ 48 int oldx, oldy, oldw, oldh; 49 int basew, baseh, incw, inch, maxw, maxh, minw, minh; 50 int bw, oldbw; 51 unsigned int tags; 52 - Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; 53 + unsigned char expandmask; 54 + int expandx1, expandy1, expandx2, expandy2; 55 + Bool wasfloating, isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; 56 Client *next; 57 Client *snext; 58 Monitor *mon; 59 @@ -1132,8 +1135,14 @@ manage(Window w, XWindowAttributes *wa) { 60 updatewindowtype(c); 61 updatesizehints(c); 62 updatewmhints(c); 63 + c->sfx = c->x; 64 + c->sfy = c->y; 65 + c->sfw = c->w; 66 + c->sfh = c->h; 67 XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); 68 grabbuttons(c, False); 69 + c->wasfloating = False; 70 + c->expandmask = 0; 71 if(!c->isfloating) 72 c->isfloating = c->oldstate = trans != None || c->isfixed; 73 if(c->isfloating) 74 @@ -1234,8 +1243,9 @@ movemouse(const Arg *arg) { 75 case MotionNotify: 76 nx = ocx + (ev.xmotion.x - x); 77 ny = ocy + (ev.xmotion.y - y); 78 - if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww 79 - && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) { 80 + if ((m = recttomon(nx, ny, c->w, c->h))) { 81 + if (m != selmon) 82 + sendmon(c, m); 83 if(abs(selmon->wx - nx) < snap) 84 nx = selmon->wx; 85 else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) 86 @@ -1343,6 +1353,7 @@ resizeclient(Client *c, int x, int y, int w, int h) { 87 c->oldy = c->y; c->y = wc.y = y; 88 c->oldw = c->w; c->w = wc.width = w; 89 c->oldh = c->h; c->h = wc.height = h; 90 + c->expandmask = 0; 91 wc.border_width = c->bw; 92 XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); 93 configure(c); 94 @@ -1379,9 +1390,9 @@ resizemouse(const Arg *arg) { 95 case MotionNotify: 96 nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); 97 nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); 98 - if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww 99 - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) 100 - { 101 + if ((m = recttomon(c->x, c->y, nw, nh))) { 102 + if (m != selmon) 103 + sendmon(c, m); 104 if(!c->isfloating && selmon->lt[selmon->sellt]->arrange 105 && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) 106 togglefloating(NULL); 107 @@ -1463,6 +1474,7 @@ scan(void) { 108 109 void 110 sendmon(Client *c, Monitor *m) { 111 + Monitor *oldm = selmon; 112 if(c->mon == m) 113 return; 114 unfocus(c, True); 115 @@ -1472,8 +1484,11 @@ sendmon(Client *c, Monitor *m) { 116 c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ 117 attach(c); 118 attachstack(c); 119 - focus(NULL); 120 - arrange(NULL); 121 + if (oldm != m) 122 + arrange(oldm); 123 + arrange(m); 124 + focus(c); 125 + restack(m); 126 } 127 128 void 129 @@ -1549,8 +1564,18 @@ setfullscreen(Client *c, Bool fullscreen) { 130 131 void 132 setlayout(const Arg *arg) { 133 - if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) 134 + if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { 135 selmon->sellt ^= 1; 136 + if (!selmon->lt[selmon->sellt]->arrange) { 137 + for (Client *c = selmon->clients ; c ; c = c->next) { 138 + if(!c->isfloating) { 139 + /*restore last known float dimensions*/ 140 + resize(c, selmon->mx + c->sfx, selmon->my + c->sfy, 141 + c->sfw, c->sfh, False); 142 + } 143 + } 144 + } 145 + } 146 if(arg && arg->v) 147 selmon->lt[selmon->sellt] = (Layout *)arg->v; 148 strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); 149 @@ -1732,9 +1757,19 @@ togglefloating(const Arg *arg) { 150 if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ 151 return; 152 selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; 153 - if(selmon->sel->isfloating) 154 - resize(selmon->sel, selmon->sel->x, selmon->sel->y, 155 - selmon->sel->w, selmon->sel->h, False); 156 + if(selmon->sel->isfloating) { 157 + /*restore last known float dimensions*/ 158 + resize(selmon->sel, selmon->mx + selmon->sel->sfx, selmon->my + selmon->sel->sfy, 159 + selmon->sel->sfw, selmon->sel->sfh, False); 160 + } else { 161 + if (selmon->sel->isfullscreen) 162 + setfullscreen(selmon->sel, False); 163 + /*save last known float dimensions*/ 164 + selmon->sel->sfx = selmon->sel->x - selmon->mx; 165 + selmon->sel->sfy = selmon->sel->y - selmon->my; 166 + selmon->sel->sfw = selmon->sel->w; 167 + selmon->sel->sfh = selmon->sel->h; 168 + } 169 arrange(selmon); 170 } 171 172 diff --git a/exresize.c b/exresize.c 173 new file mode 100644 174 index 0000000..2343ffe 175 --- /dev/null 176 +++ b/exresize.c 177 @@ -0,0 +1,195 @@ 178 +#define EXPAND_LEFT (1 << 0) 179 +#define EXPAND_RIGHT (1 << 2) 180 +#define EXPAND_UP (1 << 4) 181 +#define EXPAND_DOWN (1 << 6) 182 + 183 +#define IS_SET(q, w) ((q & w) != 0) 184 +#define IS_FORCED(q, w) IS_SET((q << 1), w) 185 + 186 +#define EXPANDALL (EXPAND_LEFT | EXPAND_RIGHT | EXPAND_UP | EXPAND_DOWN) 187 +#define UNEXPAND (EXPANDALL << 1) // Force all directions to 0 188 +#define FORCE_EXPANDALL ~0 // Force expand in all directions 189 + 190 +enum { EX_NW, EX_N, EX_NE, EX_W, EX_C, EX_E, EX_SW, EX_S, EX_SE }; 191 + 192 +void expand(unsigned char mask); 193 + 194 +void togglemaximize(const Arg *arg); 195 +void toggleverticalexpand(const Arg *arg); 196 +void togglehorizontalexpand(const Arg *arg); 197 +void exresize(const Arg *arg); 198 +void explace(const Arg *arg); 199 + 200 +void 201 +exresize(const Arg *arg) { 202 + Client *c; 203 + int x, y, nx, ny, nw, nh; 204 + c = selmon->sel; 205 + 206 + if (!c || !arg) return; 207 + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) 208 + togglefloating(NULL); 209 + if (c->expandmask != 0) 210 + expand(UNEXPAND); 211 + 212 + x = ((int *)arg->v)[0]; 213 + y = ((int *)arg->v)[1]; 214 + 215 + nw = MIN(selmon->ww - c->bw*2, c->w + x); 216 + nh = MIN(selmon->wh - c->bw*2, c->h + y); 217 + nx = c->x - x/2; 218 + ny = c->y - y/2; 219 + 220 + if (!((abs(c->x + c->w/2 - (selmon->wx + selmon->ww/2)) < snap))) { 221 + if ((nw == selmon->ww) || 222 + (nx < selmon->wx) || 223 + (abs(selmon->wx - c->x) < snap)) 224 + nx = selmon->wx; 225 + else if ((nx+nw > (selmon->wx + selmon->ww)) || 226 + (abs((selmon->wx + selmon->ww) - (c->x + c->w)) < snap)) 227 + nx = (selmon->wx + selmon->ww) - nw - c->bw*2; 228 + } else 229 + nx = selmon->wx + selmon->ww/2 - nw/2; 230 + 231 + if (!((abs(c->y + c->h/2 - (selmon->wy + selmon->wh/2)) < snap))) { 232 + 233 + if ((nh == selmon->wh) || 234 + (ny < selmon->wy) || 235 + (abs(selmon->wy - c->y) < snap)) 236 + ny = selmon->wy; 237 + else if ((ny+nh > (selmon->wy + selmon->wh)) || 238 + (abs((selmon->wy + selmon->wh) - (c->y + c->h)) < snap)) 239 + ny = (selmon->wy + selmon->wh) - nh - c->bw*2; 240 + } else 241 + ny = selmon->wy + selmon->wh/2 - nh/2; 242 + 243 + 244 + resizeclient(c, nx, ny, MAX(nw, 32), MAX(nh, 32)); 245 + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); 246 +} 247 + 248 +void 249 +explace(const Arg *arg) { 250 + Client *c; 251 + int nx, ny; 252 + 253 + c = selmon->sel; 254 + if (!c || (arg->ui >= 9)) return; 255 + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) 256 + togglefloating(NULL); 257 + 258 + nx = (arg->ui % 3) - 1; 259 + ny = (arg->ui / 3) - 1; 260 + 261 + if (nx < 0) nx = selmon->wx; 262 + else if (nx > 0) nx = selmon->wx + selmon->ww - c->w - c->bw*2; 263 + else nx = selmon->wx + selmon->ww/2 - c->w/2; 264 + 265 + if (ny < 0) ny = selmon->wy; 266 + else if (ny > 0) ny = selmon->wy + selmon->wh - c->h - c->bw*2; 267 + else ny = selmon->wy + selmon->wh/2 - c->h/2; 268 + 269 + resize(c, nx, ny, c->w, c->h, True); 270 + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); 271 +} 272 + 273 +int 274 +calculate_expand(unsigned char mask, unsigned char curmask, 275 + unsigned char *newmask, unsigned char key, 276 + int *reset_value, int new_reset_value, 277 + int max_value, int old_value) { 278 + if (IS_SET(key, mask) || 279 + (IS_SET(key, curmask) && (!IS_SET(key, mask) && IS_FORCED(key, mask))) || 280 + (!IS_SET(key, curmask) && (IS_SET(key, mask) && IS_FORCED(key, mask)))) { 281 + 282 + if (IS_SET(key, mask) && (!IS_SET(key,curmask) || IS_FORCED(key,mask))) 283 + { 284 + if (!IS_SET(key, curmask)) 285 + *reset_value = new_reset_value; 286 + *newmask |= key; 287 + return max_value; 288 + } else if ((IS_SET(key,curmask) && IS_SET(key, mask)) || 289 + (!IS_SET(key, mask) && IS_FORCED(key, mask))) { 290 + *newmask &= ~key; 291 + return *reset_value; 292 + } else { 293 + *newmask &= ~key; 294 + return old_value; 295 + } 296 + } else 297 + return new_reset_value; 298 +} 299 + 300 +void 301 +expand(unsigned char mask) { 302 + XEvent ev; 303 + int nx1, ny1, nx2, ny2; 304 + unsigned char curmask; 305 + unsigned char newmask; 306 + 307 + if(!selmon->sel || selmon->sel->isfixed) 308 + return; 309 + XRaiseWindow(dpy, selmon->sel->win); 310 + newmask = curmask = selmon->sel->expandmask; 311 + 312 + if (curmask == 0) { 313 + if(!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating) 314 + selmon->sel->wasfloating = True; 315 + else { 316 + togglefloating(NULL); 317 + selmon->sel->wasfloating = False; 318 + } 319 + } 320 + 321 + nx1 = calculate_expand(mask, curmask, &newmask, 322 + EXPAND_LEFT, &selmon->sel->expandx1, 323 + selmon->sel->x, 324 + selmon->wx, 325 + selmon->sel->oldx); 326 + nx2 = calculate_expand(mask, curmask, &newmask, 327 + EXPAND_RIGHT, &selmon->sel->expandx2, 328 + selmon->sel->x + selmon->sel->w, 329 + selmon->wx + selmon->ww - 2*borderpx, 330 + selmon->sel->oldw + selmon->sel->x); 331 + ny1 = calculate_expand(mask, curmask, &newmask, 332 + EXPAND_UP, &selmon->sel->expandy1, 333 + selmon->sel->y, 334 + selmon->wy, 335 + selmon->sel->oldy); 336 + ny2 = calculate_expand(mask, curmask, &newmask, 337 + EXPAND_DOWN, &selmon->sel->expandy2, 338 + selmon->sel->y + selmon->sel->h, 339 + selmon->wy + selmon->wh - 2*borderpx, 340 + selmon->sel->oldh + selmon->sel->y); 341 + 342 + 343 + resizeclient(selmon->sel, nx1, ny1, MAX(nx2-nx1, 32), MAX(ny2-ny1, 32)); 344 + 345 + if ((newmask == 0) && (!selmon->sel->wasfloating)) 346 + togglefloating(NULL); 347 + selmon->sel->expandmask = newmask; 348 + drawbar(selmon); 349 + while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); 350 +} 351 + 352 +void 353 +togglemaximize(const Arg *arg) { 354 + if (arg->i > 0) expand(FORCE_EXPANDALL); 355 + else if (arg->i < 0) expand(UNEXPAND); 356 + else expand(EXPANDALL); 357 +} 358 + 359 +void 360 +toggleverticalexpand(const Arg *arg) { 361 + if (arg->i < 0) expand(EXPAND_DOWN); 362 + else if (arg->i > 0) expand(EXPAND_UP); 363 + else expand(EXPAND_DOWN | EXPAND_UP); 364 +} 365 + 366 +void 367 +togglehorizontalexpand(const Arg *arg) { 368 + if (arg->i < 0) expand(EXPAND_LEFT); 369 + else if (arg->i > 0) expand(EXPAND_RIGHT); 370 + else expand(EXPAND_LEFT | EXPAND_RIGHT); 371 +} 372 +