127 Bool isfloating; |
127 Bool isfloating; |
128 } Rule; |
128 } Rule; |
129 |
129 |
130 /* function declarations */ |
130 /* function declarations */ |
131 static void applyrules(Client *c); |
131 static void applyrules(Client *c); |
132 static void applysizehints(Client *c, int *w, int *h); |
132 static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h); |
133 static void arrange(void); |
133 static void arrange(void); |
134 static void attach(Client *c); |
134 static void attach(Client *c); |
135 static void attachstack(Client *c); |
135 static void attachstack(Client *c); |
136 static void buttonpress(XEvent *e); |
136 static void buttonpress(XEvent *e); |
137 static void checkotherwm(void); |
137 static void checkotherwm(void); |
250 unsigned int i; |
250 unsigned int i; |
251 Rule *r; |
251 Rule *r; |
252 XClassHint ch = { 0 }; |
252 XClassHint ch = { 0 }; |
253 |
253 |
254 /* rule matching */ |
254 /* rule matching */ |
|
255 c->isfloating = c->tags = 0; |
255 if(XGetClassHint(dpy, c->win, &ch)) { |
256 if(XGetClassHint(dpy, c->win, &ch)) { |
256 for(i = 0; i < LENGTH(rules); i++) { |
257 for(i = 0; i < LENGTH(rules); i++) { |
257 r = &rules[i]; |
258 r = &rules[i]; |
258 if((!r->title || strstr(c->name, r->title)) |
259 if((!r->title || strstr(c->name, r->title)) |
259 && (!r->class || (ch.res_class && strstr(ch.res_class, r->class))) |
260 && (!r->class || (ch.res_class && strstr(ch.res_class, r->class))) |
260 && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) { |
261 && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) { |
261 c->isfloating = r->isfloating; |
262 c->isfloating = r->isfloating; |
262 c->tags |= r->tags & TAGMASK ? r->tags & TAGMASK : tagset[seltags]; |
263 c->tags |= r->tags; |
263 } |
264 } |
264 } |
265 } |
265 if(ch.res_class) |
266 if(ch.res_class) |
266 XFree(ch.res_class); |
267 XFree(ch.res_class); |
267 if(ch.res_name) |
268 if(ch.res_name) |
268 XFree(ch.res_name); |
269 XFree(ch.res_name); |
269 } |
270 } |
270 if(!c->tags) |
271 c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : tagset[seltags]; |
271 c->tags = tagset[seltags]; |
272 } |
272 } |
273 |
273 |
274 Bool |
274 void |
275 applysizehints(Client *c, int *x, int *y, int *w, int *h) { |
275 applysizehints(Client *c, int *w, int *h) { |
|
276 Bool baseismin; |
276 Bool baseismin; |
277 |
|
278 if(!resizehints && !c->isfloating) |
|
279 return; |
|
280 |
|
281 /* see last two sentences in ICCCM 4.1.2.3 */ |
|
282 baseismin = c->basew == c->minw && c->baseh == c->minh; |
|
283 |
277 |
284 /* set minimum possible */ |
278 /* set minimum possible */ |
285 *w = MAX(1, *w); |
279 *w = MAX(1, *w); |
286 *h = MAX(1, *h); |
280 *h = MAX(1, *h); |
287 |
281 |
288 if(!baseismin) { /* temporarily remove base dimensions */ |
282 if(*x > sx + sw) |
289 *w -= c->basew; |
283 *x = sw - WIDTH(c); |
290 *h -= c->baseh; |
284 if(*y > sy + sh) |
291 } |
285 *y = sh - HEIGHT(c); |
292 |
286 if(*x + *w + 2 * c->bw < sx) |
293 /* adjust for aspect limits */ |
287 *x = sx; |
294 if(c->mina > 0 && c->maxa > 0) { |
288 if(*y + *h + 2 * c->bw < sy) |
295 if(c->maxa < (float)*w / *h) |
289 *y = sy; |
296 *w = *h * c->maxa; |
290 if(*h < bh) |
297 else if(c->mina < (float)*h / *w) |
291 *h = bh; |
298 *h = *w * c->mina; |
292 if(*w < bh) |
299 } |
293 *w = bh; |
300 |
294 |
301 if(baseismin) { /* increment calculation requires this */ |
295 if(resizehints || c->isfloating) { |
302 *w -= c->basew; |
296 /* see last two sentences in ICCCM 4.1.2.3 */ |
303 *h -= c->baseh; |
297 baseismin = c->basew == c->minw && c->baseh == c->minh; |
304 } |
298 |
305 |
299 if(!baseismin) { /* temporarily remove base dimensions */ |
306 /* adjust for increment value */ |
300 *w -= c->basew; |
307 if(c->incw) |
301 *h -= c->baseh; |
308 *w -= *w % c->incw; |
302 } |
309 if(c->inch) |
303 |
310 *h -= *h % c->inch; |
304 /* adjust for aspect limits */ |
311 |
305 if(c->mina > 0 && c->maxa > 0) { |
312 /* restore base dimensions */ |
306 if(c->maxa < (float)*w / *h) |
313 *w += c->basew; |
307 *w = *h * c->maxa; |
314 *h += c->baseh; |
308 else if(c->mina < (float)*h / *w) |
315 |
309 *h = *w * c->mina; |
316 *w = MAX(*w, c->minw); |
310 } |
317 *h = MAX(*h, c->minh); |
311 |
318 |
312 if(baseismin) { /* increment calculation requires this */ |
319 if(c->maxw) |
313 *w -= c->basew; |
320 *w = MIN(*w, c->maxw); |
314 *h -= c->baseh; |
321 |
315 } |
322 if(c->maxh) |
316 |
323 *h = MIN(*h, c->maxh); |
317 /* adjust for increment value */ |
|
318 if(c->incw) |
|
319 *w -= *w % c->incw; |
|
320 if(c->inch) |
|
321 *h -= *h % c->inch; |
|
322 |
|
323 /* restore base dimensions */ |
|
324 *w += c->basew; |
|
325 *h += c->baseh; |
|
326 |
|
327 *w = MAX(*w, c->minw); |
|
328 *h = MAX(*h, c->minh); |
|
329 |
|
330 if(c->maxw) |
|
331 *w = MIN(*w, c->maxw); |
|
332 |
|
333 if(c->maxh) |
|
334 *h = MIN(*h, c->maxh); |
|
335 } |
|
336 return *x != c->x || *y != c->y || *w != c->w || *h != c->h; |
324 } |
337 } |
325 |
338 |
326 void |
339 void |
327 arrange(void) { |
340 arrange(void) { |
328 unsigned int nt; |
341 unsigned int nt; |
1003 ocy = c->y; |
1016 ocy = c->y; |
1004 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1017 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1005 None, cursor[CurMove], CurrentTime) != GrabSuccess) |
1018 None, cursor[CurMove], CurrentTime) != GrabSuccess) |
1006 return; |
1019 return; |
1007 XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui); |
1020 XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui); |
1008 if(usegrab) |
|
1009 XGrabServer(dpy); |
|
1010 do { |
1021 do { |
1011 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); |
1022 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); |
1012 switch (ev.type) { |
1023 switch (ev.type) { |
1013 case ConfigureRequest: |
1024 case ConfigureRequest: |
1014 case Expose: |
1025 case Expose: |
1089 |
1098 |
1090 void |
1099 void |
1091 resize(Client *c, int x, int y, int w, int h) { |
1100 resize(Client *c, int x, int y, int w, int h) { |
1092 XWindowChanges wc; |
1101 XWindowChanges wc; |
1093 |
1102 |
1094 applysizehints(c, &w, &h); |
1103 if(applysizehints(c, &x, &y, &w, &h)) { |
1095 if(w <= 0 || h <= 0) |
|
1096 return; |
|
1097 if(x > sx + sw) |
|
1098 x = sw - WIDTH(c); |
|
1099 if(y > sy + sh) |
|
1100 y = sh - HEIGHT(c); |
|
1101 if(x + w + 2 * c->bw < sx) |
|
1102 x = sx; |
|
1103 if(y + h + 2 * c->bw < sy) |
|
1104 y = sy; |
|
1105 if(h < bh) |
|
1106 h = bh; |
|
1107 if(w < bh) |
|
1108 w = bh; |
|
1109 if(c->x != x || c->y != y || c->w != w || c->h != h) { |
|
1110 c->x = wc.x = x; |
1104 c->x = wc.x = x; |
1111 c->y = wc.y = y; |
1105 c->y = wc.y = y; |
1112 c->w = wc.width = w; |
1106 c->w = wc.width = w; |
1113 c->h = wc.height = h; |
1107 c->h = wc.height = h; |
1114 wc.border_width = c->bw; |
1108 wc.border_width = c->bw; |
1133 ocy = c->y; |
1127 ocy = c->y; |
1134 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1128 if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, |
1135 None, cursor[CurResize], CurrentTime) != GrabSuccess) |
1129 None, cursor[CurResize], CurrentTime) != GrabSuccess) |
1136 return; |
1130 return; |
1137 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
1131 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
1138 if(usegrab) |
|
1139 XGrabServer(dpy); |
|
1140 do { |
1132 do { |
1141 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); |
1133 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); |
1142 switch(ev.type) { |
1134 switch(ev.type) { |
1143 case ConfigureRequest: |
1135 case ConfigureRequest: |
1144 case Expose: |
1136 case Expose: |
1159 resize(c, c->x, c->y, nw, nh); |
1151 resize(c, c->x, c->y, nw, nh); |
1160 break; |
1152 break; |
1161 } |
1153 } |
1162 } |
1154 } |
1163 while(ev.type != ButtonRelease); |
1155 while(ev.type != ButtonRelease); |
1164 if(usegrab) |
|
1165 XUngrabServer(dpy); |
|
1166 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
1156 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
1167 XUngrabPointer(dpy, CurrentTime); |
1157 XUngrabPointer(dpy, CurrentTime); |
1168 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1158 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1169 } |
1159 } |
1170 |
1160 |