removed ugly ban(), extended resize() that it only resets the size if necessary, added border_width commit to manage()
6e22ccf7
5 file(s) · +100 −93
| 158 | 158 | manage(Window w, XWindowAttributes *wa) { |
|
| 159 | 159 | Client *c, *t; |
|
| 160 | 160 | Window trans; |
|
| 161 | + | XWindowChanges wc; |
|
| 161 | 162 | ||
| 162 | 163 | c = emallocz(sizeof(Client)); |
|
| 163 | 164 | c->tags = emallocz(ntags * sizeof(Bool)); |
|
| 187 | 188 | StructureNotifyMask | PropertyChangeMask | EnterWindowMask); |
|
| 188 | 189 | XGetTransientForHint(dpy, c->win, &trans); |
|
| 189 | 190 | grabbuttons(c, False); |
|
| 191 | + | wc.border_width = c->border; |
|
| 192 | + | XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); |
|
| 190 | 193 | XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); |
|
| 194 | + | configure(c); /* propagates border_width, if size doesn't change */ |
|
| 191 | 195 | updatetitle(c); |
|
| 192 | 196 | t = getclient(trans); |
|
| 193 | 197 | settags(c, t); |
|
| 198 | 202 | c->next = clients; |
|
| 199 | 203 | c->snext = stack; |
|
| 200 | 204 | stack = clients = c; |
|
| 201 | - | ban(c); |
|
| 205 | + | c->isbanned = True; |
|
| 206 | + | XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
|
| 202 | 207 | XMapWindow(dpy, c->win); |
|
| 203 | 208 | setclientstate(c, NormalState); |
|
| 204 | 209 | if(isvisible(c)) |
|
| 207 | 212 | } |
|
| 208 | 213 | ||
| 209 | 214 | void |
|
| 210 | - | resize(Client *c, Bool sizehints) { |
|
| 215 | + | resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
|
| 211 | 216 | float actual, dx, dy, max, min; |
|
| 212 | 217 | XWindowChanges wc; |
|
| 213 | 218 | ||
| 214 | - | if(c->w <= 0 || c->h <= 0) |
|
| 219 | + | if(w <= 0 || h <= 0) |
|
| 215 | 220 | return; |
|
| 216 | 221 | if(sizehints) { |
|
| 217 | - | if(c->minw && c->w < c->minw) |
|
| 218 | - | c->w = c->minw; |
|
| 219 | - | if(c->minh && c->h < c->minh) |
|
| 220 | - | c->h = c->minh; |
|
| 221 | - | if(c->maxw && c->w > c->maxw) |
|
| 222 | - | c->w = c->maxw; |
|
| 223 | - | if(c->maxh && c->h > c->maxh) |
|
| 224 | - | c->h = c->maxh; |
|
| 222 | + | if(c->minw && w < c->minw) |
|
| 223 | + | w = c->minw; |
|
| 224 | + | if(c->minh && h < c->minh) |
|
| 225 | + | h = c->minh; |
|
| 226 | + | if(c->maxw && w > c->maxw) |
|
| 227 | + | w = c->maxw; |
|
| 228 | + | if(c->maxh && h > c->maxh) |
|
| 229 | + | h = c->maxh; |
|
| 225 | 230 | /* inspired by algorithm from fluxbox */ |
|
| 226 | - | if(c->minay > 0 && c->maxay && (c->h - c->baseh) > 0) { |
|
| 227 | - | dx = (float)(c->w - c->basew); |
|
| 228 | - | dy = (float)(c->h - c->baseh); |
|
| 231 | + | if(c->minay > 0 && c->maxay && (h - c->baseh) > 0) { |
|
| 232 | + | dx = (float)(w - c->basew); |
|
| 233 | + | dy = (float)(h - c->baseh); |
|
| 229 | 234 | min = (float)(c->minax) / (float)(c->minay); |
|
| 230 | 235 | max = (float)(c->maxax) / (float)(c->maxay); |
|
| 231 | 236 | actual = dx / dy; |
|
| 233 | 238 | if(actual < min) { |
|
| 234 | 239 | dy = (dx * min + dy) / (min * min + 1); |
|
| 235 | 240 | dx = dy * min; |
|
| 236 | - | c->w = (int)dx + c->basew; |
|
| 237 | - | c->h = (int)dy + c->baseh; |
|
| 241 | + | w = (int)dx + c->basew; |
|
| 242 | + | h = (int)dy + c->baseh; |
|
| 238 | 243 | } |
|
| 239 | 244 | else if(actual > max) { |
|
| 240 | 245 | dy = (dx * min + dy) / (max * max + 1); |
|
| 241 | 246 | dx = dy * min; |
|
| 242 | - | c->w = (int)dx + c->basew; |
|
| 243 | - | c->h = (int)dy + c->baseh; |
|
| 247 | + | w = (int)dx + c->basew; |
|
| 248 | + | h = (int)dy + c->baseh; |
|
| 244 | 249 | } |
|
| 245 | 250 | } |
|
| 246 | 251 | } |
|
| 247 | 252 | if(c->incw) |
|
| 248 | - | c->w -= (c->w - c->basew) % c->incw; |
|
| 253 | + | w -= (w - c->basew) % c->incw; |
|
| 249 | 254 | if(c->inch) |
|
| 250 | - | c->h -= (c->h - c->baseh) % c->inch; |
|
| 255 | + | h -= (h - c->baseh) % c->inch; |
|
| 251 | 256 | } |
|
| 252 | - | if(c->w == sw && c->h == sh) |
|
| 257 | + | if(w == sw && h == sh) |
|
| 253 | 258 | c->border = 0; |
|
| 254 | 259 | else |
|
| 255 | 260 | c->border = BORDERPX; |
|
| 256 | 261 | /* offscreen appearance fixes */ |
|
| 257 | - | if(c->x > sw) |
|
| 258 | - | c->x = sw - c->w - 2 * c->border; |
|
| 259 | - | if(c->y > sh) |
|
| 260 | - | c->y = sh - c->h - 2 * c->border; |
|
| 261 | - | if(c->x + c->w + 2 * c->border < sx) |
|
| 262 | - | c->x = sx; |
|
| 263 | - | if(c->y + c->h + 2 * c->border < sy) |
|
| 264 | - | c->y = sy; |
|
| 265 | - | wc.x = c->x; |
|
| 266 | - | wc.y = c->y; |
|
| 267 | - | wc.width = c->w; |
|
| 268 | - | wc.height = c->h; |
|
| 269 | - | wc.border_width = c->border; |
|
| 270 | - | XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); |
|
| 271 | - | configure(c); |
|
| 272 | - | XSync(dpy, False); |
|
| 262 | + | if(x > sw) |
|
| 263 | + | x = sw - w - 2 * c->border; |
|
| 264 | + | if(y > sh) |
|
| 265 | + | y = sh - h - 2 * c->border; |
|
| 266 | + | if(x + w + 2 * c->border < sx) |
|
| 267 | + | x = sx; |
|
| 268 | + | if(y + h + 2 * c->border < sy) |
|
| 269 | + | y = sy; |
|
| 270 | + | if(c->x != x || c->y != y || c->w != w || c->h != h) { |
|
| 271 | + | c->x = wc.x = x; |
|
| 272 | + | c->y = wc.y = y; |
|
| 273 | + | c->w = wc.width = w; |
|
| 274 | + | c->h = wc.height = h; |
|
| 275 | + | wc.border_width = c->border; |
|
| 276 | + | XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); |
|
| 277 | + | configure(c); |
|
| 278 | + | XSync(dpy, False); |
|
| 279 | + | } |
|
| 273 | 280 | } |
|
| 274 | 281 | ||
| 275 | 282 | void |
|
| 99 | 99 | extern Window root, barwin; |
|
| 100 | 100 | ||
| 101 | 101 | /* client.c */ |
|
| 102 | - | extern void ban(Client *c); /* ban c */ |
|
| 103 | 102 | extern void configure(Client *c); /* send synthetic configure event */ |
|
| 104 | 103 | extern void focus(Client *c); /* focus c, c may be NULL */ |
|
| 105 | 104 | extern Client *getclient(Window w); /* return client of w */ |
|
| 106 | 105 | extern Bool isprotodel(Client *c); /* returns True if c->win supports wmatom[WMDelete] */ |
|
| 107 | 106 | extern void killclient(Arg *arg); /* kill c nicely */ |
|
| 108 | 107 | extern void manage(Window w, XWindowAttributes *wa); /* manage new client */ |
|
| 109 | - | extern void resize(Client *c, Bool sizehints); /* resize c*/ |
|
| 108 | + | extern void resize(Client *c, int x, int y, |
|
| 109 | + | int w, int h, Bool sizehints); /* resize c*/ |
|
| 110 | 110 | extern void updatesizehints(Client *c); /* update the size hint variables of c */ |
|
| 111 | 111 | extern void updatetitle(Client *c); /* update the name of c */ |
|
| 112 | 112 | extern void unmanage(Client *c); /* destroy c */ |
| 22 | 22 | ||
| 23 | 23 | static void |
|
| 24 | 24 | movemouse(Client *c) { |
|
| 25 | - | int x1, y1, ocx, ocy, di; |
|
| 25 | + | int x1, y1, ocx, ocy, di, nx, ny; |
|
| 26 | 26 | unsigned int dui; |
|
| 27 | 27 | Window dummy; |
|
| 28 | 28 | XEvent ev; |
|
| 29 | 29 | ||
| 30 | - | ocx = c->x; |
|
| 31 | - | ocy = c->y; |
|
| 30 | + | ocx = nx = c->x; |
|
| 31 | + | ocy = ny = c->y; |
|
| 32 | 32 | if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
|
| 33 | 33 | None, cursor[CurMove], CurrentTime) != GrabSuccess) |
|
| 34 | 34 | return; |
|
| 38 | 38 | XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev); |
|
| 39 | 39 | switch (ev.type) { |
|
| 40 | 40 | case ButtonRelease: |
|
| 41 | - | resize(c, True); |
|
| 42 | 41 | XUngrabPointer(dpy, CurrentTime); |
|
| 43 | 42 | return; |
|
| 44 | 43 | case ConfigureRequest: |
|
| 48 | 47 | break; |
|
| 49 | 48 | case MotionNotify: |
|
| 50 | 49 | XSync(dpy, False); |
|
| 51 | - | c->x = ocx + (ev.xmotion.x - x1); |
|
| 52 | - | c->y = ocy + (ev.xmotion.y - y1); |
|
| 53 | - | if(abs(wax + c->x) < SNAP) |
|
| 54 | - | c->x = wax; |
|
| 55 | - | else if(abs((wax + waw) - (c->x + c->w + 2 * c->border)) < SNAP) |
|
| 56 | - | c->x = wax + waw - c->w - 2 * c->border; |
|
| 57 | - | if(abs(way - c->y) < SNAP) |
|
| 58 | - | c->y = way; |
|
| 59 | - | else if(abs((way + wah) - (c->y + c->h + 2 * c->border)) < SNAP) |
|
| 60 | - | c->y = way + wah - c->h - 2 * c->border; |
|
| 61 | - | resize(c, False); |
|
| 50 | + | nx = ocx + (ev.xmotion.x - x1); |
|
| 51 | + | ny = ocy + (ev.xmotion.y - y1); |
|
| 52 | + | if(abs(wax + nx) < SNAP) |
|
| 53 | + | nx = wax; |
|
| 54 | + | else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP) |
|
| 55 | + | nx = wax + waw - c->w - 2 * c->border; |
|
| 56 | + | if(abs(way - ny) < SNAP) |
|
| 57 | + | ny = way; |
|
| 58 | + | else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP) |
|
| 59 | + | ny = way + wah - c->h - 2 * c->border; |
|
| 60 | + | resize(c, nx, ny, c->w, c->h, False); |
|
| 62 | 61 | break; |
|
| 63 | 62 | } |
|
| 64 | 63 | } |
|
| 81 | 80 | XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev); |
|
| 82 | 81 | switch(ev.type) { |
|
| 83 | 82 | case ButtonRelease: |
|
| 84 | - | resize(c, True); |
|
| 85 | 83 | XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, |
|
| 86 | 84 | c->w + c->border - 1, c->h + c->border - 1); |
|
| 87 | 85 | XUngrabPointer(dpy, CurrentTime); |
|
| 94 | 92 | break; |
|
| 95 | 93 | case MotionNotify: |
|
| 96 | 94 | XSync(dpy, False); |
|
| 97 | - | nw = ev.xmotion.x - ocx - 2 * c->border + 1; |
|
| 98 | - | c->w = nw > 0 ? nw : 1; |
|
| 99 | - | nh = ev.xmotion.y - ocy - 2 * c->border + 1; |
|
| 100 | - | c->h = nh > 0 ? nh : 1; |
|
| 101 | - | resize(c, True); |
|
| 95 | + | if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0) |
|
| 96 | + | nw = 1; |
|
| 97 | + | if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0) |
|
| 98 | + | nh = 1; |
|
| 99 | + | resize(c, c->x, c->y, nw, nh, True); |
|
| 102 | 100 | break; |
|
| 103 | 101 | } |
|
| 104 | 102 | } |
|
| 187 | 185 | if((ev->value_mask & (CWX | CWY)) |
|
| 188 | 186 | && !(ev->value_mask & (CWWidth | CWHeight))) |
|
| 189 | 187 | configure(c); |
|
| 190 | - | resize(c, False); |
|
| 188 | + | resize(c, c->x, c->y, c->w, c->h, False); |
|
| 191 | 189 | if(!isvisible(c)) |
|
| 192 | 190 | ban(c); |
|
| 193 | 191 | } |
|
| 41 | 41 | cleanup(void) { |
|
| 42 | 42 | close(STDIN_FILENO); |
|
| 43 | 43 | while(stack) { |
|
| 44 | - | resize(stack, True); |
|
| 44 | + | if(stack->isbanned) |
|
| 45 | + | XMoveWindow(dpy, stack->win, stack->x, stack->y); |
|
| 45 | 46 | unmanage(stack); |
|
| 46 | 47 | } |
|
| 47 | 48 | if(dc.font.set) |
| 20 | 20 | return; |
|
| 21 | 21 | ||
| 22 | 22 | if((c->ismax = !c->ismax)) { |
|
| 23 | - | c->rx = c->x; c->x = wax; |
|
| 24 | - | c->ry = c->y; c->y = way; |
|
| 25 | - | c->rw = c->w; c->w = waw - 2 * BORDERPX; |
|
| 26 | - | c->rh = c->h; c->h = wah - 2 * BORDERPX; |
|
| 27 | - | } |
|
| 28 | - | else { |
|
| 29 | - | c->x = c->rx; |
|
| 30 | - | c->y = c->ry; |
|
| 31 | - | c->w = c->rw; |
|
| 32 | - | c->h = c->rh; |
|
| 23 | + | c->rx = c->x; |
|
| 24 | + | c->ry = c->y; |
|
| 25 | + | c->rw = c->w; |
|
| 26 | + | c->rh = c->h; |
|
| 27 | + | resize(c, wax, way, waw - 2 * BORDERPX, wah - 2 * BORDERPX, True); |
|
| 33 | 28 | } |
|
| 34 | - | resize(c, True); |
|
| 29 | + | else |
|
| 30 | + | resize(c, c->rx, c->ry, c->rw, c->rh, True); |
|
| 35 | 31 | while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
|
| 36 | 32 | } |
|
| 37 | 33 | ||
| 56 | 52 | ||
| 57 | 53 | for(c = clients; c; c = c->next) { |
|
| 58 | 54 | if(isvisible(c)) { |
|
| 55 | + | if(c->isbanned) |
|
| 56 | + | XMoveWindow(dpy, c->win, c->x, c->y); |
|
| 59 | 57 | c->isbanned = False; |
|
| 60 | - | resize(c, True); |
|
| 61 | 58 | } |
|
| 62 | - | else |
|
| 63 | - | ban(c); |
|
| 59 | + | else { |
|
| 60 | + | c->isbanned = True; |
|
| 61 | + | XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
|
| 62 | + | } |
|
| 64 | 63 | } |
|
| 65 | 64 | if(!sel || !isvisible(sel)) { |
|
| 66 | 65 | for(c = stack; c && !isvisible(c); c = c->snext); |
|
| 71 | 70 | ||
| 72 | 71 | void |
|
| 73 | 72 | dotile(void) { |
|
| 74 | - | unsigned int i, n, mw, mh, tw, th; |
|
| 73 | + | unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th; |
|
| 75 | 74 | Client *c; |
|
| 76 | 75 | ||
| 77 | 76 | for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) |
|
| 84 | 83 | ||
| 85 | 84 | for(i = 0, c = clients; c; c = c->next) |
|
| 86 | 85 | if(isvisible(c)) { |
|
| 86 | + | if(c->isbanned) |
|
| 87 | + | XMoveWindow(dpy, c->win, c->x, c->y); |
|
| 87 | 88 | c->isbanned = False; |
|
| 88 | - | if(c->isfloat) { |
|
| 89 | - | resize(c, True); |
|
| 89 | + | if(c->isfloat) |
|
| 90 | 90 | continue; |
|
| 91 | - | } |
|
| 92 | 91 | c->ismax = False; |
|
| 93 | - | c->x = wax; |
|
| 94 | - | c->y = way; |
|
| 92 | + | nx = wax; |
|
| 93 | + | ny = way; |
|
| 95 | 94 | if(i < nmaster) { |
|
| 96 | - | c->y += i * mh; |
|
| 97 | - | c->w = mw - 2 * BORDERPX; |
|
| 98 | - | c->h = mh - 2 * BORDERPX; |
|
| 95 | + | ny += i * mh; |
|
| 96 | + | nw = mw - 2 * BORDERPX; |
|
| 97 | + | nh = mh - 2 * BORDERPX; |
|
| 99 | 98 | } |
|
| 100 | 99 | else { /* tile window */ |
|
| 101 | - | c->x += mw; |
|
| 102 | - | c->w = tw - 2 * BORDERPX; |
|
| 100 | + | nx += mw; |
|
| 101 | + | nw = tw - 2 * BORDERPX; |
|
| 103 | 102 | if(th > 2 * BORDERPX) { |
|
| 104 | - | c->y += (i - nmaster) * th; |
|
| 105 | - | c->h = th - 2 * BORDERPX; |
|
| 103 | + | ny += (i - nmaster) * th; |
|
| 104 | + | nh = th - 2 * BORDERPX; |
|
| 106 | 105 | } |
|
| 107 | 106 | else /* fallback if th <= 2 * BORDERPX */ |
|
| 108 | - | c->h = wah - 2 * BORDERPX; |
|
| 107 | + | nh = wah - 2 * BORDERPX; |
|
| 109 | 108 | } |
|
| 110 | - | resize(c, False); |
|
| 109 | + | resize(c, nx, ny, nw, nh, False); |
|
| 111 | 110 | i++; |
|
| 112 | 111 | } |
|
| 113 | - | else |
|
| 114 | - | ban(c); |
|
| 112 | + | else { |
|
| 113 | + | c->isbanned = True; |
|
| 114 | + | XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
|
| 115 | + | } |
|
| 115 | 116 | if(!sel || !isvisible(sel)) { |
|
| 116 | 117 | for(c = stack; c && !isvisible(c); c = c->snext); |
|
| 117 | 118 | focus(c); |
|