initial import
This commit is contained in:
		
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| MIT/X Consortium License | ||||
|  | ||||
| (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a | ||||
| copy of this software and associated documentation files (the "Software"), | ||||
| to deal in the Software without restriction, including without limitation | ||||
| the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
| and/or sell copies of the Software, and to permit persons to whom the  | ||||
| Software is furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in  | ||||
| all copies or substantial portions of the Software.  | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL  | ||||
| THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  | ||||
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  | ||||
| DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										23
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # gridwm - grid window manager | ||||
| #   (C)opyright MMVI Anselm R. Garbe | ||||
|  | ||||
| include config.mk | ||||
|  | ||||
| SRC      = wm.c | ||||
| OBJ      = ${SRC:.c=.o} | ||||
|  | ||||
| all: gridwm | ||||
| 	@echo finished | ||||
|  | ||||
| .c.o: | ||||
| 	@echo CC $< | ||||
| 	@${CC} -c ${CFLAGS} $< | ||||
|  | ||||
| ${OBJ}: wm.h | ||||
|  | ||||
| gridwm: ${OBJ} | ||||
| 	@echo LD $@ | ||||
| 	@${CC} -o $@ ${OBJ} ${X11LDFLAGS} | ||||
|  | ||||
| clean: | ||||
| 	rm -f gridwm *.o | ||||
							
								
								
									
										40
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| gridwm | ||||
| ------ | ||||
|  | ||||
| gridwm is an automatic X11 window manager which arranges all windows in a grid. | ||||
|  | ||||
|  | ||||
| Requirements | ||||
| ------------ | ||||
| In order to build gridwm you need the Xlib header files. | ||||
|  | ||||
|  | ||||
| Installation | ||||
| ------------ | ||||
| Edit config.mk to match your local setup. gridwm is installed into | ||||
| the /usr/local namespace by default. | ||||
|  | ||||
| Afterwards enter the following command to build and install gridwm (if | ||||
| necessary as root): | ||||
|  | ||||
|     make clean install | ||||
|  | ||||
|  | ||||
| Running gridwm | ||||
| -------------- | ||||
| Add the following line to your .xinitrc to start gridwm using startx: | ||||
|  | ||||
|     exec gridwm | ||||
|  | ||||
| In order to connect gridwm to a specific display, make sure that | ||||
| the DISPLAY environment variable is set correctly, e.g.: | ||||
|  | ||||
|     DISPLAY=foo.bar:1 exec wmii | ||||
|  | ||||
| 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. | ||||
							
								
								
									
										29
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| # Customize to fit your system | ||||
|  | ||||
| # paths | ||||
| PREFIX = /usr/local | ||||
| CONFPREFIX = ${PREFIX}/etc | ||||
| MANPREFIX = ${PREFIX}/share/man | ||||
|  | ||||
| X11INC = /usr/X11R6/include | ||||
| X11LIB = /usr/X11R6/lib | ||||
|  | ||||
| VERSION = 0.0 | ||||
|  | ||||
| # includes and libs | ||||
| LIBS = -L${PREFIX}/lib -L/usr/lib -lc | ||||
| X11LIBS = -L${X11LIB} -lX11 | ||||
|  | ||||
| # Linux/BSD | ||||
| CFLAGS = -g -Wall -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \ | ||||
| 	-DVERSION=\"${VERSION}\" | ||||
| LDFLAGS = -g ${LIBS} | ||||
| X11LDFLAGS = ${LDFLAGS} ${X11LIBS} | ||||
|  | ||||
| # Solaris | ||||
| #CFLAGS = -fast -xtarget=ultra ${INCLUDES} -DVERSION=\"${VERSION}\" | ||||
| #LIBS += -lnsl -lsocket | ||||
|  | ||||
| AR = ar cr | ||||
| CC = cc | ||||
| RANLIB = ranlib | ||||
							
								
								
									
										16
									
								
								gridwm.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								gridwm.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| .TH GRIDWM 1 gridwm-0.0 | ||||
| .SH NAME | ||||
| gridwm \- grid window manager | ||||
| .SH SYNOPSIS | ||||
| .B gridwm | ||||
| .RB [ \-v ] | ||||
| .SH DESCRIPTION | ||||
| .SS Overview | ||||
| .B gridwm | ||||
| is an automatic window manager for X11. | ||||
| .SS Options | ||||
| .TP | ||||
| .B \-v | ||||
| prints version information to stdout, then exits. | ||||
| .SH SEE ALSO | ||||
| .BR gridmenu (1) | ||||
							
								
								
									
										264
									
								
								wm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								wm.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,264 @@ | ||||
| /* | ||||
|  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||||
|  * See LICENSE file for license details. | ||||
|  */ | ||||
|  | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <X11/cursorfont.h> | ||||
| #include <X11/Xatom.h> | ||||
| #include <X11/Xproto.h> | ||||
|  | ||||
| #include "wm.h" | ||||
|  | ||||
| Display *dpy; | ||||
| Window root; | ||||
| XRectangle rect; | ||||
| int screen, sel_screen; | ||||
| Atom wm_atom[WMLast]; | ||||
| Atom net_atom[NetLast]; | ||||
| Cursor cursor[CurLast]; | ||||
| unsigned int kmask, numlock_mask; | ||||
| Pixmap pmap; | ||||
|  | ||||
| enum { WM_PROTOCOL_DELWIN = 1 }; | ||||
|  | ||||
| static Bool other_wm_running; | ||||
| static int (*x_error_handler) (Display *, XErrorEvent *); | ||||
| static char version[] = "gridwm - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; | ||||
|  | ||||
| static void | ||||
| usage() | ||||
| { | ||||
| 	fputs("usage: gridwm [-v]\n", stderr); | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| void | ||||
| error(char *errstr, ...) { | ||||
| 	va_list ap; | ||||
| 	va_start(ap, errstr); | ||||
| 	vfprintf(stderr, errstr, ap); | ||||
| 	va_end(ap); | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| scan_wins() | ||||
| { | ||||
| 	unsigned int i, num; | ||||
| 	Window *wins; | ||||
| 	XWindowAttributes wa; | ||||
| 	Window d1, d2; | ||||
|  | ||||
| 	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { | ||||
| 		for(i = 0; i < num; i++) { | ||||
| 			if(!XGetWindowAttributes(dpy, wins[i], &wa)) | ||||
| 				continue; | ||||
| 			if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) | ||||
| 				continue; | ||||
| 			if(wa.map_state == IsViewable) | ||||
| 				/*manage*/; | ||||
| 		} | ||||
| 	} | ||||
| 	if(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; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * There's no way to check accesses to destroyed windows, thus | ||||
|  * those cases are ignored (especially on UnmapNotify's). | ||||
|  * Other types of errors call Xlib's default error handler, which | ||||
|  * calls exit(). | ||||
|  */ | ||||
| static int | ||||
| error_handler(Display *dpy, XErrorEvent *error) | ||||
| { | ||||
| 	if(error->error_code == BadWindow | ||||
| 			|| (error->request_code == X_SetInputFocus | ||||
| 				&& error->error_code == BadMatch) | ||||
| 			|| (error->request_code == X_PolyText8 | ||||
| 				&& error->error_code == BadDrawable) | ||||
| 			|| (error->request_code == X_PolyFillRectangle | ||||
| 				&& error->error_code == BadDrawable) | ||||
| 			|| (error->request_code == X_PolySegment | ||||
| 				&& error->error_code == BadDrawable) | ||||
| 			|| (error->request_code == X_ConfigureWindow | ||||
| 				&& error->error_code == BadMatch) | ||||
| 			|| (error->request_code == X_GrabKey | ||||
| 				&& error->error_code == BadAccess)) | ||||
| 		return 0; | ||||
| 	fprintf(stderr, "gridwm: fatal error: request code=%d, error code=%d\n", | ||||
| 			error->request_code, error->error_code); | ||||
| 	return x_error_handler(dpy, error); /* may call exit() */ | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Startup Error handler to check if another window manager | ||||
|  * is already running. | ||||
|  */ | ||||
| static int | ||||
| startup_error_handler(Display *dpy, XErrorEvent *error) | ||||
| { | ||||
| 	other_wm_running = True; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| init_lock_keys() | ||||
| { | ||||
| 	XModifierKeymap *modmap; | ||||
| 	KeyCode numlock; | ||||
| 	int i; | ||||
| 	static int masks[] = { | ||||
| 		ShiftMask, LockMask, ControlMask, Mod1Mask, | ||||
| 		Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask | ||||
| 	}; | ||||
|  | ||||
| 	numlock_mask = 0; | ||||
| 	modmap = XGetModifierMapping(dpy); | ||||
| 	numlock = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock")); | ||||
|  | ||||
| 	if(modmap && modmap->max_keypermod > 0) { | ||||
| 		int max = (sizeof(masks) / sizeof(int)) * modmap->max_keypermod; | ||||
| 		for(i = 0; i < max; i++) | ||||
| 			if(numlock && (modmap->modifiermap[i] == numlock)) | ||||
| 				numlock_mask = masks[i / modmap->max_keypermod]; | ||||
| 	} | ||||
| 	XFreeModifiermap(modmap); | ||||
|  | ||||
| 	kmask = 255 & ~(numlock_mask | LockMask); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cleanup() | ||||
| { | ||||
| 	/* | ||||
| 	Client *c; | ||||
| 	for(c=client; c; c=c->next) | ||||
| 		reparent_client(c, root, c->sel->rect.x, c->sel->rect.y); | ||||
| 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); | ||||
| 	*/ | ||||
| } | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	int i; | ||||
| 	XSetWindowAttributes wa; | ||||
| 	unsigned int mask; | ||||
| 	Window w; | ||||
|  | ||||
| 	/* command line args */ | ||||
| 	for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { | ||||
| 		switch (argv[i][1]) { | ||||
| 		case 'v': | ||||
| 			fprintf(stdout, "%s", version); | ||||
| 			exit(0); | ||||
| 			break; | ||||
| 		default: | ||||
| 			usage(); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	dpy = XOpenDisplay(0); | ||||
| 	if(!dpy) | ||||
| 		error("gridwm: cannot connect X server\n"); | ||||
|  | ||||
| 	screen = DefaultScreen(dpy); | ||||
| 	root = RootWindow(dpy, screen); | ||||
|  | ||||
| 	/* check if another WM is already running */ | ||||
| 	other_wm_running = False; | ||||
| 	XSetErrorHandler(startup_error_handler); | ||||
| 	/* this causes an error if some other WM is running */ | ||||
| 	XSelectInput(dpy, root, SubstructureRedirectMask); | ||||
| 	XSync(dpy, False); | ||||
|  | ||||
| 	if(other_wm_running) | ||||
| 		error("gridwm: another window manager is already running\n"); | ||||
|  | ||||
| 	rect.x = rect.y = 0; | ||||
| 	rect.width = DisplayWidth(dpy, screen); | ||||
| 	rect.height = DisplayHeight(dpy, screen); | ||||
| 	sel_screen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); | ||||
|  | ||||
| 	XSetErrorHandler(0); | ||||
| 	x_error_handler = XSetErrorHandler(error_handler); | ||||
|  | ||||
| 	/* init atoms */ | ||||
| 	wm_atom[WMState] = XInternAtom(dpy, "WM_STATE", False); | ||||
| 	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); | ||||
|  | ||||
| 	XChangeProperty(dpy, root, net_atom[NetSupported], XA_ATOM, 32, | ||||
| 			PropModeReplace, (unsigned char *) net_atom, NetLast); | ||||
|  | ||||
|  | ||||
| 	/* init cursors */ | ||||
| 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); | ||||
| 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); | ||||
| 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); | ||||
|  | ||||
| 	init_lock_keys(); | ||||
|  | ||||
| 	pmap = XCreatePixmap(dpy, root, rect.width, rect.height, | ||||
| 			DefaultDepth(dpy, screen)); | ||||
|  | ||||
| 	wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask; | ||||
| 	wa.cursor = cursor[CurNormal]; | ||||
| 	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); | ||||
|  | ||||
| 	scan_wins(); | ||||
|  | ||||
| 	cleanup(); | ||||
| 	XCloseDisplay(dpy); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										57
									
								
								wm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								wm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||||
|  * See LICENSE file for license details. | ||||
|  */ | ||||
|  | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xutil.h> | ||||
|  | ||||
| /* WM atoms */ | ||||
| enum { WMState, WMProtocols, WMDelete, WMLast }; | ||||
|  | ||||
| /* NET atoms */ | ||||
| enum { NetSupported, NetWMName, NetLast }; | ||||
|  | ||||
| /* Cursor */ | ||||
| enum { CurNormal, CurResize, CurMove, CurInput, CurLast }; | ||||
|  | ||||
| /* Rects */ | ||||
| enum { RFloat, RGrid, RLast }; | ||||
|  | ||||
| typedef struct Client Client; | ||||
| typedef struct Tag Tag; | ||||
|  | ||||
| struct Client { | ||||
| 	Tag *tag; | ||||
| 	char name[256]; | ||||
| 	int proto; | ||||
| 	Window win; | ||||
| 	Window trans; | ||||
| 	Window title; | ||||
| 	GC gc; | ||||
| 	XSizeHints size; | ||||
| 	XRectangle r[RLast]; | ||||
| 	Client *next; | ||||
| 	Client *tnext; | ||||
| 	Client *tprev; | ||||
| }; | ||||
|  | ||||
| struct Tag { | ||||
| 	char name[256]; | ||||
| 	Client *clients; | ||||
| 	Client *sel; | ||||
| 	XRectangle r; | ||||
| }; | ||||
|  | ||||
| extern Display *dpy; | ||||
| extern Window root; | ||||
| extern XRectangle rect; | ||||
| extern int screen, sel_screen; | ||||
| extern unsigned int kmask, numlock_mask; | ||||
| extern Atom wm_atom[WMLast]; | ||||
| extern Atom net_atom[NetLast]; | ||||
| extern Cursor cursor[CurLast]; | ||||
| extern Pixmap pmap; | ||||
|  | ||||
| /* wm.c */ | ||||
| extern void error(char *errstr, ...); | ||||
		Reference in New Issue
	
	Block a user