screen.c (4449B)
1 /* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> 2 * See LICENSE file for license details. 3 */ 4 #include "dat.h" 5 #include <math.h> 6 #include "fns.h" 7 8 #ifdef notdef 9 void 10 mapscreens(void) { 11 WMScreen *s, *ss; 12 Rectangle r; 13 int i, j; 14 15 #define frob(left, min, max, x, y) \ 16 if(Dy(r) > 0) /* If they intersect at some point on this axis */ \ 17 if(ss->r.min.x < s->r.min.x) { \ 18 if((!s->left) \ 19 || (abs(Dy(r)) < abs(s->left.max.x - s->min.x))) \ 20 s->left = ss; \ 21 } 22 23 /* Variable hell? Certainly. */ 24 for(i=0; i < nscreens; i++) { 25 s = screens[i]; 26 for(j=0; j < nscreens; j++) { 27 if(i == j) 28 continue; 29 ss = screens[j]; 30 r = rect_intersection(ss->r, s->r); 31 frob(left, min, max, x, y); 32 frob(right, max, min, x, y); 33 frob(atop, min, max, y, x); 34 frob(below, max, min, y, x); 35 } 36 } 37 #undef frob 38 } 39 40 int findscreen(Rectangle, int); 41 int 42 findscreen(Rectangle rect, int direction) { 43 Rectangle r; 44 WMScreen *ss, *s; 45 int best, i, j; 46 47 best = -1; 48 #define frob(min, max, x, y) 49 if(Dy(r) > 0) /* If they intersect at some point on this axis */ 50 if(ss->r.min.x < rect.min.x) { 51 if(best == -1 52 || (abs(ss->r.max.x - rect.min.x) < abs(screens[best]->r.max.x - rect.min.x))) 53 best = s->idx; 54 } 55 56 /* Variable hell? Certainly. */ 57 for(i=0; i < nscreens; i++) { 58 ss = screens[j]; 59 r = rect_intersection(ss->r, rect); 60 switch(direction) { 61 default: 62 return -1; 63 case West: 64 frob(min, max, x, y); 65 break; 66 case East: 67 frob(max, min, x, y); 68 break; 69 case North: 70 frob(min, max, y, x); 71 break; 72 case South: 73 frob(max, min, y, x); 74 break; 75 } 76 } 77 #undef frob 78 } 79 #endif 80 81 static Rectangle 82 leastthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*)) { 83 Rectangle r; 84 int i, best, d; 85 86 SET(d); 87 SET(best); 88 for(i=0; i < vec->n; i++) { 89 r = key(vec->ary[i]); 90 switch(direction) { 91 case South: d = r.min.y; break; 92 case North: d = -r.max.y; break; 93 case East: d = r.min.x; break; 94 case West: d = -r.max.x; break; 95 } 96 if(i == 0 || d < best) 97 best = d; 98 } 99 switch(direction) { 100 case South: rect.min.y = rect.max.y = best; break; 101 case North: rect.min.y = rect.max.y = -best; break; 102 case East: rect.min.x = rect.max.x = best; break; 103 case West: rect.min.x = rect.max.x = -best; break; 104 } 105 return rect; 106 } 107 108 void* 109 findthing(Rectangle rect, int direction, Vector_ptr *vec, Rectangle (*key)(void*), bool wrap) { 110 Rectangle isect; 111 Rectangle r, bestisect = {0,}, bestr = {0,}; 112 void *best, *p; 113 int i, n; 114 115 best = nil; 116 117 /* For the record, I really hate these macros. */ 118 #define frob(min, max, LT, x, y) \ 119 if(D##y(isect) > 0) /* If they intersect at some point on this axis */ \ 120 if(r.min.x LT rect.min.x) { \ 121 n = abs(r.max.x - rect.min.x) - abs(bestr.max.x - rect.min.x); \ 122 if(best == nil \ 123 || n == 0 && D##y(isect) > D##y(bestisect) \ 124 || n < 0 \ 125 ) { \ 126 best = p; \ 127 bestr = r; \ 128 bestisect = isect; \ 129 } \ 130 } 131 132 /* Variable hell? Certainly. */ 133 for(i=0; i < vec->n; i++) { 134 p = vec->ary[i]; 135 r = key(p); 136 isect = rect_intersection(rect, r); 137 switch(direction) { 138 default: 139 die("not reached"); 140 /* Not reached */ 141 case West: 142 frob(min, max, <, x, y); 143 break; 144 case East: 145 frob(max, min, >, x, y); 146 break; 147 case North: 148 frob(min, max, <, y, x); 149 break; 150 case South: 151 frob(max, min, >, y, x); 152 break; 153 } 154 } 155 #undef frob 156 if(!best && wrap) { 157 r = leastthing(rect, direction, vec, key); 158 return findthing(r, direction, vec, key, false); 159 } 160 return best; 161 } 162 163 static int 164 area(Rectangle r) { 165 return Dx(r) * Dy(r) * 166 (Dx(r) < 0 && Dy(r) < 0 ? -1 : 1); 167 } 168 169 int 170 ownerscreen(Rectangle r) { 171 Rectangle isect; 172 int s, a, best, besta; 173 174 SET(besta); 175 best = -1; 176 for(s=0; s < nscreens; s++) { 177 if(!screens[s]->showing) 178 continue; 179 isect = rect_intersection(r, screens[s]->r); 180 a = area(isect); 181 if(best < 0 || a > besta) { 182 besta = a; 183 best = s; 184 } 185 } 186 return best; 187 } 188