client.c
changeset 76 4bd49f404f10
parent 75 f08271b7cb20
child 77 38c8f7f7d401
equal deleted inserted replaced
75:f08271b7cb20 76:4bd49f404f10
     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 #include "dwm.h"
     5 
     6 
     6 #include <stdlib.h>
     7 #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 /* static functions */
    13 
       
    14 void
       
    15 ban(Client *c)
       
    16 {
       
    17 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
       
    18 	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
       
    19 }
       
    20 
    13 
    21 static void
    14 static void
    22 resizetitle(Client *c)
    15 resizetitle(Client *c)
    23 {
    16 {
    24 	int i;
    17 	int i;
    33 	c->tx = c->x + c->w - c->tw + 2;
    26 	c->tx = c->x + c->w - c->tw + 2;
    34 	c->ty = c->y;
    27 	c->ty = c->y;
    35 	XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
    28 	XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
    36 }
    29 }
    37 
    30 
    38 void
    31 static int
    39 settitle(Client *c)
    32 xerrordummy(Display *dsply, XErrorEvent *ee)
    40 {
    33 {
    41 	XTextProperty name;
    34 	return 0;
    42 	int n;
    35 }
    43 	char **list = NULL;
    36 
    44 
    37 /* extern functions */
    45 	name.nitems = 0;
    38 
    46 	c->name[0] = 0;
    39 void
    47 	XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
    40 ban(Client *c)
    48 	if(!name.nitems)
    41 {
    49 		XGetWMName(dpy, c->win, &name);
    42 	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
    50 	if(!name.nitems)
    43 	XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
    51 		return;
       
    52 	if(name.encoding == XA_STRING)
       
    53 		strncpy(c->name, (char *)name.value, sizeof(c->name));
       
    54 	else {
       
    55 		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
       
    56 				&& n > 0 && *list)
       
    57 		{
       
    58 			strncpy(c->name, *list, sizeof(c->name));
       
    59 			XFreeStringList(list);
       
    60 		}
       
    61 	}
       
    62 	XFree(name.value);
       
    63 	resizetitle(c);
       
    64 }
       
    65 
       
    66 void
       
    67 setsize(Client *c)
       
    68 {
       
    69 	XSizeHints size;
       
    70 	long msize;
       
    71 	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
       
    72 		size.flags = PSize;
       
    73 	c->flags = size.flags;
       
    74 	if(c->flags & PBaseSize) {
       
    75 		c->basew = size.base_width;
       
    76 		c->baseh = size.base_height;
       
    77 	}
       
    78 	else
       
    79 		c->basew = c->baseh = 0;
       
    80 	if(c->flags & PResizeInc) {
       
    81 		c->incw = size.width_inc;
       
    82 		c->inch = size.height_inc;
       
    83 	}
       
    84 	else
       
    85 		c->incw = c->inch = 0;
       
    86 	if(c->flags & PMaxSize) {
       
    87 		c->maxw = size.max_width;
       
    88 		c->maxh = size.max_height;
       
    89 	}
       
    90 	else
       
    91 		c->maxw = c->maxh = 0;
       
    92 	if(c->flags & PMinSize) {
       
    93 		c->minw = size.min_width;
       
    94 		c->minh = size.min_height;
       
    95 	}
       
    96 	else
       
    97 		c->minw = c->minh = 0;
       
    98 	if(c->flags & PWinGravity)
       
    99 		c->grav = size.win_gravity;
       
   100 	else
       
   101 		c->grav = NorthWestGravity;
       
   102 }
       
   103 
       
   104 void
       
   105 higher(Client *c)
       
   106 {
       
   107 	XRaiseWindow(dpy, c->win);
       
   108 	XRaiseWindow(dpy, c->title);
       
   109 }
       
   110 
       
   111 void
       
   112 lower(Client *c)
       
   113 {
       
   114 	XLowerWindow(dpy, c->title);
       
   115 	XLowerWindow(dpy, c->win);
       
   116 }
    44 }
   117 
    45 
   118 void
    46 void
   119 focus(Client *c)
    47 focus(Client *c)
   120 {
    48 {
   127 		drawtitle(old);
    55 		drawtitle(old);
   128 	drawtitle(c);
    56 	drawtitle(c);
   129 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
    57 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   130 	XFlush(dpy);
    58 	XFlush(dpy);
   131 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
    59 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
       
    60 }
       
    61 
       
    62 void
       
    63 focusnext(Arg *arg)
       
    64 {
       
    65 	Client *c;
       
    66    
       
    67 	if(!sel)
       
    68 		return;
       
    69 
       
    70 	if(!(c = getnext(sel->next)))
       
    71 		c = getnext(clients);
       
    72 	if(c) {
       
    73 		higher(c);
       
    74 		c->revert = sel;
       
    75 		focus(c);
       
    76 	}
       
    77 }
       
    78 
       
    79 void
       
    80 focusprev(Arg *arg)
       
    81 {
       
    82 	Client *c;
       
    83 
       
    84 	if(!sel)
       
    85 		return;
       
    86 
       
    87 	if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
       
    88 		higher(c);
       
    89 		focus(c);
       
    90 	}
       
    91 }
       
    92 
       
    93 Client *
       
    94 getclient(Window w)
       
    95 {
       
    96 	Client *c;
       
    97 	for(c = clients; c; c = c->next)
       
    98 		if(c->win == w)
       
    99 			return c;
       
   100 	return NULL;
       
   101 }
       
   102 
       
   103 Client *
       
   104 getctitle(Window w)
       
   105 {
       
   106 	Client *c;
       
   107 	for(c = clients; c; c = c->next)
       
   108 		if(c->title == w)
       
   109 			return c;
       
   110 	return NULL;
       
   111 }
       
   112 
       
   113 void
       
   114 gravitate(Client *c, Bool invert)
       
   115 {
       
   116 	int dx = 0, dy = 0;
       
   117 
       
   118 	switch(c->grav) {
       
   119 	case StaticGravity:
       
   120 	case NorthWestGravity:
       
   121 	case NorthGravity:
       
   122 	case NorthEastGravity:
       
   123 		dy = c->border;
       
   124 		break;
       
   125 	case EastGravity:
       
   126 	case CenterGravity:
       
   127 	case WestGravity:
       
   128 		dy = -(c->h / 2) + c->border;
       
   129 		break;
       
   130 	case SouthEastGravity:
       
   131 	case SouthGravity:
       
   132 	case SouthWestGravity:
       
   133 		dy = -c->h;
       
   134 		break;
       
   135 	default:
       
   136 		break;
       
   137 	}
       
   138 
       
   139 	switch (c->grav) {
       
   140 	case StaticGravity:
       
   141 	case NorthWestGravity:
       
   142 	case WestGravity:
       
   143 	case SouthWestGravity:
       
   144 		dx = c->border;
       
   145 		break;
       
   146 	case NorthGravity:
       
   147 	case CenterGravity:
       
   148 	case SouthGravity:
       
   149 		dx = -(c->w / 2) + c->border;
       
   150 		break;
       
   151 	case NorthEastGravity:
       
   152 	case EastGravity:
       
   153 	case SouthEastGravity:
       
   154 		dx = -(c->w + c->border);
       
   155 		break;
       
   156 	default:
       
   157 		break;
       
   158 	}
       
   159 
       
   160 	if(invert) {
       
   161 		dx = -dx;
       
   162 		dy = -dy;
       
   163 	}
       
   164 	c->x += dx;
       
   165 	c->y += dy;
       
   166 }
       
   167 
       
   168 void
       
   169 higher(Client *c)
       
   170 {
       
   171 	XRaiseWindow(dpy, c->win);
       
   172 	XRaiseWindow(dpy, c->title);
       
   173 }
       
   174 
       
   175 void
       
   176 killclient(Arg *arg)
       
   177 {
       
   178 	if(!sel)
       
   179 		return;
       
   180 	if(sel->proto & WM_PROTOCOL_DELWIN)
       
   181 		sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
       
   182 	else
       
   183 		XKillClient(dpy, sel->win);
       
   184 }
       
   185 
       
   186 void
       
   187 lower(Client *c)
       
   188 {
       
   189 	XLowerWindow(dpy, c->title);
       
   190 	XLowerWindow(dpy, c->win);
   132 }
   191 }
   133 
   192 
   134 void
   193 void
   135 manage(Window w, XWindowAttributes *wa)
   194 manage(Window w, XWindowAttributes *wa)
   136 {
   195 {
   193 		XMapRaised(dpy, c->title);
   252 		XMapRaised(dpy, c->title);
   194 	}
   253 	}
   195 }
   254 }
   196 
   255 
   197 void
   256 void
   198 gravitate(Client *c, Bool invert)
   257 maximize(Arg *arg)
   199 {
   258 {
   200 	int dx = 0, dy = 0;
   259 	if(!sel)
   201 
   260 		return;
   202 	switch(c->grav) {
   261 	sel->x = sx;
   203 	case StaticGravity:
   262 	sel->y = sy + bh;
   204 	case NorthWestGravity:
   263 	sel->w = sw - 2 * sel->border;
   205 	case NorthGravity:
   264 	sel->h = sh - 2 * sel->border - bh;
   206 	case NorthEastGravity:
   265 	higher(sel);
   207 		dy = c->border;
   266 	resize(sel, False);
   208 		break;
   267 }
   209 	case EastGravity:
       
   210 	case CenterGravity:
       
   211 	case WestGravity:
       
   212 		dy = -(c->h / 2) + c->border;
       
   213 		break;
       
   214 	case SouthEastGravity:
       
   215 	case SouthGravity:
       
   216 	case SouthWestGravity:
       
   217 		dy = -c->h;
       
   218 		break;
       
   219 	default:
       
   220 		break;
       
   221 	}
       
   222 
       
   223 	switch (c->grav) {
       
   224 	case StaticGravity:
       
   225 	case NorthWestGravity:
       
   226 	case WestGravity:
       
   227 	case SouthWestGravity:
       
   228 		dx = c->border;
       
   229 		break;
       
   230 	case NorthGravity:
       
   231 	case CenterGravity:
       
   232 	case SouthGravity:
       
   233 		dx = -(c->w / 2) + c->border;
       
   234 		break;
       
   235 	case NorthEastGravity:
       
   236 	case EastGravity:
       
   237 	case SouthEastGravity:
       
   238 		dx = -(c->w + c->border);
       
   239 		break;
       
   240 	default:
       
   241 		break;
       
   242 	}
       
   243 
       
   244 	if(invert) {
       
   245 		dx = -dx;
       
   246 		dy = -dy;
       
   247 	}
       
   248 	c->x += dx;
       
   249 	c->y += dy;
       
   250 }
       
   251 
       
   252 
   268 
   253 void
   269 void
   254 resize(Client *c, Bool inc)
   270 resize(Client *c, Bool inc)
   255 {
   271 {
   256 	XConfigureEvent e;
   272 	XConfigureEvent e;
   288 	e.override_redirect = False;
   304 	e.override_redirect = False;
   289 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
   305 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
   290 	XFlush(dpy);
   306 	XFlush(dpy);
   291 }
   307 }
   292 
   308 
   293 static int
   309 void
   294 xerrordummy(Display *dsply, XErrorEvent *ee)
   310 setsize(Client *c)
   295 {
   311 {
   296 	return 0;
   312 	XSizeHints size;
       
   313 	long msize;
       
   314 	if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
       
   315 		size.flags = PSize;
       
   316 	c->flags = size.flags;
       
   317 	if(c->flags & PBaseSize) {
       
   318 		c->basew = size.base_width;
       
   319 		c->baseh = size.base_height;
       
   320 	}
       
   321 	else
       
   322 		c->basew = c->baseh = 0;
       
   323 	if(c->flags & PResizeInc) {
       
   324 		c->incw = size.width_inc;
       
   325 		c->inch = size.height_inc;
       
   326 	}
       
   327 	else
       
   328 		c->incw = c->inch = 0;
       
   329 	if(c->flags & PMaxSize) {
       
   330 		c->maxw = size.max_width;
       
   331 		c->maxh = size.max_height;
       
   332 	}
       
   333 	else
       
   334 		c->maxw = c->maxh = 0;
       
   335 	if(c->flags & PMinSize) {
       
   336 		c->minw = size.min_width;
       
   337 		c->minh = size.min_height;
       
   338 	}
       
   339 	else
       
   340 		c->minw = c->minh = 0;
       
   341 	if(c->flags & PWinGravity)
       
   342 		c->grav = size.win_gravity;
       
   343 	else
       
   344 		c->grav = NorthWestGravity;
       
   345 }
       
   346 
       
   347 void
       
   348 settitle(Client *c)
       
   349 {
       
   350 	XTextProperty name;
       
   351 	int n;
       
   352 	char **list = NULL;
       
   353 
       
   354 	name.nitems = 0;
       
   355 	c->name[0] = 0;
       
   356 	XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
       
   357 	if(!name.nitems)
       
   358 		XGetWMName(dpy, c->win, &name);
       
   359 	if(!name.nitems)
       
   360 		return;
       
   361 	if(name.encoding == XA_STRING)
       
   362 		strncpy(c->name, (char *)name.value, sizeof(c->name));
       
   363 	else {
       
   364 		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
       
   365 				&& n > 0 && *list)
       
   366 		{
       
   367 			strncpy(c->name, *list, sizeof(c->name));
       
   368 			XFreeStringList(list);
       
   369 		}
       
   370 	}
       
   371 	XFree(name.value);
       
   372 	resizetitle(c);
   297 }
   373 }
   298 
   374 
   299 void
   375 void
   300 unmanage(Client *c)
   376 unmanage(Client *c)
   301 {
   377 {
   323 	arrange(NULL);
   399 	arrange(NULL);
   324 	if(sel)
   400 	if(sel)
   325 		focus(sel);
   401 		focus(sel);
   326 }
   402 }
   327 
   403 
   328 Client *
       
   329 getctitle(Window w)
       
   330 {
       
   331 	Client *c;
       
   332 	for(c = clients; c; c = c->next)
       
   333 		if(c->title == w)
       
   334 			return c;
       
   335 	return NULL;
       
   336 }
       
   337 
       
   338 Client *
       
   339 getclient(Window w)
       
   340 {
       
   341 	Client *c;
       
   342 	for(c = clients; c; c = c->next)
       
   343 		if(c->win == w)
       
   344 			return c;
       
   345 	return NULL;
       
   346 }
       
   347 
       
   348 void
   404 void
   349 zoom(Arg *arg)
   405 zoom(Arg *arg)
   350 {
   406 {
   351 	Client **l, *c;
   407 	Client **l, *c;
   352 
   408 
   364 	sel->next = clients; /* pop */
   420 	sel->next = clients; /* pop */
   365 	clients = sel;
   421 	clients = sel;
   366 	arrange(NULL);
   422 	arrange(NULL);
   367 	focus(sel);
   423 	focus(sel);
   368 }
   424 }
   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 }