floatpos.c (4936B)
1 void 2 floatpos(const Arg *arg) 3 { 4 Client *c = selmon->sel; 5 6 if (!c || (selmon->lt[selmon->sellt]->arrange && !c->isfloating)) 7 return; 8 9 setfloatpos(c, (char *)arg->v); 10 resizeclient(c, c->x, c->y, c->w, c->h); 11 12 #if !FOCUSONCLICK_PATCH 13 XRaiseWindow(dpy, c->win); 14 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); 15 #endif // FOCUSONCLICK_PATCH 16 } 17 18 void 19 setfloatpos(Client *c, const char *floatpos) 20 { 21 char xCh, yCh, wCh, hCh; 22 int x, y, w, h, wx, ww, wy, wh; 23 #if FLOATPOS_RESPECT_GAPS_PATCH && VANITYGAPS_PATCH 24 int oh, ov, ih, iv; 25 unsigned int n; 26 #endif // FLOATPOS_RESPECT_GAPS_PATCH | VANITYGAPS_PATCH 27 28 if (!c || !floatpos) 29 return; 30 if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) 31 return; 32 33 switch(sscanf(floatpos, "%d%c %d%c %d%c %d%c", &x, &xCh, &y, &yCh, &w, &wCh, &h, &hCh)) { 34 case 4: 35 if (xCh == 'w' || xCh == 'W') { 36 w = x; wCh = xCh; 37 h = y; hCh = yCh; 38 x = -1; xCh = 'C'; 39 y = -1; yCh = 'C'; 40 } else if (xCh == 'p' || xCh == 'P') { 41 w = x; wCh = xCh; 42 h = y; hCh = yCh; 43 x = 0; xCh = 'G'; 44 y = 0; yCh = 'G'; 45 } else if (xCh == 'm' || xCh == 'M') { 46 getrootptr(&x, &y); 47 } else { 48 w = 0; wCh = 0; 49 h = 0; hCh = 0; 50 } 51 break; 52 case 8: 53 if (xCh == 'm' || xCh == 'M') 54 getrootptr(&x, &y); 55 break; 56 default: 57 return; 58 } 59 60 #if FLOATPOS_RESPECT_GAPS_PATCH && VANITYGAPS_PATCH 61 getgaps(c->mon, &oh, &ov, &ih, &iv, &n); 62 wx = c->mon->wx + ov; 63 wy = c->mon->wy + oh; 64 ww = c->mon->ww - 2*ov; 65 wh = c->mon->wh - 2*oh; 66 #else 67 wx = c->mon->wx; 68 wy = c->mon->wy; 69 ww = c->mon->ww; 70 wh = c->mon->wh; 71 #endif // FLOATPOS_RESPECT_GAPS_PATCH | VANITYGAPS_PATCH 72 73 getfloatpos(x, xCh, w, wCh, wx, ww, c->x, c->w, c->bw, floatposgrid_x, &c->x, &c->w); 74 getfloatpos(y, yCh, h, hCh, wy, wh, c->y, c->h, c->bw, floatposgrid_y, &c->y, &c->h); 75 } 76 77 /* p - position, s - size, cp and cs represents current position and size */ 78 void 79 getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s) 80 { 81 int abs_p, abs_s, i, delta, rest; 82 83 abs_p = pCh == 'A' || pCh == 'a'; 84 abs_s = sCh == 'A' || sCh == 'a'; 85 86 cs += 2*cbw; 87 88 switch(pCh) { 89 case 'A': // absolute position 90 cp = pos; 91 break; 92 case 'a': // absolute relative position 93 cp += pos; 94 break; 95 case 'y': 96 case 'x': // client relative position 97 cp = MIN(cp + pos, min_p + max_s); 98 break; 99 case 'Y': 100 case 'X': // client position relative to monitor 101 cp = min_p + MIN(pos, max_s); 102 break; 103 case 'S': // fixed client position (sticky) 104 case 'C': // fixed client position (center) 105 case 'Z': // fixed client right-hand position (position + size) 106 if (pos == -1) 107 break; 108 pos = MAX(MIN(pos, max_s), 0); 109 if (pCh == 'Z') 110 cs = abs((cp + cs) - (min_p + pos)); 111 else if (pCh == 'C') 112 cs = abs((cp + cs / 2) - (min_p + pos)); 113 else 114 cs = abs(cp - (min_p + pos)); 115 cp = min_p + pos; 116 sCh = 0; // size determined by position, override defined size 117 break; 118 case 'G': // grid 119 if (pos <= 0) 120 pos = defgrid; // default configurable 121 if (size == 0 || pos < 2 || (sCh != 'p' && sCh != 'P')) 122 break; 123 delta = (max_s - cs) / (pos - 1); 124 rest = max_s - cs - delta * (pos - 1); 125 if (sCh == 'P') { 126 if (size < 1 || size > pos) 127 break; 128 cp = min_p + delta * (size - 1); 129 } else { 130 for (i = 0; i < pos && cp >= min_p + delta * i + (i > pos - rest ? i + rest - pos + 1 : 0); i++); 131 cp = min_p + delta * (MAX(MIN(i + size, pos), 1) - 1) + (i > pos - rest ? i + rest - pos + 1 : 0); 132 } 133 break; 134 } 135 136 switch(sCh) { 137 case 'A': // absolute size 138 cs = size; 139 break; 140 case 'a': // absolute relative size 141 cs = MAX(1, cs + size); 142 break; 143 case '%': // client size percentage in relation to monitor window area size 144 if (size <= 0) 145 break; 146 size = max_s * MIN(size, 100) / 100; 147 /* falls through */ 148 case 'h': 149 case 'w': // size relative to client 150 if (sCh == 'w' || sCh == 'h') { 151 if (size == 0) 152 break; 153 size += cs; 154 } 155 /* falls through */ 156 case 'H': 157 case 'W': // normal size, position takes precedence 158 if (pCh == 'S' && cp + size > min_p + max_s) 159 size = min_p + max_s - cp; 160 else if (size > max_s) 161 size = max_s; 162 163 if (pCh == 'C') { // fixed client center, expand or contract client 164 delta = size - cs; 165 if (delta < 0 || (cp - delta / 2 + size <= min_p + max_s)) 166 cp -= delta / 2; 167 else if (cp - delta / 2 < min_p) 168 cp = min_p; 169 else if (delta) 170 cp = min_p + max_s; 171 } else if (pCh == 'Z') 172 cp -= size - cs; 173 174 cs = size; 175 break; 176 } 177 178 if (pCh == '%') // client mid-point position in relation to monitor window area size 179 cp = min_p + max_s * MAX(MIN(pos, 100), 0) / 100 - (cs) / 2; 180 if (pCh == 'm' || pCh == 'M') 181 cp = pos - cs / 2; 182 183 if (!abs_p && cp < min_p) 184 cp = min_p; 185 if (cp + cs > min_p + max_s && !(abs_p && abs_s)) { 186 if (abs_p || cp == min_p) 187 cs = min_p + max_s - cp; 188 else 189 cp = min_p + max_s - cs; 190 } 191 192 *out_p = cp; 193 *out_s = MAX(cs - 2*cbw, 1); 194 } 195