client.c
changeset 51 035617ee18d1
parent 50 148f25ed0ad7
child 52 d18f6dd0cf23
equal deleted inserted replaced
50:148f25ed0ad7 51:035617ee18d1
     1 /*
     1 /*
     2  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
     2  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
     3  * See LICENSE file for license details.
     3  * See LICENSE file for license details.
     4  */
     4  */
     5 
     5 
     6 #include <math.h>
       
     7 #include <stdlib.h>
     6 #include <stdlib.h>
       
     7 #include <stdio.h>
     8 #include <string.h>
     8 #include <string.h>
     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 void (*arrange)(Arg *) = floating;
    14 static void (*arrange)(Arg *) = tiling;
    15 
    15 
    16 static void
    16 static Rule rule[] = {
    17 center(Client *c)
    17 	{ "Firefox-bin", "Gecko", { [Twww] = "www" } },
    18 {
    18 };
    19 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
       
    20 }
       
    21 
    19 
    22 static Client *
    20 static Client *
    23 next(Client *c)
    21 next(Client *c)
    24 {
    22 {
    25 	for(; c && !c->tags[tsel]; c = c->next);
    23 	for(; c && !c->tags[tsel]; c = c->next);
    27 }
    25 }
    28 
    26 
    29 void
    27 void
    30 zoom(Arg *arg)
    28 zoom(Arg *arg)
    31 {
    29 {
    32 	Client **l;
    30 	Client **l, *old;
    33 
    31 
    34 	if(!sel)
    32 	if(!(old = sel))
    35 		return;
    33 		return;
    36 
    34 
    37 	for(l = &clients; *l && *l != sel; l = &(*l)->next);
    35 	for(l = &clients; *l && *l != sel; l = &(*l)->next);
    38 	*l = sel->next;
    36 	*l = sel->next;
    39 
    37 
    40 	sel->next = clients; /* pop */
    38 	old->next = clients; /* pop */
    41 	clients = sel;
    39 	clients = old;
       
    40 	sel = old;
    42 	arrange(NULL);
    41 	arrange(NULL);
    43 	center(sel);
       
    44 	focus(sel);
    42 	focus(sel);
    45 }
    43 }
    46 
    44 
    47 void
    45 void
    48 max(Arg *arg)
    46 max(Arg *arg)
   117 
   115 
   118 void
   116 void
   119 tiling(Arg *arg)
   117 tiling(Arg *arg)
   120 {
   118 {
   121 	Client *c;
   119 	Client *c;
   122 	int n, cols, rows, gw, gh, i, j;
   120 	int n, i, w, h;
   123     float rt, fd;
   121 
   124 
   122 	w = sw - mw;
   125 	arrange = tiling;
   123 	arrange = tiling;
   126 	for(n = 0, c = clients; c; c = next(c->next), n++);
   124 	for(n = 0, c = clients; c; c = c->next)
   127 	if(n) {
   125 		if(c->tags[tsel])
   128 		rt = sqrt(n);
   126 			n++;
   129 		if(modff(rt, &fd) < 0.5)
   127 
   130 			rows = floor(rt);
   128 	h = (n > 2) ? sh / (n - 2) : sh;
   131 		else
   129 
   132 			rows = ceil(rt);
   130 	for(i = 0, c = clients; c; c = c->next) {
   133 		if(rows * rows < n)
       
   134 			cols = rows + 1;
       
   135 		else
       
   136 			cols = rows;
       
   137 
       
   138 		gw = (sw - 2)  / cols;
       
   139 		gh = (sh - 2) / rows;
       
   140 	}
       
   141 	else
       
   142 		cols = rows = gw = gh = 0;
       
   143 
       
   144 	for(i = j = 0, c = clients; c; c = c->next) {
       
   145 		if(c->tags[tsel]) {
   131 		if(c->tags[tsel]) {
   146 			c->x = i * gw;
   132 			if(n == 1) {
   147 			c->y = j * gh;
   133 				c->x = sx;
   148 			c->w = gw;
   134 				c->y = sy;
   149 			c->h = gh;
   135 				c->w = sw;
       
   136 				c->h = sh;
       
   137 			}
       
   138 			else if(i == 1) {
       
   139 				c->x = sx;
       
   140 				c->y = sy;
       
   141 				c->w = mw;
       
   142 				c->h = sh;
       
   143 			}
       
   144 			else {
       
   145 				c->x = sx + mw;
       
   146 				c->y = sy + (i - 2) * h;
       
   147 				c->w = w;
       
   148 				c->h = h;
       
   149 			}
   150 			resize(c);
   150 			resize(c);
   151 			if(++i == cols) {
   151 			i++;
   152 				j++;
       
   153 				i = 0;
       
   154 			}
       
   155 		}
   152 		}
   156 		else
   153 		else
   157 			ban_client(c);
   154 			ban_client(c);
   158 	}
   155 	}
   159 	if(sel && !sel->tags[tsel]) {
   156 	if(sel && !sel->tags[tsel]) {
   173 	if(!sel)
   170 	if(!sel)
   174 		return;
   171 		return;
   175 
   172 
   176 	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
   173 	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
   177 		craise(c);
   174 		craise(c);
   178 		center(c);
       
   179 		focus(c);
   175 		focus(c);
   180 	}
   176 	}
   181 }
   177 }
   182 
   178 
   183 void
   179 void
   190 
   186 
   191 	if(!(c = next(sel->next)))
   187 	if(!(c = next(sel->next)))
   192 		c = next(clients);
   188 		c = next(clients);
   193 	if(c) {
   189 	if(c) {
   194 		craise(c);
   190 		craise(c);
   195 		center(c);
       
   196 		c->revert = sel;
   191 		c->revert = sel;
   197 		focus(c);
   192 		focus(c);
   198 	}
   193 	}
   199 }
   194 }
   200 
   195 
   319 	XSetWindowBorder(dpy, c->win, dc.fg);
   314 	XSetWindowBorder(dpy, c->win, dc.fg);
   320 	draw_client(c);
   315 	draw_client(c);
   321 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   316 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   322 	XFlush(dpy);
   317 	XFlush(dpy);
   323 	discard_events(EnterWindowMask);
   318 	discard_events(EnterWindowMask);
       
   319 }
       
   320 
       
   321 static void
       
   322 init_tags(Client *c)
       
   323 {
       
   324 	XClassHint ch;
       
   325 	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
       
   326 	unsigned int i, j;
       
   327 	Bool matched = False;
       
   328 
       
   329 	if(!len) {
       
   330 		c->tags[tsel] = tags[tsel];
       
   331 		return;
       
   332 	}
       
   333 
       
   334 	if(XGetClassHint(dpy, c->win, &ch)) {
       
   335 		if(ch.res_class && ch.res_name) {
       
   336 			fprintf(stderr, "%s:%s\n", ch.res_class, ch.res_name);
       
   337 			for(i = 0; i < len; i++)
       
   338 				if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class))
       
   339 					&& !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance)))
       
   340 				{
       
   341 			fprintf(stderr, "->>>%s:%s\n", ch.res_class, ch.res_name);
       
   342 					for(j = 0; j < TLast; j++)
       
   343 						c->tags[j] = rule[i].tags[j];
       
   344 					matched = True;
       
   345 					break;
       
   346 				}
       
   347 		}
       
   348 		if(ch.res_class)
       
   349 			XFree(ch.res_class);
       
   350 		if(ch.res_name)
       
   351 			XFree(ch.res_name);
       
   352 	}
       
   353 
       
   354 	if(!matched)
       
   355 		c->tags[tsel] = tags[tsel];
   324 }
   356 }
   325 
   357 
   326 void
   358 void
   327 manage(Window w, XWindowAttributes *wa)
   359 manage(Window w, XWindowAttributes *wa)
   328 {
   360 {
   344 	XGetTransientForHint(dpy, c->win, &c->trans);
   376 	XGetTransientForHint(dpy, c->win, &c->trans);
   345 	twa.override_redirect = 1;
   377 	twa.override_redirect = 1;
   346 	twa.background_pixmap = ParentRelative;
   378 	twa.background_pixmap = ParentRelative;
   347 	twa.event_mask = ExposureMask;
   379 	twa.event_mask = ExposureMask;
   348 
   380 
   349 	c->tags[tsel] = tags[tsel];
       
   350 	c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
   381 	c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
   351 			0, DefaultDepth(dpy, screen), CopyFromParent,
   382 			0, DefaultDepth(dpy, screen), CopyFromParent,
   352 			DefaultVisual(dpy, screen),
   383 			DefaultVisual(dpy, screen),
   353 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   384 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
   354 
   385 
   355 	update_name(c);
   386 	update_name(c);
       
   387 	init_tags(c);
   356 
   388 
   357 	for(l = &clients; *l; l = &(*l)->next);
   389 	for(l = &clients; *l; l = &(*l)->next);
   358 	c->next = *l; /* *l == nil */
   390 	c->next = *l; /* *l == nil */
   359 	*l = c;
   391 	*l = c;
   360 
   392 
   366 	XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
   398 	XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
   367 			GrabModeAsync, GrabModeSync, None, None);
   399 			GrabModeAsync, GrabModeSync, None, None);
   368 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
   400 	XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
   369 			GrabModeAsync, GrabModeSync, None, None);
   401 			GrabModeAsync, GrabModeSync, None, None);
   370 	arrange(NULL);
   402 	arrange(NULL);
   371 	center(c);
   403 	if(c->tags[tsel])
   372 	focus(c);
   404 		focus(c);
       
   405 	else
       
   406 		ban_client(c);
   373 }
   407 }
   374 
   408 
   375 void
   409 void
   376 gravitate(Client *c, Bool invert)
   410 gravitate(Client *c, Bool invert)
   377 {
   411 {