client.c
changeset 75 f08271b7cb20
parent 74 5370ef170cc9
child 76 4bd49f404f10
equal deleted inserted replaced
74:5370ef170cc9 75:f08271b7cb20
     9 #include <X11/Xatom.h>
     9 #include <X11/Xatom.h>
    10 #include <X11/Xutil.h>
    10 #include <X11/Xutil.h>
    11 
    11 
    12 #include "dwm.h"
    12 #include "dwm.h"
    13 
    13 
    14 static Rule rule[] = {
       
    15 	/* class			instance	tags						floating */
       
    16 	{ "Firefox-bin",	"Gecko",	{ [Twww] = "www" },			False },
       
    17 };
       
    18 
       
    19 Client *
       
    20 getnext(Client *c)
       
    21 {
       
    22 	for(; c && !c->tags[tsel]; c = c->next);
       
    23 	return c;
       
    24 }
       
    25 
       
    26 void
    14 void
    27 ban(Client *c)
    15 ban(Client *c)
    28 {
    16 {
    29 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
    17 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
    30 	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
    18 	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
    31 }
    19 }
    32 
    20 
    33 static void
    21 static void
    34 resize_title(Client *c)
    22 resizetitle(Client *c)
    35 {
    23 {
    36 	int i;
    24 	int i;
    37 
    25 
    38 	c->tw = 0;
    26 	c->tw = 0;
    39 	for(i = 0; i < TLast; i++)
    27 	for(i = 0; i < TLast; i++)
    70 			strncpy(c->name, *list, sizeof(c->name));
    58 			strncpy(c->name, *list, sizeof(c->name));
    71 			XFreeStringList(list);
    59 			XFreeStringList(list);
    72 		}
    60 		}
    73 	}
    61 	}
    74 	XFree(name.value);
    62 	XFree(name.value);
    75 	resize_title(c);
    63 	resizetitle(c);
    76 }
    64 }
    77 
    65 
    78 void
    66 void
    79 setsize(Client *c)
    67 setsize(Client *c)
    80 {
    68 {
   139 		drawtitle(old);
   127 		drawtitle(old);
   140 	drawtitle(c);
   128 	drawtitle(c);
   141 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   129 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   142 	XFlush(dpy);
   130 	XFlush(dpy);
   143 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   131 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   144 }
       
   145 
       
   146 static void
       
   147 init_tags(Client *c)
       
   148 {
       
   149 	XClassHint ch;
       
   150 	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
       
   151 	unsigned int i, j;
       
   152 	Bool matched = False;
       
   153 
       
   154 	if(!len) {
       
   155 		c->tags[tsel] = tags[tsel];
       
   156 		return;
       
   157 	}
       
   158 
       
   159 	if(XGetClassHint(dpy, c->win, &ch)) {
       
   160 		if(ch.res_class && ch.res_name) {
       
   161 			for(i = 0; i < len; i++)
       
   162 				if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
       
   163 					&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
       
   164 				{
       
   165 					for(j = 0; j < TLast; j++)
       
   166 						c->tags[j] = rule[i].tags[j];
       
   167 					c->floating = rule[i].floating;
       
   168 					matched = True;
       
   169 					break;
       
   170 				}
       
   171 		}
       
   172 		if(ch.res_class)
       
   173 			XFree(ch.res_class);
       
   174 		if(ch.res_name)
       
   175 			XFree(ch.res_name);
       
   176 	}
       
   177 
       
   178 	if(!matched)
       
   179 		c->tags[tsel] = tags[tsel];
       
   180 }
   132 }
   181 
   133 
   182 void
   134 void
   183 manage(Window w, XWindowAttributes *wa)
   135 manage(Window w, XWindowAttributes *wa)
   184 {
   136 {
   194 		c->ty = c->y += bh;
   146 		c->ty = c->y += bh;
   195 	c->tw = c->w = wa->width;
   147 	c->tw = c->w = wa->width;
   196 	c->h = wa->height;
   148 	c->h = wa->height;
   197 	c->th = bh;
   149 	c->th = bh;
   198 	c->border = 1;
   150 	c->border = 1;
   199 	c->proto = proto(c->win);
   151 	c->proto = getproto(c->win);
   200 	setsize(c);
   152 	setsize(c);
   201 	XSelectInput(dpy, c->win,
   153 	XSelectInput(dpy, c->win,
   202 			StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
   154 			StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
   203 	XGetTransientForHint(dpy, c->win, &trans);
   155 	XGetTransientForHint(dpy, c->win, &trans);
   204 	twa.override_redirect = 1;
   156 	twa.override_redirect = 1;
   209 			0, DefaultDepth(dpy, screen), CopyFromParent,
   161 			0, DefaultDepth(dpy, screen), CopyFromParent,
   210 			DefaultVisual(dpy, screen),
   162 			DefaultVisual(dpy, screen),
   211 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   163 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   212 
   164 
   213 	settitle(c);
   165 	settitle(c);
   214 	init_tags(c);
   166 	settags(c);
   215 
   167 
   216 	for(l = &clients; *l; l = &(*l)->next);
   168 	for(l = &clients; *l; l = &(*l)->next);
   217 	c->next = *l; /* *l == nil */
   169 	c->next = *l; /* *l == nil */
   218 	*l = c;
   170 	*l = c;
   219 
   171 
   222 	XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
   174 	XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
   223 			GrabModeAsync, GrabModeSync, None, None);
   175 			GrabModeAsync, GrabModeSync, None, None);
   224 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
   176 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
   225 			GrabModeAsync, GrabModeSync, None, None);
   177 			GrabModeAsync, GrabModeSync, None, None);
   226 
   178 
   227 	if(!c->floating)
   179 	if(!c->dofloat)
   228 		c->floating = trans
   180 		c->dofloat = trans
   229 			|| ((c->maxw == c->minw) && (c->maxh == c->minh));
   181 			|| ((c->maxw == c->minw) && (c->maxh == c->minh));
   230 
   182 
   231 	arrange(NULL);
   183 	arrange(NULL);
   232 	/* mapping the window now prevents flicker */
   184 	/* mapping the window now prevents flicker */
   233 	if(c->tags[tsel]) {
   185 	if(c->tags[tsel]) {
   319 		c->h = c->minh;
   271 		c->h = c->minh;
   320 	if(c->maxw && c->w > c->maxw)
   272 	if(c->maxw && c->w > c->maxw)
   321 		c->w = c->maxw;
   273 		c->w = c->maxw;
   322 	if(c->maxh && c->h > c->maxh)
   274 	if(c->maxh && c->h > c->maxh)
   323 		c->h = c->maxh;
   275 		c->h = c->maxh;
   324 	resize_title(c);
   276 	resizetitle(c);
   325 	XSetWindowBorderWidth(dpy, c->win, 1);
   277 	XSetWindowBorderWidth(dpy, c->win, 1);
   326 	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   278 	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   327 	e.type = ConfigureNotify;
   279 	e.type = ConfigureNotify;
   328 	e.event = c->win;
   280 	e.event = c->win;
   329 	e.window = c->win;
   281 	e.window = c->win;
   337 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
   289 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
   338 	XFlush(dpy);
   290 	XFlush(dpy);
   339 }
   291 }
   340 
   292 
   341 static int
   293 static int
   342 dummy_xerror(Display *dsply, XErrorEvent *err)
   294 xerrordummy(Display *dsply, XErrorEvent *ee)
   343 {
   295 {
   344 	return 0;
   296 	return 0;
   345 }
   297 }
   346 
   298 
   347 void
   299 void
   348 unmanage(Client *c)
   300 unmanage(Client *c)
   349 {
   301 {
   350 	Client **l;
   302 	Client **l;
   351 
   303 
   352 	XGrabServer(dpy);
   304 	XGrabServer(dpy);
   353 	XSetErrorHandler(dummy_xerror);
   305 	XSetErrorHandler(xerrordummy);
   354 
   306 
   355 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   307 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   356 	XDestroyWindow(dpy, c->title);
   308 	XDestroyWindow(dpy, c->title);
   357 
   309 
   358 	for(l = &clients; *l && *l != c; l = &(*l)->next);
   310 	for(l = &clients; *l && *l != c; l = &(*l)->next);
   372 	if(sel)
   324 	if(sel)
   373 		focus(sel);
   325 		focus(sel);
   374 }
   326 }
   375 
   327 
   376 Client *
   328 Client *
   377 gettitle(Window w)
   329 getctitle(Window w)
   378 {
   330 {
   379 	Client *c;
   331 	Client *c;
   380 	for(c = clients; c; c = c->next)
   332 	for(c = clients; c; c = c->next)
   381 		if(c->title == w)
   333 		if(c->title == w)
   382 			return c;
   334 			return c;
   390 	for(c = clients; c; c = c->next)
   342 	for(c = clients; c; c = c->next)
   391 		if(c->win == w)
   343 		if(c->win == w)
   392 			return c;
   344 			return c;
   393 	return NULL;
   345 	return NULL;
   394 }
   346 }
       
   347 
       
   348 void
       
   349 zoom(Arg *arg)
       
   350 {
       
   351 	Client **l, *c;
       
   352 
       
   353 	if(!sel)
       
   354 		return;
       
   355 
       
   356 	if(sel == getnext(clients) && sel->next)  {
       
   357 		if((c = getnext(sel->next)))
       
   358 			sel = c;
       
   359 	}
       
   360 
       
   361 	for(l = &clients; *l && *l != sel; l = &(*l)->next);
       
   362 	*l = sel->next;
       
   363 
       
   364 	sel->next = clients; /* pop */
       
   365 	clients = sel;
       
   366 	arrange(NULL);
       
   367 	focus(sel);
       
   368 }
       
   369 
       
   370 void
       
   371 maximize(Arg *arg)
       
   372 {
       
   373 	if(!sel)
       
   374 		return;
       
   375 	sel->x = sx;
       
   376 	sel->y = sy + bh;
       
   377 	sel->w = sw - 2 * sel->border;
       
   378 	sel->h = sh - 2 * sel->border - bh;
       
   379 	higher(sel);
       
   380 	resize(sel, False);
       
   381 }
       
   382 
       
   383 void
       
   384 focusprev(Arg *arg)
       
   385 {
       
   386 	Client *c;
       
   387 
       
   388 	if(!sel)
       
   389 		return;
       
   390 
       
   391 	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
       
   392 		higher(c);
       
   393 		focus(c);
       
   394 	}
       
   395 }
       
   396 
       
   397 void
       
   398 focusnext(Arg *arg)
       
   399 {
       
   400 	Client *c;
       
   401    
       
   402 	if(!sel)
       
   403 		return;
       
   404 
       
   405 	if(!(c = getnext(sel->next)))
       
   406 		c = getnext(clients);
       
   407 	if(c) {
       
   408 		higher(c);
       
   409 		c->revert = sel;
       
   410 		focus(c);
       
   411 	}
       
   412 }
       
   413 
       
   414 void
       
   415 killclient(Arg *arg)
       
   416 {
       
   417 	if(!sel)
       
   418 		return;
       
   419 	if(sel->proto & WM_PROTOCOL_DELWIN)
       
   420 		sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
       
   421 	else
       
   422 		XKillClient(dpy, sel->win);
       
   423 }