aewl

annotate client.c @ 75:f08271b7cb20

rearranged several stuff
author Anselm R. Garbe <garbeam@wmii.de>
date Sat, 15 Jul 2006 16:30:50 +0200
parents 5370ef170cc9
children 4bd49f404f10
rev   line source
garbeam@5 1 /*
garbeam@5 2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
garbeam@5 3 * See LICENSE file for license details.
garbeam@5 4 */
garbeam@5 5
garbeam@10 6 #include <stdlib.h>
garbeam@51 7 #include <stdio.h>
garbeam@5 8 #include <string.h>
garbeam@5 9 #include <X11/Xatom.h>
garbeam@32 10 #include <X11/Xutil.h>
garbeam@5 11
garbeam@43 12 #include "dwm.h"
garbeam@5 13
garbeam@50 14 void
garbeam@74 15 ban(Client *c)
garbeam@50 16 {
garbeam@50 17 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
garbeam@50 18 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
garbeam@50 19 }
garbeam@50 20
garbeam@26 21 static void
garbeam@75 22 resizetitle(Client *c)
garbeam@26 23 {
garbeam@31 24 int i;
garbeam@31 25
garbeam@31 26 c->tw = 0;
garbeam@31 27 for(i = 0; i < TLast; i++)
garbeam@31 28 if(c->tags[i])
garbeam@73 29 c->tw += textw(c->tags[i]);
garbeam@73 30 c->tw += textw(c->name);
garbeam@26 31 if(c->tw > c->w)
garbeam@26 32 c->tw = c->w + 2;
garbeam@26 33 c->tx = c->x + c->w - c->tw + 2;
garbeam@26 34 c->ty = c->y;
garbeam@26 35 XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
garbeam@26 36 }
garbeam@18 37
garbeam@13 38 void
garbeam@74 39 settitle(Client *c)
garbeam@5 40 {
garbeam@5 41 XTextProperty name;
garbeam@5 42 int n;
garbeam@7 43 char **list = NULL;
garbeam@5 44
garbeam@5 45 name.nitems = 0;
garbeam@5 46 c->name[0] = 0;
garbeam@5 47 XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
garbeam@5 48 if(!name.nitems)
garbeam@5 49 XGetWMName(dpy, c->win, &name);
garbeam@5 50 if(!name.nitems)
garbeam@5 51 return;
garbeam@5 52 if(name.encoding == XA_STRING)
garbeam@5 53 strncpy(c->name, (char *)name.value, sizeof(c->name));
garbeam@5 54 else {
garbeam@5 55 if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
garbeam@5 56 && n > 0 && *list)
garbeam@5 57 {
garbeam@5 58 strncpy(c->name, *list, sizeof(c->name));
garbeam@5 59 XFreeStringList(list);
garbeam@5 60 }
garbeam@5 61 }
garbeam@5 62 XFree(name.value);
garbeam@75 63 resizetitle(c);
garbeam@5 64 }
garbeam@5 65
garbeam@10 66 void
garbeam@74 67 setsize(Client *c)
garbeam@20 68 {
garbeam@20 69 XSizeHints size;
garbeam@20 70 long msize;
garbeam@20 71 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
garbeam@20 72 size.flags = PSize;
garbeam@20 73 c->flags = size.flags;
garbeam@21 74 if(c->flags & PBaseSize) {
garbeam@21 75 c->basew = size.base_width;
garbeam@21 76 c->baseh = size.base_height;
garbeam@21 77 }
garbeam@21 78 else
garbeam@21 79 c->basew = c->baseh = 0;
garbeam@21 80 if(c->flags & PResizeInc) {
garbeam@21 81 c->incw = size.width_inc;
garbeam@21 82 c->inch = size.height_inc;
garbeam@21 83 }
garbeam@21 84 else
garbeam@21 85 c->incw = c->inch = 0;
garbeam@21 86 if(c->flags & PMaxSize) {
garbeam@21 87 c->maxw = size.max_width;
garbeam@21 88 c->maxh = size.max_height;
garbeam@21 89 }
garbeam@21 90 else
garbeam@21 91 c->maxw = c->maxh = 0;
garbeam@21 92 if(c->flags & PMinSize) {
garbeam@21 93 c->minw = size.min_width;
garbeam@21 94 c->minh = size.min_height;
garbeam@21 95 }
garbeam@21 96 else
garbeam@21 97 c->minw = c->minh = 0;
garbeam@29 98 if(c->flags & PWinGravity)
garbeam@29 99 c->grav = size.win_gravity;
garbeam@29 100 else
garbeam@29 101 c->grav = NorthWestGravity;
garbeam@20 102 }
garbeam@20 103
garbeam@20 104 void
garbeam@74 105 higher(Client *c)
garbeam@26 106 {
garbeam@26 107 XRaiseWindow(dpy, c->win);
garbeam@26 108 XRaiseWindow(dpy, c->title);
garbeam@26 109 }
garbeam@26 110
garbeam@26 111 void
garbeam@26 112 lower(Client *c)
garbeam@26 113 {
garbeam@26 114 XLowerWindow(dpy, c->title);
garbeam@26 115 XLowerWindow(dpy, c->win);
garbeam@26 116 }
garbeam@26 117
garbeam@26 118 void
garbeam@13 119 focus(Client *c)
garbeam@13 120 {
garbeam@52 121 Client *old = sel;
garbeam@63 122 XEvent ev;
garbeam@52 123
garbeam@63 124 XFlush(dpy);
garbeam@50 125 sel = c;
garbeam@52 126 if(old && old != c)
garbeam@74 127 drawtitle(old);
garbeam@74 128 drawtitle(c);
garbeam@26 129 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
garbeam@13 130 XFlush(dpy);
garbeam@63 131 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
garbeam@13 132 }
garbeam@13 133
garbeam@13 134 void
garbeam@10 135 manage(Window w, XWindowAttributes *wa)
garbeam@5 136 {
garbeam@50 137 Client *c, **l;
garbeam@5 138 XSetWindowAttributes twa;
garbeam@53 139 Window trans;
garbeam@5 140
garbeam@5 141 c = emallocz(sizeof(Client));
garbeam@5 142 c->win = w;
garbeam@22 143 c->tx = c->x = wa->x;
garbeam@22 144 c->ty = c->y = wa->y;
garbeam@57 145 if(c->y < bh)
garbeam@57 146 c->ty = c->y += bh;
garbeam@22 147 c->tw = c->w = wa->width;
garbeam@20 148 c->h = wa->height;
garbeam@57 149 c->th = bh;
garbeam@29 150 c->border = 1;
garbeam@75 151 c->proto = getproto(c->win);
garbeam@74 152 setsize(c);
garbeam@26 153 XSelectInput(dpy, c->win,
garbeam@26 154 StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
garbeam@53 155 XGetTransientForHint(dpy, c->win, &trans);
garbeam@5 156 twa.override_redirect = 1;
garbeam@5 157 twa.background_pixmap = ParentRelative;
garbeam@23 158 twa.event_mask = ExposureMask;
garbeam@5 159
garbeam@22 160 c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
garbeam@20 161 0, DefaultDepth(dpy, screen), CopyFromParent,
garbeam@5 162 DefaultVisual(dpy, screen),
garbeam@5 163 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
garbeam@31 164
garbeam@74 165 settitle(c);
garbeam@75 166 settags(c);
garbeam@49 167
garbeam@50 168 for(l = &clients; *l; l = &(*l)->next);
garbeam@50 169 c->next = *l; /* *l == nil */
garbeam@50 170 *l = c;
garbeam@49 171
garbeam@19 172 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@19 173 GrabModeAsync, GrabModeSync, None, None);
garbeam@19 174 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@19 175 GrabModeAsync, GrabModeSync, None, None);
garbeam@19 176 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
garbeam@18 177 GrabModeAsync, GrabModeSync, None, None);
garbeam@53 178
garbeam@75 179 if(!c->dofloat)
garbeam@75 180 c->dofloat = trans
garbeam@53 181 || ((c->maxw == c->minw) && (c->maxh == c->minh));
garbeam@53 182
garbeam@46 183 arrange(NULL);
garbeam@60 184 /* mapping the window now prevents flicker */
garbeam@60 185 if(c->tags[tsel]) {
garbeam@60 186 XMapRaised(dpy, c->win);
garbeam@60 187 XMapRaised(dpy, c->title);
garbeam@51 188 focus(c);
garbeam@60 189 }
garbeam@60 190 else {
garbeam@74 191 ban(c);
garbeam@60 192 XMapRaised(dpy, c->win);
garbeam@60 193 XMapRaised(dpy, c->title);
garbeam@60 194 }
garbeam@5 195 }
garbeam@9 196
garbeam@18 197 void
garbeam@29 198 gravitate(Client *c, Bool invert)
garbeam@29 199 {
garbeam@29 200 int dx = 0, dy = 0;
garbeam@29 201
garbeam@29 202 switch(c->grav) {
garbeam@29 203 case StaticGravity:
garbeam@29 204 case NorthWestGravity:
garbeam@29 205 case NorthGravity:
garbeam@29 206 case NorthEastGravity:
garbeam@29 207 dy = c->border;
garbeam@29 208 break;
garbeam@29 209 case EastGravity:
garbeam@29 210 case CenterGravity:
garbeam@29 211 case WestGravity:
garbeam@29 212 dy = -(c->h / 2) + c->border;
garbeam@29 213 break;
garbeam@29 214 case SouthEastGravity:
garbeam@29 215 case SouthGravity:
garbeam@29 216 case SouthWestGravity:
garbeam@29 217 dy = -c->h;
garbeam@29 218 break;
garbeam@29 219 default:
garbeam@29 220 break;
garbeam@29 221 }
garbeam@29 222
garbeam@29 223 switch (c->grav) {
garbeam@29 224 case StaticGravity:
garbeam@29 225 case NorthWestGravity:
garbeam@29 226 case WestGravity:
garbeam@29 227 case SouthWestGravity:
garbeam@29 228 dx = c->border;
garbeam@29 229 break;
garbeam@29 230 case NorthGravity:
garbeam@29 231 case CenterGravity:
garbeam@29 232 case SouthGravity:
garbeam@29 233 dx = -(c->w / 2) + c->border;
garbeam@29 234 break;
garbeam@29 235 case NorthEastGravity:
garbeam@29 236 case EastGravity:
garbeam@29 237 case SouthEastGravity:
garbeam@29 238 dx = -(c->w + c->border);
garbeam@29 239 break;
garbeam@29 240 default:
garbeam@29 241 break;
garbeam@29 242 }
garbeam@29 243
garbeam@29 244 if(invert) {
garbeam@29 245 dx = -dx;
garbeam@29 246 dy = -dy;
garbeam@29 247 }
garbeam@29 248 c->x += dx;
garbeam@29 249 c->y += dy;
garbeam@29 250 }
garbeam@29 251
garbeam@31 252
garbeam@29 253 void
garbeam@52 254 resize(Client *c, Bool inc)
garbeam@18 255 {
garbeam@18 256 XConfigureEvent e;
garbeam@18 257
garbeam@52 258 if(inc) {
garbeam@52 259 if(c->incw)
garbeam@52 260 c->w -= (c->w - c->basew) % c->incw;
garbeam@52 261 if(c->inch)
garbeam@52 262 c->h -= (c->h - c->baseh) % c->inch;
garbeam@52 263 }
garbeam@67 264 if(c->x > sw) /* might happen on restart */
garbeam@67 265 c->x = sw - c->w;
garbeam@67 266 if(c->y > sh)
garbeam@67 267 c->ty = c->y = sh - c->h;
garbeam@31 268 if(c->minw && c->w < c->minw)
garbeam@31 269 c->w = c->minw;
garbeam@31 270 if(c->minh && c->h < c->minh)
garbeam@31 271 c->h = c->minh;
garbeam@31 272 if(c->maxw && c->w > c->maxw)
garbeam@31 273 c->w = c->maxw;
garbeam@31 274 if(c->maxh && c->h > c->maxh)
garbeam@31 275 c->h = c->maxh;
garbeam@75 276 resizetitle(c);
garbeam@55 277 XSetWindowBorderWidth(dpy, c->win, 1);
garbeam@20 278 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
garbeam@18 279 e.type = ConfigureNotify;
garbeam@18 280 e.event = c->win;
garbeam@18 281 e.window = c->win;
garbeam@20 282 e.x = c->x;
garbeam@20 283 e.y = c->y;
garbeam@20 284 e.width = c->w;
garbeam@20 285 e.height = c->h;
garbeam@29 286 e.border_width = c->border;
garbeam@18 287 e.above = None;
garbeam@18 288 e.override_redirect = False;
garbeam@18 289 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
garbeam@18 290 XFlush(dpy);
garbeam@18 291 }
garbeam@18 292
garbeam@10 293 static int
garbeam@75 294 xerrordummy(Display *dsply, XErrorEvent *ee)
garbeam@10 295 {
garbeam@10 296 return 0;
garbeam@10 297 }
garbeam@10 298
garbeam@10 299 void
garbeam@10 300 unmanage(Client *c)
garbeam@10 301 {
garbeam@50 302 Client **l;
garbeam@50 303
garbeam@10 304 XGrabServer(dpy);
garbeam@75 305 XSetErrorHandler(xerrordummy);
garbeam@10 306
garbeam@18 307 XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
garbeam@10 308 XDestroyWindow(dpy, c->title);
garbeam@10 309
garbeam@50 310 for(l = &clients; *l && *l != c; l = &(*l)->next);
garbeam@50 311 *l = c->next;
garbeam@50 312 for(l = &clients; *l; l = &(*l)->next)
garbeam@50 313 if((*l)->revert == c)
garbeam@50 314 (*l)->revert = NULL;
garbeam@50 315 if(sel == c)
garbeam@50 316 sel = sel->revert ? sel->revert : clients;
garbeam@49 317
garbeam@10 318 free(c);
garbeam@10 319
garbeam@10 320 XFlush(dpy);
garbeam@74 321 XSetErrorHandler(xerror);
garbeam@10 322 XUngrabServer(dpy);
garbeam@46 323 arrange(NULL);
garbeam@50 324 if(sel)
garbeam@50 325 focus(sel);
garbeam@10 326 }
garbeam@10 327
garbeam@23 328 Client *
garbeam@75 329 getctitle(Window w)
garbeam@23 330 {
garbeam@23 331 Client *c;
garbeam@50 332 for(c = clients; c; c = c->next)
garbeam@23 333 if(c->title == w)
garbeam@23 334 return c;
garbeam@23 335 return NULL;
garbeam@23 336 }
garbeam@10 337
garbeam@9 338 Client *
garbeam@9 339 getclient(Window w)
garbeam@9 340 {
garbeam@9 341 Client *c;
garbeam@50 342 for(c = clients; c; c = c->next)
garbeam@9 343 if(c->win == w)
garbeam@9 344 return c;
garbeam@9 345 return NULL;
garbeam@9 346 }
garbeam@75 347
garbeam@75 348 void
garbeam@75 349 zoom(Arg *arg)
garbeam@75 350 {
garbeam@75 351 Client **l, *c;
garbeam@75 352
garbeam@75 353 if(!sel)
garbeam@75 354 return;
garbeam@75 355
garbeam@75 356 if(sel == getnext(clients) && sel->next) {
garbeam@75 357 if((c = getnext(sel->next)))
garbeam@75 358 sel = c;
garbeam@75 359 }
garbeam@75 360
garbeam@75 361 for(l = &clients; *l && *l != sel; l = &(*l)->next);
garbeam@75 362 *l = sel->next;
garbeam@75 363
garbeam@75 364 sel->next = clients; /* pop */
garbeam@75 365 clients = sel;
garbeam@75 366 arrange(NULL);
garbeam@75 367 focus(sel);
garbeam@75 368 }
garbeam@75 369
garbeam@75 370 void
garbeam@75 371 maximize(Arg *arg)
garbeam@75 372 {
garbeam@75 373 if(!sel)
garbeam@75 374 return;
garbeam@75 375 sel->x = sx;
garbeam@75 376 sel->y = sy + bh;
garbeam@75 377 sel->w = sw - 2 * sel->border;
garbeam@75 378 sel->h = sh - 2 * sel->border - bh;
garbeam@75 379 higher(sel);
garbeam@75 380 resize(sel, False);
garbeam@75 381 }
garbeam@75 382
garbeam@75 383 void
garbeam@75 384 focusprev(Arg *arg)
garbeam@75 385 {
garbeam@75 386 Client *c;
garbeam@75 387
garbeam@75 388 if(!sel)
garbeam@75 389 return;
garbeam@75 390
garbeam@75 391 if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
garbeam@75 392 higher(c);
garbeam@75 393 focus(c);
garbeam@75 394 }
garbeam@75 395 }
garbeam@75 396
garbeam@75 397 void
garbeam@75 398 focusnext(Arg *arg)
garbeam@75 399 {
garbeam@75 400 Client *c;
garbeam@75 401
garbeam@75 402 if(!sel)
garbeam@75 403 return;
garbeam@75 404
garbeam@75 405 if(!(c = getnext(sel->next)))
garbeam@75 406 c = getnext(clients);
garbeam@75 407 if(c) {
garbeam@75 408 higher(c);
garbeam@75 409 c->revert = sel;
garbeam@75 410 focus(c);
garbeam@75 411 }
garbeam@75 412 }
garbeam@75 413
garbeam@75 414 void
garbeam@75 415 killclient(Arg *arg)
garbeam@75 416 {
garbeam@75 417 if(!sel)
garbeam@75 418 return;
garbeam@75 419 if(sel->proto & WM_PROTOCOL_DELWIN)
garbeam@75 420 sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
garbeam@75 421 else
garbeam@75 422 XKillClient(dpy, sel->win);
garbeam@75 423 }