diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README | 10 | ||||
| -rw-r--r-- | client.c | 32 | ||||
| -rw-r--r-- | event.c | 30 | ||||
| -rw-r--r-- | kb.c (renamed from key.c) | 0 | ||||
| -rw-r--r-- | mouse.c | 100 | ||||
| -rw-r--r-- | wm.h | 26 | 
7 files changed, 181 insertions, 19 deletions
| @@ -3,7 +3,7 @@  include config.mk -WMSRC = bar.c client.c cmd.c draw.c event.c key.c util.c wm.c +WMSRC = bar.c client.c cmd.c draw.c event.c kb.c mouse.c util.c wm.c  WMOBJ = ${WMSRC:.c=.o}  MENSRC = menu.c draw.c util.c  MENOBJ = ${MENSRC:.c=.o} @@ -5,14 +5,6 @@ gridwm is an extremly fast, small, and automatic X11 window manager.  It  arranges all windows in a grid. -Configuration -------------- -You have to edit the source code for configuration, this WM is intended to -provide sane defaults, if something doesn't fits your needs, edit config.h and -maybe key.c. To change the status output edit that status variable definition -in wm.c. - -  Requirements  ------------  In order to build gridwm you need the Xlib header files. @@ -46,6 +38,6 @@ This will start gridwm on display :1 of the host foo.bar.  Configuration  -------------  The configuration of gridwm is done by customizing the config.h source file. To -customize the key bindings edit key.c. To change the status output, edit the +customize the key bindings edit kb.c. To change the status output, edit the  status command definition in wm.c. @@ -10,6 +10,8 @@  #include "util.h"  #include "wm.h" +#define CLIENT_MASK		(StructureNotifyMask | PropertyChangeMask | EnterWindowMask) +  void  update_name(Client *c)  { @@ -70,7 +72,7 @@ manage(Window w, XWindowAttributes *wa)  	c->r[RFloat].height = wa->height;  	c->border = wa->border_width;  	XSetWindowBorderWidth(dpy, c->win, 0); -	XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | EnterWindowMask); +	XSelectInput(dpy, c->win, CLIENT_MASK);  	XGetTransientForHint(dpy, c->win, &c->trans);  	if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags)  		c->size.flags = PSize; @@ -95,9 +97,34 @@ manage(Window w, XWindowAttributes *wa)  	c->snext = stack;  	stack = c;  	XMapWindow(dpy, c->win); +	XGrabButton(dpy, AnyButton, Mod1Mask, c->win, False, ButtonPressMask, +			GrabModeAsync, GrabModeSync, None, None);  	focus(c);  } +void +resize(Client *c) +{ +	XConfigureEvent e; + +	XMoveResizeWindow(dpy, c->win, c->r[RFloat].x, c->r[RFloat].y, +			c->r[RFloat].width, c->r[RFloat].height); +	e.type = ConfigureNotify; +	e.event = c->win; +	e.window = c->win; +	e.x = c->r[RFloat].x; +	e.y = c->r[RFloat].y; +	e.width = c->r[RFloat].width; +	e.height = c->r[RFloat].height; +	e.border_width = c->border; +	e.above = None; +	e.override_redirect = False; +	XSelectInput(dpy, c->win, CLIENT_MASK & ~StructureNotifyMask); +	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); +	XSelectInput(dpy, c->win, CLIENT_MASK); +	XFlush(dpy); +} +  static int  dummy_error_handler(Display *dpy, XErrorEvent *error)  { @@ -112,6 +139,7 @@ unmanage(Client *c)  	XGrabServer(dpy);  	XSetErrorHandler(dummy_error_handler); +	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);  	XUnmapWindow(dpy, c->win);  	XDestroyWindow(dpy, c->title); @@ -126,7 +154,7 @@ unmanage(Client *c)  	XFlush(dpy);  	XSetErrorHandler(error_handler);  	XUngrabServer(dpy); -	flush_events(EnterWindowMask); +	discard_events(EnterWindowMask);  	if(stack)  		focus(stack);  } @@ -12,6 +12,7 @@  #include "wm.h"  /* local functions */ +static void buttonpress(XEvent *e);  static void configurerequest(XEvent *e);  static void destroynotify(XEvent *e);  static void enternotify(XEvent *e); @@ -23,6 +24,7 @@ static void propertynotify(XEvent *e);  static void unmapnotify(XEvent *e);  void (*handler[LASTEvent]) (XEvent *) = { +	[ButtonPress] = buttonpress,  	[ConfigureRequest] = configurerequest,  	[DestroyNotify] = destroynotify,  	[EnterNotify] = enternotify, @@ -36,7 +38,7 @@ void (*handler[LASTEvent]) (XEvent *) = {  };  unsigned int -flush_events(long even_mask) +discard_events(long even_mask)  {  	XEvent ev;  	unsigned int n = 0; @@ -45,15 +47,37 @@ flush_events(long even_mask)  }  static void +buttonpress(XEvent *e) +{ +	XButtonPressedEvent *ev = &e->xbutton; +	Client *c; + +	if((c = getclient(ev->window))) { +		switch(ev->button) { +		default: +			break; +		case Button1: +			mmove(c); +			break; +		case Button2: +			XLowerWindow(dpy, c->win); +			break; +		case Button3: +			mresize(c); +			break; +		} +	} +} + +static void  configurerequest(XEvent *e)  {  	XConfigureRequestEvent *ev = &e->xconfigurerequest;  	XWindowChanges wc;  	Client *c; -	c = getclient(ev->window);  	ev->value_mask &= ~CWSibling; -	if(c) { +	if((c = getclient(ev->window))) {  		if(ev->value_mask & CWX)  			c->r[RFloat].x = ev->x;  		if(ev->value_mask & CWY) @@ -0,0 +1,100 @@ +/* + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> + * (C)opyright MMVI Kris Maglione <fbsdaemon@gmail.com> + * See LICENSE file for license details. + */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "wm.h" + +#define ButtonMask      (ButtonPressMask | ButtonReleaseMask) +#define MouseMask       (ButtonMask | PointerMotionMask) + +static void +mmatch(Client *c, int x1, int y1, int x2, int y2) +{ +	c->r[RFloat].width = abs(x1 - x2); +	c->r[RFloat].height = abs(y1 - y2); +	c->r[RFloat].width -= +		(c->r[RFloat].width - c->size.base_width) % c->size.width_inc; +	c->r[RFloat].height -= +		(c->r[RFloat].height - c->size.base_height) % c->size.height_inc; +	if(c->size.min_width && c->r[RFloat].width < c->size.min_width) +		c->r[RFloat].width = c->size.min_width; +	if(c->size.min_height && c->r[RFloat].height < c->size.min_height) +		c->r[RFloat].height = c->size.min_height; +	if(c->size.max_width && c->r[RFloat].width > c->size.max_width) +		c->r[RFloat].width = c->size.max_width; +	if(c->size.max_height && c->r[RFloat].height > c->size.max_height) +		c->r[RFloat].height = c->size.max_height; +	c->r[RFloat].x = (x1 <= x2) ? x1 : x1 - c->r[RFloat].width; +	c->r[RFloat].y = (y1 <= y2) ? y1 : y1 - c->r[RFloat].height; +} + +void +mresize(Client *c) +{ +	XEvent ev; +	int old_cx, old_cy; + +	old_cx = c->r[RFloat].x; +	old_cy = c->r[RFloat].y; +	if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync, +				None, cursor[CurResize], CurrentTime) != GrabSuccess) +		return; +	XGrabServer(dpy); +	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, +			c->r[RFloat].width, c->r[RFloat].height); +	for(;;) { +		XMaskEvent(dpy, MouseMask, &ev); +		switch(ev.type) { +		default: break; +		case MotionNotify: +			XUngrabServer(dpy); +			mmatch(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y); +			resize(c); +			XGrabServer(dpy); +			break; +		case ButtonRelease: +			XUngrabPointer(dpy, CurrentTime); +			return; +		} +	} +} + +void +mmove(Client *c) +{ +	XEvent ev; +	int x1, y1, old_cx, old_cy, di; +	unsigned int dui; +	Window dummy; + +	old_cx = c->r[RFloat].x; +	old_cy = c->r[RFloat].y; +	if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync, +				None, cursor[CurMove], CurrentTime) != GrabSuccess) +		return; +	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); +	XGrabServer(dpy); +	for(;;) { +		XMaskEvent(dpy, MouseMask, &ev); +		switch (ev.type) { +		default: break; +		case MotionNotify: +			XUngrabServer(dpy); +			c->r[RFloat].x = old_cx + (ev.xmotion.x - x1); +			c->r[RFloat].y = old_cy + (ev.xmotion.y - y1); +			resize(c); +			XGrabServer(dpy); +			break; +		case ButtonRelease: +			XUngrabServer(dpy); +			XUngrabPointer(dpy, CurrentTime); +			return; +		} +	} +} @@ -11,6 +11,22 @@  #define WM_PROTOCOL_DELWIN 1 +typedef struct Client Client; +typedef struct Key Key; +typedef enum Align Align; + +enum Align { +	NORTH = 0x01, +	EAST  = 0x02, +	SOUTH = 0x04, +	WEST  = 0x08, +	NEAST = NORTH | EAST, +	NWEST = NORTH | WEST, +	SEAST = SOUTH | EAST, +	SWEST = SOUTH | WEST, +	CENTER = NEAST | SWEST +}; +  /* atoms */  enum { WMProtocols, WMDelete, WMLast };  enum { NetSupported, NetWMName, NetLast }; @@ -21,9 +37,6 @@ enum { CurNormal, CurResize, CurMove, CurInput, CurLast };  /* rects */  enum { RFloat, RGrid, RLast }; -typedef struct Client Client; -typedef struct Key Key; -  struct Client {  	char name[256];  	char tag[256]; @@ -75,14 +88,19 @@ extern Client *getclient(Window w);  extern void focus(Client *c);  extern void update_name(Client *c);  extern void draw_client(Client *c); +extern void resize(Client *c);  /* event.c */ -extern unsigned int flush_events(long even_mask); +extern unsigned int discard_events(long even_mask);  /* key.c */  extern void update_keys();  extern void keypress(XEvent *e); +/* mouse.c */ +extern void mresize(Client *c); +extern void mmove(Client *c); +  /* wm.c */  extern int error_handler(Display *dpy, XErrorEvent *error);  extern void send_message(Window w, Atom a, long value); | 
