added mouse-based resizals
This commit is contained in:
		
							parent
							
								
									5ed16faecb
								
							
						
					
					
						commit
						b9da4b082e
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -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} | ||||
|  | ||||
							
								
								
									
										10
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README
									
									
									
									
									
								
							| @ -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. | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										32
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								client.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); | ||||
| } | ||||
|  | ||||
							
								
								
									
										30
									
								
								event.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								event.c
									
									
									
									
									
								
							| @ -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; | ||||
| @ -44,6 +46,29 @@ flush_events(long even_mask) | ||||
| 	return n; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| @ -51,9 +76,8 @@ configurerequest(XEvent *e) | ||||
| 	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) | ||||
|  | ||||
							
								
								
									
										100
									
								
								mouse.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								mouse.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										26
									
								
								wm.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								wm.h
									
									
									
									
									
								
							| @ -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); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anselm R. Garbe
						Anselm R. Garbe