client.c
changeset 50 148f25ed0ad7
parent 49 466591c2f967
child 51 035617ee18d1
equal deleted inserted replaced
49:466591c2f967 50:148f25ed0ad7
    11 
    11 
    12 #include "dwm.h"
    12 #include "dwm.h"
    13 
    13 
    14 static void (*arrange)(Arg *) = floating;
    14 static void (*arrange)(Arg *) = floating;
    15 
    15 
       
    16 static void
       
    17 center(Client *c)
       
    18 {
       
    19 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
       
    20 }
       
    21 
    16 static Client *
    22 static Client *
    17 next(Client *c)
    23 next(Client *c)
    18 {
    24 {
    19 	for(c = c->next; c && !c->tags[tsel]; c = c->next);
    25 	for(; c && !c->tags[tsel]; c = c->next);
    20 	return c;
    26 	return c;
    21 }
    27 }
    22 
    28 
    23 static Client *
    29 void
    24 prev(Client *c)
    30 zoom(Arg *arg)
    25 {
    31 {
    26 	for(c = c->prev; c && !c->tags[tsel]; c = c->prev);
    32 	Client **l;
    27 	return c;
    33 
       
    34 	if(!sel)
       
    35 		return;
       
    36 
       
    37 	for(l = &clients; *l && *l != sel; l = &(*l)->next);
       
    38 	*l = sel->next;
       
    39 
       
    40 	sel->next = clients; /* pop */
       
    41 	clients = sel;
       
    42 	arrange(NULL);
       
    43 	center(sel);
       
    44 	focus(sel);
    28 }
    45 }
    29 
    46 
    30 void
    47 void
    31 max(Arg *arg)
    48 max(Arg *arg)
    32 {
    49 {
    33 	if(!csel)
    50 	if(!sel)
    34 		return;
    51 		return;
    35 	csel->x = sx;
    52 	sel->x = sx;
    36 	csel->y = sy;
    53 	sel->y = sy;
    37 	csel->w = sw - 2 * csel->border;
    54 	sel->w = sw - 2 * sel->border;
    38 	csel->h = sh - 2 * csel->border;
    55 	sel->h = sh - 2 * sel->border;
    39 	craise(csel);
    56 	craise(sel);
    40 	resize(csel);
    57 	resize(sel);
    41 	discard_events(EnterWindowMask);
    58 	discard_events(EnterWindowMask);
    42 }
    59 }
    43 
    60 
    44 void
    61 void
       
    62 view(Arg *arg)
       
    63 {
       
    64 	tsel = arg->i;
       
    65 	arrange(NULL);
       
    66 }
       
    67 
       
    68 void
    45 tag(Arg *arg)
    69 tag(Arg *arg)
    46 {
    70 {
    47 	if(!csel)
    71 	int i, n;
    48 		return;
    72 	if(!sel)
    49 
    73 		return;
    50 	if(arg->i == tsel)
    74 
    51 		return;
    75 	if(arg->i == tsel) {
    52 
    76 		for(n = i = 0; i < TLast; i++)
    53 	if(csel->tags[arg->i])
    77 			if(sel->tags[i])
    54 		csel->tags[arg->i] = NULL; /* toggle tag */
    78 				n++;
    55 	else
    79 		if(n < 2)
    56 		csel->tags[arg->i] = tags[arg->i];
    80 			return;
       
    81 	}
       
    82 
       
    83 	if(sel->tags[arg->i])
       
    84 		sel->tags[arg->i] = NULL; /* toggle tag */
       
    85 	else
       
    86 		sel->tags[arg->i] = tags[arg->i];
    57 	arrange(NULL);
    87 	arrange(NULL);
    58 }
    88 }
    59 
    89 
       
    90 static void
       
    91 ban_client(Client *c)
       
    92 {
       
    93 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
       
    94 	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
       
    95 }
       
    96 
    60 void
    97 void
    61 floating(Arg *arg)
    98 floating(Arg *arg)
    62 {
    99 {
    63 	Client *c;
   100 	Client *c;
    64 
   101 
    65 	arrange = floating;
   102 	arrange = floating;
    66 	if(!csel)
   103 	for(c = clients; c; c = c->next) {
    67 		return;
   104 		if(c->tags[tsel])
    68 	for(c = csel; c; c = next(c))
   105 			resize(c);
    69 		resize(c);
   106 		else
       
   107 			ban_client(c);
       
   108 	}
       
   109 	if(sel && !sel->tags[tsel]) {
       
   110 		if((sel = next(clients))) {
       
   111 			craise(sel);
       
   112 			focus(sel);
       
   113 		}
       
   114 	}
    70 	discard_events(EnterWindowMask);
   115 	discard_events(EnterWindowMask);
    71 }
   116 }
    72 
   117 
    73 void
   118 void
    74 tiling(Arg *arg)
   119 tiling(Arg *arg)
    76 	Client *c;
   121 	Client *c;
    77 	int n, cols, rows, gw, gh, i, j;
   122 	int n, cols, rows, gw, gh, i, j;
    78     float rt, fd;
   123     float rt, fd;
    79 
   124 
    80 	arrange = tiling;
   125 	arrange = tiling;
    81 	if(!csel)
   126 	for(n = 0, c = clients; c; c = next(c->next), n++);
    82 		return;
   127 	if(n) {
    83 	for(n = 0, c = csel; c; c = next(c), n++);
   128 		rt = sqrt(n);
    84 	rt = sqrt(n);
   129 		if(modff(rt, &fd) < 0.5)
    85 	if(modff(rt, &fd) < 0.5)
   130 			rows = floor(rt);
    86 		rows = floor(rt);
   131 		else
    87 	else
   132 			rows = ceil(rt);
    88 		rows = ceil(rt);
   133 		if(rows * rows < n)
    89 	if(rows * rows < n)
   134 			cols = rows + 1;
    90 		cols = rows + 1;
   135 		else
    91 	else
   136 			cols = rows;
    92 		cols = rows;
   137 
    93 
   138 		gw = (sw - 2)  / cols;
    94 	gw = (sw - 2)  / cols;
   139 		gh = (sh - 2) / rows;
    95 	gh = (sh - 2) / rows;
   140 	}
    96 
   141 	else
    97 	for(i = j = 0, c = csel; c; c = next(c)) {
   142 		cols = rows = gw = gh = 0;
    98 		c->x = i * gw;
   143 
    99 		c->y = j * gh;
   144 	for(i = j = 0, c = clients; c; c = c->next) {
   100 		c->w = gw;
   145 		if(c->tags[tsel]) {
   101 		c->h = gh;
   146 			c->x = i * gw;
   102 		resize(c);
   147 			c->y = j * gh;
   103 		if(++i == cols) {
   148 			c->w = gw;
   104 			j++;
   149 			c->h = gh;
   105 			i = 0;
   150 			resize(c);
       
   151 			if(++i == cols) {
       
   152 				j++;
       
   153 				i = 0;
       
   154 			}
   106 		}
   155 		}
       
   156 		else
       
   157 			ban_client(c);
       
   158 	}
       
   159 	if(sel && !sel->tags[tsel]) {
       
   160 		if((sel = next(clients))) {
       
   161 			craise(sel);
       
   162 			focus(sel);
       
   163 		}
   107 	}
   164 	}
   108 	discard_events(EnterWindowMask);
   165 	discard_events(EnterWindowMask);
   109 }
   166 }
   110 
   167 
   111 void
   168 void
   112 prevc(Arg *arg)
   169 prevc(Arg *arg)
   113 {
   170 {
   114 	Client *c;
   171 	Client *c;
   115 
   172 
   116 	if(!csel)
   173 	if(!sel)
   117 		return;
   174 		return;
   118 
   175 
   119 	if(!(c = prev(csel)))
   176 	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
   120 		c = prev(cend);
   177 		craise(c);
       
   178 		center(c);
       
   179 		focus(c);
       
   180 	}
       
   181 }
       
   182 
       
   183 void
       
   184 nextc(Arg *arg)
       
   185 {
       
   186 	Client *c;
       
   187    
       
   188 	if(!sel)
       
   189 		return;
       
   190 
       
   191 	if(!(c = next(sel->next)))
       
   192 		c = next(clients);
   121 	if(c) {
   193 	if(c) {
   122 		craise(c);
   194 		craise(c);
   123 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
   195 		center(c);
       
   196 		c->revert = sel;
   124 		focus(c);
   197 		focus(c);
   125 	}
   198 	}
   126 }
   199 }
   127 
   200 
   128 void
   201 void
   129 nextc(Arg *arg)
       
   130 {
       
   131 	Client *c;
       
   132    
       
   133 	if(!csel)
       
   134 		return;
       
   135 
       
   136 	if(!(c = next(csel)))
       
   137 		c = next(cstart);
       
   138 
       
   139 	if(c) {
       
   140 		craise(c);
       
   141 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
       
   142 		focus(c);
       
   143 	}
       
   144 }
       
   145 
       
   146 void
       
   147 ckill(Arg *arg)
   202 ckill(Arg *arg)
   148 {
   203 {
   149 	Client *c = csel;
   204 	if(!sel)
   150 
   205 		return;
   151 	if(!c)
   206 	if(sel->proto & WM_PROTOCOL_DELWIN)
   152 		return;
   207 		send_message(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
   153 	if(c->proto & WM_PROTOCOL_DELWIN)
   208 	else
   154 		send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
   209 		XKillClient(dpy, sel->win);
   155 	else
       
   156 		XKillClient(dpy, c->win);
       
   157 }
   210 }
   158 
   211 
   159 static void
   212 static void
   160 resize_title(Client *c)
   213 resize_title(Client *c)
   161 {
   214 {
   254 }
   307 }
   255 
   308 
   256 void
   309 void
   257 focus(Client *c)
   310 focus(Client *c)
   258 {
   311 {
   259 	if(csel && csel != c) {
   312 	if(sel && sel != c) {
   260 		XSetWindowBorder(dpy, csel->win, dc.bg);
   313 		XSetWindowBorder(dpy, sel->win, dc.bg);
   261 		XMapWindow(dpy, csel->title);
   314 		XMapWindow(dpy, sel->title);
   262 		draw_client(csel);
   315 		draw_client(sel);
   263 	}
   316 	}
   264 	csel = c;
   317 	sel = c;
   265 	XUnmapWindow(dpy, c->title);
   318 	XUnmapWindow(dpy, c->title);
   266 	XSetWindowBorder(dpy, c->win, dc.fg);
   319 	XSetWindowBorder(dpy, c->win, dc.fg);
   267 	draw_client(c);
   320 	draw_client(c);
   268 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   321 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   269 	XFlush(dpy);
   322 	XFlush(dpy);
   271 }
   324 }
   272 
   325 
   273 void
   326 void
   274 manage(Window w, XWindowAttributes *wa)
   327 manage(Window w, XWindowAttributes *wa)
   275 {
   328 {
   276 	Client *c;
   329 	Client *c, **l;
   277 	XSetWindowAttributes twa;
   330 	XSetWindowAttributes twa;
   278 
   331 
   279 	c = emallocz(sizeof(Client));
   332 	c = emallocz(sizeof(Client));
   280 	c->win = w;
   333 	c->win = w;
   281 	c->tx = c->x = wa->x;
   334 	c->tx = c->x = wa->x;
   282 	c->ty = c->y = wa->y;
   335 	c->ty = c->y = wa->y;
   283 	c->tw = c->w = wa->width;
   336 	c->tw = c->w = wa->width;
   284 	c->h = wa->height;
   337 	c->h = wa->height;
   285 	c->th = th;
   338 	c->th = th;
   286 	c->border = 1;
   339 	c->border = 1;
       
   340 	c->proto = win_proto(c->win);
   287 	update_size(c);
   341 	update_size(c);
   288 	XSelectInput(dpy, c->win,
   342 	XSelectInput(dpy, c->win,
   289 			StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
   343 			StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
   290 	XGetTransientForHint(dpy, c->win, &c->trans);
   344 	XGetTransientForHint(dpy, c->win, &c->trans);
   291 	twa.override_redirect = 1;
   345 	twa.override_redirect = 1;
   298 			DefaultVisual(dpy, screen),
   352 			DefaultVisual(dpy, screen),
   299 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   353 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   300 
   354 
   301 	update_name(c);
   355 	update_name(c);
   302 
   356 
   303 	if(!cstart)
   357 	for(l = &clients; *l; l = &(*l)->next);
   304 		cstart = cend = c;
   358 	c->next = *l; /* *l == nil */
   305 	else {
   359 	*l = c;
   306 		cend->next = c;
       
   307 		c->prev = cend;
       
   308 		cend = c;
       
   309 	}
       
   310 
   360 
   311 	XSetWindowBorderWidth(dpy, c->win, 1);
   361 	XSetWindowBorderWidth(dpy, c->win, 1);
   312 	XMapRaised(dpy, c->win);
   362 	XMapRaised(dpy, c->win);
   313 	XMapRaised(dpy, c->title);
   363 	XMapRaised(dpy, c->title);
   314 	XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
   364 	XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
   316 	XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
   366 	XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
   317 			GrabModeAsync, GrabModeSync, None, None);
   367 			GrabModeAsync, GrabModeSync, None, None);
   318 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
   368 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
   319 			GrabModeAsync, GrabModeSync, None, None);
   369 			GrabModeAsync, GrabModeSync, None, None);
   320 	arrange(NULL);
   370 	arrange(NULL);
   321 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
   371 	center(c);
   322 	focus(c);
   372 	focus(c);
   323 }
   373 }
   324 
   374 
   325 void
   375 void
   326 gravitate(Client *c, Bool invert)
   376 gravitate(Client *c, Bool invert)
   418 }
   468 }
   419 
   469 
   420 void
   470 void
   421 unmanage(Client *c)
   471 unmanage(Client *c)
   422 {
   472 {
       
   473 	Client **l;
       
   474 
   423 	XGrabServer(dpy);
   475 	XGrabServer(dpy);
   424 	XSetErrorHandler(dummy_error_handler);
   476 	XSetErrorHandler(dummy_error_handler);
   425 
   477 
   426 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   478 	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   427 	XDestroyWindow(dpy, c->title);
   479 	XDestroyWindow(dpy, c->title);
   428 
   480 
   429 	if(c->prev) {
   481 	for(l = &clients; *l && *l != c; l = &(*l)->next);
   430 		c->prev->next = c->next;
   482 	*l = c->next;
   431 		if(csel == c)
   483 	for(l = &clients; *l; l = &(*l)->next)
   432 			csel = c->prev;
   484 		if((*l)->revert == c)
   433 	}
   485 			(*l)->revert = NULL;
   434 	if(c->next) {
   486 	if(sel == c)
   435 		c->next->prev = c->prev;
   487 		sel = sel->revert ? sel->revert : clients;
   436 		if(csel == c)
       
   437 			csel = c->next;
       
   438 	}
       
   439 	if(cstart == c)
       
   440 		cstart = c->next;
       
   441 	if(cend == c)
       
   442 		cend = c->prev;
       
   443 
   488 
   444 	free(c);
   489 	free(c);
   445 
   490 
   446 	XFlush(dpy);
   491 	XFlush(dpy);
   447 	XSetErrorHandler(error_handler);
   492 	XSetErrorHandler(error_handler);
   448 	XUngrabServer(dpy);
   493 	XUngrabServer(dpy);
   449 	arrange(NULL);
   494 	arrange(NULL);
   450 	if(csel)
   495 	if(sel)
   451 		focus(csel);
   496 		focus(sel);
   452 }
   497 }
   453 
   498 
   454 Client *
   499 Client *
   455 gettitle(Window w)
   500 gettitle(Window w)
   456 {
   501 {
   457 	Client *c;
   502 	Client *c;
   458 	for(c = cstart; c; c = c->next)
   503 	for(c = clients; c; c = c->next)
   459 		if(c->title == w)
   504 		if(c->title == w)
   460 			return c;
   505 			return c;
   461 	return NULL;
   506 	return NULL;
   462 }
   507 }
   463 
   508 
   464 Client *
   509 Client *
   465 getclient(Window w)
   510 getclient(Window w)
   466 {
   511 {
   467 	Client *c;
   512 	Client *c;
   468 	for(c = cstart; c; c = c->next)
   513 	for(c = clients; c; c = c->next)
   469 		if(c->win == w)
   514 		if(c->win == w)
   470 			return c;
   515 			return c;
   471 	return NULL;
   516 	return NULL;
   472 }
   517 }
   473 
   518 
   474 void
   519 void
   475 draw_client(Client *c)
   520 draw_client(Client *c)
   476 {
   521 {
   477 	int i;
   522 	int i;
   478 	if(c == csel)
   523 	if(c == sel)
   479 		return;
   524 		return;
   480 
   525 
   481 	dc.x = dc.y = 0;
   526 	dc.x = dc.y = 0;
   482 	dc.h = c->th;
   527 	dc.h = c->th;
   483 
   528