Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
4.8 KiB

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