diff options
| -rw-r--r-- | client.c | 33 | ||||
| -rw-r--r-- | cmd.c | 14 | ||||
| -rw-r--r-- | event.c | 50 | ||||
| -rw-r--r-- | menu.c | 2 | ||||
| -rw-r--r-- | wm.c | 66 | ||||
| -rw-r--r-- | wm.h | 24 | 
6 files changed, 153 insertions, 36 deletions
| @@ -10,8 +10,8 @@  #include "util.h"  #include "wm.h" -static void -update_client_name(Client *c) +void +update_name(Client *c)  {  	XTextProperty name;  	int n; @@ -38,6 +38,20 @@ update_client_name(Client *c)  }  void +focus(Client *c) +{ +	Client **l; +	for(l=&stack; *l && *l != c; l=&(*l)->snext); +	eassert(*l == c); +	*l = c->snext; +	c->snext = stack; +	stack = c; +	XRaiseWindow(dpy, c->win); +	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); +	XFlush(dpy); +} + +void  manage(Window w, XWindowAttributes *wa)  {  	Client *c, **l; @@ -59,7 +73,7 @@ manage(Window w, XWindowAttributes *wa)  		(c->size.flags & PMinSize && c->size.flags & PMaxSize  		 && c->size.min_width == c->size.max_width  		 && c->size.min_height == c->size.max_height); -	update_client_name(c); +	update_name(c);  	twa.override_redirect = 1;  	twa.background_pixmap = ParentRelative;  	twa.event_mask = ExposureMask; @@ -73,9 +87,10 @@ manage(Window w, XWindowAttributes *wa)  	for(l=&clients; *l; l=&(*l)->next);  	c->next = *l; /* *l == nil */  	*l = c; -	XMapRaised(dpy, c->win); -	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); -	XFlush(dpy); +	c->snext = stack; +	stack = c; +	XMapWindow(dpy, c->win); +	focus(c);  }  static int @@ -98,12 +113,15 @@ unmanage(Client *c)  	for(l=&clients; *l && *l != c; l=&(*l)->next);  	eassert(*l == c);  	*l = c->next; +	for(l=&stack; *l && *l != c; l=&(*l)->snext); +	eassert(*l == c); +	*l = c->snext;  	free(c);  	XFlush(dpy);  	XSetErrorHandler(error_handler);  	XUngrabServer(dpy); -	/*flush_masked_events(EnterWindowMask); ? */ +	flush_events(EnterWindowMask);  } @@ -116,3 +134,4 @@ getclient(Window w)  			return c;  	return NULL;  } + @@ -18,3 +18,17 @@ quit(char *arg)  	fputs("quit\n", stderr);  	running = False;  } + +void +kill(char *arg) +{ +	Client *c = stack; + +	if(!c) +		return; +	if(c->proto & WM_PROTOCOL_DELWIN) +		send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); +	else +		XKillClient(dpy, c->win); +} + @@ -7,6 +7,7 @@  #include <stdlib.h>  #include <string.h>  #include <X11/keysym.h> +#include <X11/Xatom.h>  #include "wm.h" @@ -35,7 +36,7 @@ void (*handler[LASTEvent]) (XEvent *) = {  };  unsigned int -flush_masked_events(long even_mask) +flush_events(long even_mask)  {  	XEvent ev;  	unsigned int n = 0; @@ -91,25 +92,18 @@ destroynotify(XEvent *e)  static void  enternotify(XEvent *e)  { -#if 0  	XCrossingEvent *ev = &e->xcrossing;  	Client *c;  	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)  		return; -	if((c = client_of_win(ev->window))) { -		Frame *f = c->sel; -		Area *a = f->area; -		if(a->mode == Colmax) -			c = a->sel->client; -		focus(c, False); -	} +	if((c = getclient(ev->window))) +		focus(c);  	else if(ev->window == root) {  		sel_screen = True; -		draw_frames(); +		/*draw_frames();*/  	} -#endif  }  static void @@ -137,9 +131,7 @@ expose(XEvent *e)  static void  keymapnotify(XEvent *e)  { -#if 0  	update_keys(); -#endif  }  static void @@ -164,16 +156,40 @@ maprequest(XEvent *e)  static void  propertynotify(XEvent *e)  { -#if 0  	XPropertyEvent *ev = &e->xproperty; +	long msize;  	Client *c;  	if(ev->state == PropertyDelete)  		return; /* ignore */ -	if((c = client_of_win(ev->window))) -		prop_client(c, ev); -#endif +	if(ev->atom == wm_atom[WMProtocols]) { +		c->proto = win_proto(c->win); +		return; +	} +	if((c = getclient(ev->window))) { +		switch (ev->atom) { +			default: break; +			case XA_WM_TRANSIENT_FOR: +				XGetTransientForHint(dpy, c->win, &c->trans); +				break; +			case XA_WM_NORMAL_HINTS: +				if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) +						|| !c->size.flags) +					c->size.flags = PSize; +				if(c->size.flags & PMinSize && c->size.flags & PMaxSize +						&& c->size.min_width == c->size.max_width +						&& c->size.min_height == c->size.max_height) +					c->fixedsize = True; +				else +					c->fixedsize = False; +				break; +		} +		if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) { +			update_name(c); +			/*draw_frame(c->sel);*/ +		} +	}  }  static void @@ -304,7 +304,7 @@ kpress(XKeyEvent * e)  		}  		break;  	default: -		if((num == 1) && !iscntrl((int) buf[0])) { +		if(num && !iscntrl((int) buf[0])) {  			buf[num] = 0;  			if(len > 0)  				strncat(text, buf, sizeof(text)); @@ -16,18 +16,18 @@  /* X structs */  Display *dpy;  Window root, barwin; -Atom net_atom[NetLast]; +Atom wm_atom[WMLast], net_atom[NetLast];  Cursor cursor[CurLast];  XRectangle rect, barrect;  Bool running = True; +Bool sel_screen;  char *bartext, tag[256]; -int screen, sel_screen; +int screen;  Brush brush = {0};  Client *clients = NULL; - -enum { WM_PROTOCOL_DELWIN = 1 }; +Client *stack = NULL;  static Bool other_wm_running;  static char version[] = "gridwm - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; @@ -62,6 +62,62 @@ scan_wins()  		XFree(wins);  } +static int +win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) +{ +	Atom real; +	int format; +	unsigned long res, extra; +	int status; + +	status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format, +			&res, &extra, prop); + +	if(status != Success || *prop == 0) { +		return 0; +	} +	if(res == 0) { +		free((void *) *prop); +	} +	return res; +} + +int +win_proto(Window w) +{ +	Atom *protocols; +	long res; +	int protos = 0; +	int i; + +	res = win_property(w, wm_atom[WMProtocols], XA_ATOM, 20L, +			((unsigned char **) &protocols)); +	if(res <= 0) { +		return protos; +	} +	for(i = 0; i < res; i++) { +		if(protocols[i] == wm_atom[WMDelete]) +			protos |= WM_PROTOCOL_DELWIN; +	} +	free((char *) protocols); +	return protos; +} + +void +send_message(Window w, Atom a, long value) +{ +	XEvent e; + +	e.type = ClientMessage; +	e.xclient.window = w; +	e.xclient.message_type = a; +	e.xclient.format = 32; +	e.xclient.data.l[0] = value; +	e.xclient.data.l[1] = CurrentTime; +	XSendEvent(dpy, w, False, NoEventMask, &e); +	XFlush(dpy); +} +  /*   * There's no way to check accesses to destroyed windows, thus   * those cases are ignored (especially on UnmapNotify's). @@ -160,6 +216,8 @@ main(int argc, char *argv[])  	x_error_handler = XSetErrorHandler(error_handler);  	/* init atoms */ +	wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); +	wm_atom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);  	net_atom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);  	net_atom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); @@ -9,7 +9,10 @@  #include <X11/Xutil.h> +#define WM_PROTOCOL_DELWIN 1 +  /* atoms */ +enum { WMProtocols, WMDelete, WMLast };  enum { NetSupported, NetWMName, NetLast };  /* cursor */ @@ -25,6 +28,7 @@ struct Client {  	char name[256];  	char tag[256];  	unsigned int border; +	int proto;  	Bool fixedsize;  	Window win;  	Window trans; @@ -44,18 +48,17 @@ struct Key {  extern Display *dpy;  extern Window root, barwin; -extern Atom net_atom[NetLast]; +extern Atom wm_atom[WMLast], net_atom[NetLast];  extern Cursor cursor[CurLast];  extern XRectangle rect, barrect; -extern Bool running; -extern Bool grid; +extern Bool running, sel_screen, grid;  extern void (*handler[LASTEvent]) (XEvent *); -extern int screen, sel_screen; +extern int screen;  extern char *bartext, tag[256];  extern Brush brush; -extern Client *clients; +extern Client *clients, *stack;  /* bar.c */  extern void draw_bar(); @@ -66,8 +69,13 @@ extern void quit(char *arg);  /* client.c */  extern void manage(Window w, XWindowAttributes *wa); -void unmanage(Client *c); -extern Client * getclient(Window w); +extern void unmanage(Client *c); +extern Client *getclient(Window w); +extern void focus(Client *c); +extern void update_name(Client *c); + +/* event.c */ +extern unsigned int flush_events(long even_mask);  /* key.c */  extern void update_keys(); @@ -75,3 +83,5 @@ extern void keypress(XEvent *e);  /* wm.c */  extern int error_handler(Display *dpy, XErrorEvent *error); +extern void send_message(Window w, Atom a, long value); +extern int win_proto(Window w); | 
