added several other stuff 439e15d0
Anselm R. Garbe · 2006-07-10 22:16 12 file(s) · +476 −39
Makefile +2 −2
3 3
4 4
include config.mk
5 5
6 -
WMSRC = wm.c draw.c util.c
6 +
WMSRC = bar.c client.c draw.c event.c util.c wm.c
7 7
WMOBJ = ${WMSRC:.c=.o}
8 8
MENSRC = menu.c draw.c util.c
9 9
MENOBJ = ${MENSRC:.c=.o}
10 -
MAN = gridwm.1
10 +
MAN1 = gridwm.1 gridmenu.1
11 11
BIN = gridwm gridmenu     
12 12
13 13
all: config gridwm gridmenu
bar.c (added) +18 −0
1 +
/*
2 +
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 +
 * See LICENSE file for license details.
4 +
 */
5 +
6 +
#include "wm.h"
7 +
8 +
void
9 +
draw_bar()
10 +
{
11 +
	brush.rect = barrect;
12 +
	brush.rect.x = brush.rect.y = 0;
13 +
	draw(dpy, &brush, False, 0);
14 +
15 +
	XCopyArea(dpy, brush.drawable, barwin, brush.gc, 0, 0, barrect.width,
16 +
			barrect.height, 0, 0);
17 +
	XFlush(dpy);
18 +
}
client.c (added) +89 −0
1 +
/*
2 +
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 +
 * See LICENSE file for license details.
4 +
 */
5 +
6 +
#include <string.h>
7 +
#include <X11/Xatom.h>
8 +
9 +
#include "util.h"
10 +
#include "wm.h"
11 +
12 +
static void
13 +
update_client_name(Client *c)
14 +
{
15 +
	XTextProperty name;
16 +
	int n;
17 +
	char **list = 0;
18 +
19 +
	name.nitems = 0;
20 +
	c->name[0] = 0;
21 +
	XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
22 +
	if(!name.nitems)
23 +
		XGetWMName(dpy, c->win, &name);
24 +
	if(!name.nitems)
25 +
		return;
26 +
	if(name.encoding == XA_STRING)
27 +
		strncpy(c->name, (char *)name.value, sizeof(c->name));
28 +
	else {
29 +
		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
30 +
				&& n > 0 && *list)
31 +
		{
32 +
			strncpy(c->name, *list, sizeof(c->name));
33 +
			XFreeStringList(list);
34 +
		}
35 +
	}
36 +
	XFree(name.value);
37 +
}
38 +
39 +
Client *
40 +
create_client(Window w, XWindowAttributes *wa)
41 +
{
42 +
	Client *c;
43 +
	XSetWindowAttributes twa;
44 +
	long msize;
45 +
46 +
	c = emallocz(sizeof(Client));
47 +
	c->win = w;
48 +
	c->r[RFloat].x = wa->x;
49 +
	c->r[RFloat].y = wa->y;
50 +
	c->r[RFloat].width = wa->width;
51 +
	c->r[RFloat].height = wa->height;
52 +
	c->border = wa->border_width;
53 +
	XSetWindowBorderWidth(dpy, c->win, 0);
54 +
	c->proto = win_proto(c->win);
55 +
	XGetTransientForHint(dpy, c->win, &c->trans);
56 +
	if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags)
57 +
		c->size.flags = PSize;
58 +
	c->fixedsize =
59 +
		(c->size.flags & PMinSize && c->size.flags & PMaxSize
60 +
		 && c->size.min_width == c->size.max_width
61 +
		 && c->size.min_height == c->size.max_height);
62 +
	XAddToSaveSet(dpy, c->win);
63 +
	update_client_name(c);
64 +
	twa.override_redirect = 1;
65 +
	twa.background_pixmap = ParentRelative;
66 +
	twa.event_mask = ExposureMask;
67 +
68 +
	c->title = XCreateWindow(dpy, root, c->r[RFloat].x, c->r[RFloat].y,
69 +
			c->r[RFloat].width, barrect.height, 0,
70 +
			DefaultDepth(dpy, screen), CopyFromParent,
71 +
			DefaultVisual(dpy, screen),
72 +
			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
73 +
	XFlush(dpy);
74 +
75 +
#if 0
76 +
	for(t=&client, i=0; *t; t=&(*t)->next, i++);
77 +
	c->next = *t; /* *t == nil */
78 +
	*t = c;
79 +
#endif
80 +
	return c;
81 +
}
82 +
83 +
void
84 +
manage(Client *c)
85 +
{
86 +
	XMapRaised(dpy, c->win);
87 +
	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
88 +
	XFlush(dpy);
89 +
}
config.h +2 −2
4 4
 */
5 5
6 6
#define FONT		"-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*"
7 -
#define FGCOLOR		"#000000"
8 -
#define BGCOLOR		"#ffaa00"
7 +
#define BGCOLOR		"#000000"
8 +
#define FGCOLOR		"#ffaa00"
9 9
#define BORDERCOLOR	"#000000"
draw.c +6 −0
162 162
	}
163 163
	font->height = font->ascent + font->descent;
164 164
}
165 +
166 +
unsigned int
167 +
labelheight(Fnt *font)
168 +
{
169 +
	return font->height + 4;
170 +
}
draw.h +1 −0
33 33
extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
34 34
extern unsigned int textwidth_l(Fnt *font, char *text, unsigned int len);
35 35
extern unsigned int textwidth(Fnt *font, char *text);
36 +
extern unsigned int labelheight(Fnt *font);
event.c (added) +264 −0
1 +
/*
2 +
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 +
 * See LICENSE file for license details.
4 +
 */
5 +
6 +
#include <fcntl.h>
7 +
#include <stdlib.h>
8 +
#include <string.h>
9 +
#include <X11/keysym.h>
10 +
11 +
#include "wm.h"
12 +
13 +
/* local functions */
14 +
static void configurerequest(XEvent *e);
15 +
static void destroynotify(XEvent *e);
16 +
static void enternotify(XEvent *e);
17 +
static void leavenotify(XEvent *e);
18 +
static void expose(XEvent *e);
19 +
static void keypress(XEvent *e);
20 +
static void keymapnotify(XEvent *e);
21 +
static void maprequest(XEvent *e);
22 +
static void propertynotify(XEvent *e);
23 +
static void unmapnotify(XEvent *e);
24 +
25 +
void (*handler[LASTEvent]) (XEvent *) = {
26 +
	[ConfigureRequest] = configurerequest,
27 +
	[DestroyNotify] = destroynotify,
28 +
	[EnterNotify] = enternotify,
29 +
	[LeaveNotify] = leavenotify,
30 +
	[Expose] = expose,
31 +
	[KeyPress] = keypress,
32 +
	[KeymapNotify] = keymapnotify,
33 +
	[MapRequest] = maprequest,
34 +
	[PropertyNotify] = propertynotify,
35 +
	[UnmapNotify] = unmapnotify
36 +
};
37 +
38 +
unsigned int
39 +
flush_masked_events(long even_mask)
40 +
{
41 +
	XEvent ev;
42 +
	unsigned int n = 0;
43 +
	while(XCheckMaskEvent(dpy, even_mask, &ev)) n++;
44 +
	return n;
45 +
}
46 +
47 +
static void
48 +
configurerequest(XEvent *e)
49 +
{
50 +
#if 0
51 +
	XConfigureRequestEvent *ev = &e->xconfigurerequest;
52 +
	XWindowChanges wc;
53 +
	XRectangle *frect;
54 +
	Client *c;
55 +
56 +
	c = client_of_win(ev->window);
57 +
	ev->value_mask &= ~CWSibling;
58 +
	if(c) {
59 +
		gravitate_client(c, True);
60 +
61 +
		if(ev->value_mask & CWX)
62 +
			c->rect.x = ev->x;
63 +
		if(ev->value_mask & CWY)
64 +
			c->rect.y = ev->y;
65 +
		if(ev->value_mask & CWWidth)
66 +
			c->rect.width = ev->width;
67 +
		if(ev->value_mask & CWHeight)
68 +
			c->rect.height = ev->height;
69 +
		if(ev->value_mask & CWBorderWidth)
70 +
			c->border = ev->border_width;
71 +
72 +
		gravitate_client(c, False);
73 +
74 +
		if(c->frame) {
75 +
			if(c->sel->area->floating)
76 +
				frect=&c->sel->rect;
77 +
			else
78 +
				frect=&c->sel->revert;
79 +
80 +
			if(c->rect.width >= screen->rect.width && c->rect.height >= screen->rect.height) {
81 +
				frect->y = wc.y = -height_of_bar();
82 +
				frect->x = wc.x = -def.border;
83 +
			}
84 +
			else {
85 +
				frect->y = wc.y = c->rect.y - height_of_bar();
86 +
				frect->x = wc.x = c->rect.x - def.border;
87 +
			}
88 +
			frect->width = wc.width = c->rect.width + 2 * def.border;
89 +
			frect->height = wc.height = c->rect.height + def.border
90 +
				+ height_of_bar();
91 +
			wc.border_width = 1;
92 +
			wc.sibling = None;
93 +
			wc.stack_mode = ev->detail;
94 +
			if(c->sel->area->view != screen->sel)
95 +
				wc.x += 2 * screen->rect.width;
96 +
			if(c->sel->area->floating) {
97 +
				XConfigureWindow(dpy, c->framewin, ev->value_mask, &wc);
98 +
				configure_client(c);
99 +
			}
100 +
		}
101 +
	}
102 +
103 +
	wc.x = ev->x;
104 +
	wc.y = ev->y;
105 +
	wc.width = ev->width;
106 +
	wc.height = ev->height;
107 +
108 +
	if(c && c->frame) {
109 +
		wc.x = def.border;
110 +
		wc.y = height_of_bar();
111 +
		wc.width = c->sel->rect.width - 2 * def.border;
112 +
		wc.height = c->sel->rect.height - def.border - height_of_bar();
113 +
	}
114 +
115 +
	wc.border_width = 0;
116 +
	wc.sibling = None;
117 +
	wc.stack_mode = Above;
118 +
	ev->value_mask &= ~CWStackMode;
119 +
	ev->value_mask |= CWBorderWidth;
120 +
	XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
121 +
122 +
	XFlush(dpy);
123 +
#endif
124 +
}
125 +
126 +
static void
127 +
destroynotify(XEvent *e)
128 +
{
129 +
#if 0
130 +
	Client *c;
131 +
	XDestroyWindowEvent *ev = &e->xdestroywindow;
132 +
133 +
	if((c = client_of_win(ev->window)))
134 +
		destroy_client(c);
135 +
#endif
136 +
}
137 +
138 +
static void
139 +
enternotify(XEvent *e)
140 +
{
141 +
#if 0
142 +
	XCrossingEvent *ev = &e->xcrossing;
143 +
	Client *c;
144 +
145 +
	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
146 +
		return;
147 +
148 +
	if((c = client_of_win(ev->window))) {
149 +
		Frame *f = c->sel;
150 +
		Area *a = f->area;
151 +
		if(a->mode == Colmax)
152 +
			c = a->sel->client;
153 +
		focus(c, False);
154 +
	}
155 +
	else if(ev->window == root) {
156 +
		sel_screen = True;
157 +
		draw_frames();
158 +
	}
159 +
#endif
160 +
}
161 +
162 +
static void
163 +
leavenotify(XEvent *e)
164 +
{
165 +
	XCrossingEvent *ev = &e->xcrossing;
166 +
167 +
	if((ev->window == root) && !ev->same_screen) {
168 +
		sel_screen = True;
169 +
		/*draw_frames();*/
170 +
	}
171 +
}
172 +
173 +
static void
174 +
expose(XEvent *e)
175 +
{
176 +
	XExposeEvent *ev = &e->xexpose;
177 +
178 +
	if(ev->count == 0) {
179 +
		if(ev->window == barwin)
180 +
			draw_bar();
181 +
	}
182 +
}
183 +
184 +
static void
185 +
keypress(XEvent *e)
186 +
{
187 +
#if 0
188 +
	XKeyEvent *ev = &e->xkey;
189 +
	KeySym k = 0;
190 +
	char buf[32];
191 +
	int n;
192 +
	static Frame *f;
193 +
194 +
195 +
	ev->state &= valid_mask;
196 +
	if((f = frame_of_win(ev->window))) {
197 +
		buf[0] = 0;
198 +
		n = XLookupString(ev, buf, sizeof(buf), &k, 0);
199 +
		if(IsFunctionKey(k) || IsKeypadKey(k) || IsMiscFunctionKey(k)
200 +
				|| IsPFKey(k) || IsPrivateKeypadKey(k))
201 +
			return;
202 +
		buf[n] = 0;
203 +
		blitz_kpress_input(&f->tagbar, ev->state, k, buf);
204 +
	}
205 +
	else
206 +
		key(root, ev->state, (KeyCode) ev->keycode);
207 +
#endif
208 +
}
209 +
210 +
static void
211 +
keymapnotify(XEvent *e)
212 +
{
213 +
#if 0
214 +
	update_keys();
215 +
#endif
216 +
}
217 +
218 +
static void
219 +
maprequest(XEvent *e)
220 +
{
221 +
#if 0
222 +
	XMapRequestEvent *ev = &e->xmaprequest;
223 +
	static XWindowAttributes wa;
224 +
225 +
	if(!XGetWindowAttributes(dpy, ev->window, &wa))
226 +
		return;
227 +
228 +
	if(wa.override_redirect) {
229 +
		XSelectInput(dpy, ev->window,
230 +
				(StructureNotifyMask | PropertyChangeMask));
231 +
		return;
232 +
	}
233 +
234 +
	if(!client_of_win(ev->window))
235 +
		manage_client(create_client(ev->window, &wa));
236 +
#endif
237 +
}
238 +
239 +
static void
240 +
propertynotify(XEvent *e)
241 +
{
242 +
#if 0
243 +
	XPropertyEvent *ev = &e->xproperty;
244 +
	Client *c;
245 +
246 +
	if(ev->state == PropertyDelete)
247 +
		return; /* ignore */
248 +
249 +
	if((c = client_of_win(ev->window)))
250 +
		prop_client(c, ev);
251 +
#endif
252 +
}
253 +
254 +
static void
255 +
unmapnotify(XEvent *e)
256 +
{
257 +
#if 0
258 +
	Client *c;
259 +
	XUnmapEvent *ev = &e->xunmap;
260 +
261 +
	if((c = client_of_win(ev->window)))
262 +
		destroy_client(c);
263 +
#endif
264 +
}
menu.c +4 −5
53 53
54 54
static Brush brush = {0};
55 55
56 -
static void draw_menu(void);
56 +
static void draw_menu();
57 57
static void kpress(XKeyEvent * e);
58 58
59 59
static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
397 397
398 398
	wa.override_redirect = 1;
399 399
	wa.background_pixmap = ParentRelative;
400 -
	wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask
401 -
		| SubstructureRedirectMask | SubstructureNotifyMask;
400 +
	wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;
402 401
403 402
	rect.width = DisplayWidth(dpy, screen);
404 -
	rect.height = brush.font.height + 4;
403 +
	rect.height = labelheight(&brush.font);
405 404
	rect.y = DisplayHeight(dpy, screen) - rect.height;
406 405
	rect.x = 0;
407 406
413 412
	XFlush(dpy);
414 413
415 414
	/* pixmap */
416 -
	brush.gc = XCreateGC(dpy, win, 0, 0);
415 +
	brush.gc = XCreateGC(dpy, root, 0, 0);
417 416
	brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height,
418 417
			DefaultDepth(dpy, screen));
419 418
	XFlush(dpy);
util.c +23 −0
7 7
#include <stdio.h>
8 8
#include <stdlib.h>
9 9
#include <string.h>
10 +
#include <sys/types.h>
11 +
#include <sys/wait.h>
12 +
#include <unistd.h>
13 +
14 +
#include "util.h"
10 15
11 16
void
12 17
error(char *errstr, ...) {
75 80
	*p1 = *p2;
76 81
	*p2 = tmp;
77 82
}
83 +
84 +
void
85 +
spawn(Display *dpy, const char *shell, const char *cmd)
86 +
{
87 +
	if(!cmd || !shell)
88 +
		return;
89 +
	if(fork() == 0) {
90 +
		if(fork() == 0) {
91 +
			if(dpy)
92 +
				close(ConnectionNumber(dpy));
93 +
			execl(shell, shell, "-c", cmd, (const char *)0);
94 +
			fprintf(stderr, "gridwm: execl %s", shell);
95 +
			perror(" failed");
96 +
		}
97 +
		exit (0);
98 +
	}
99 +
	wait(0);
100 +
}
util.h +4 −2
2 2
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 3
 * See LICENSE file for license details.
4 4
 */
5 +
#include <X11/Xlib.h>
5 6
6 7
extern void error(char *errstr, ...);
7 8
extern void *emallocz(unsigned int size);
12 13
		if(!(a)) \
13 14
			failed_assert(#a, __FILE__, __LINE__); \
14 15
	} while (0)
15 -
void failed_assert(char *a, char *file, int line);
16 -
void swap(void **p1, void **p2);
16 +
extern void failed_assert(char *a, char *file, int line);
17 +
extern void swap(void **p1, void **p2);
18 +
extern void spawn(Display *dpy, const char *shell, const char *cmd);
wm.c +39 −12
15 15
16 16
/* X structs */
17 17
Display *dpy;
18 -
Window root;
19 -
XRectangle rect;
20 -
Pixmap pmap;
21 -
Atom wm_atom[WMLast];
22 -
Atom net_atom[NetLast];
18 +
Window root, barwin;
19 +
Atom wm_atom[WMLast], net_atom[NetLast];
23 20
Cursor cursor[CurLast];
21 +
XRectangle rect, barrect;
22 +
Bool running = True;
24 23
24 +
char *bartext, *shell;
25 25
int screen, sel_screen;
26 -
unsigned int kmask, numlock_mask;
26 +
unsigned int lock_mask, numlock_mask;
27 27
28 28
/* draw structs */
29 29
Brush brush = {0};
166 166
	}
167 167
	XFreeModifiermap(modmap);
168 168
169 -
	kmask = 255 & ~(numlock_mask | LockMask);
169 +
	lock_mask = 255 & ~(numlock_mask | LockMask);
170 170
}
171 171
172 172
static void
187 187
	XSetWindowAttributes wa;
188 188
	unsigned int mask;
189 189
	Window w;
190 +
	XEvent ev;
190 191
191 192
	/* command line args */
192 193
	for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
218 219
	if(other_wm_running)
219 220
		error("gridwm: another window manager is already running\n");
220 221
222 +
	if(!(shell = getenv("SHELL")))
223 +
		shell = "/bin/sh";
224 +
221 225
	rect.x = rect.y = 0;
222 226
	rect.width = DisplayWidth(dpy, screen);
223 227
	rect.height = DisplayHeight(dpy, screen);
244 248
245 249
	init_lock_keys();
246 250
247 -
	pmap = XCreatePixmap(dpy, root, rect.width, rect.height,
251 +
	brush.drawable = XCreatePixmap(dpy, root, rect.width, rect.height,
248 252
			DefaultDepth(dpy, screen));
253 +
	brush.gc = XCreateGC(dpy, root, 0, 0);
254 +
255 +
	/* style */
256 +
	loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
257 +
	loadfont(dpy, &brush.font, FONT);
258 +
259 +
	wa.override_redirect = 1;
260 +
	wa.background_pixmap = ParentRelative;
261 +
	wa.event_mask = ExposureMask;
262 +
263 +
	barrect = rect;
264 +
	barrect.height = labelheight(&brush.font);
265 +
	barrect.y = rect.height - barrect.height;
266 +
	barwin = XCreateWindow(dpy, root, barrect.x, barrect.y,
267 +
			barrect.width, barrect.height, 0, DefaultDepth(dpy, screen),
268 +
			CopyFromParent, DefaultVisual(dpy, screen),
269 +
			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
270 +
	bartext = 0;
271 +
	XDefineCursor(dpy, barwin, cursor[CurNormal]);
272 +
	XMapRaised(dpy, barwin);
273 +
	draw_bar();
249 274
250 275
	wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
251 276
	wa.cursor = cursor[CurNormal];
252 277
	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
253 278
254 -
	/* style */
255 -
	loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
256 -
	loadfont(dpy, &brush.font, FONT);
279 +
	scan_wins();
257 280
258 -
	scan_wins();
281 +
	while(running) {
282 +
		XNextEvent(dpy, &ev);
283 +
		if(handler[ev.type])
284 +
			(handler[ev.type]) (&ev); /* call handler */
285 +
	}
259 286
260 287
	cleanup();
261 288
	XCloseDisplay(dpy);
wm.h +24 −16
9 9
10 10
#include <X11/Xutil.h>
11 11
12 -
/* WM atoms */
12 +
/* atoms */
13 13
enum { WMState, WMProtocols, WMDelete, WMLast };
14 -
15 -
/* NET atoms */
16 14
enum { NetSupported, NetWMName, NetLast };
17 15
18 -
/* Cursor */
16 +
/* cursor */
19 17
enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
20 18
21 -
/* Rects */
19 +
/* rects */
22 20
enum { RFloat, RGrid, RLast };
23 21
24 22
typedef struct Client Client;
28 26
	Tag *tag;
29 27
	char name[256];
30 28
	int proto;
29 +
	unsigned int border;
30 +
	Bool fixedsize;
31 31
	Window win;
32 32
	Window trans;
33 33
	Window title;
34 -
	GC gc;
35 34
	XSizeHints size;
36 35
	XRectangle r[RLast];
37 36
	Client *next;
38 -
	Client *tnext;
39 -
	Client *tprev;
37 +
	Client *snext;
40 38
};
41 39
42 40
struct Tag {
43 41
	char name[256];
44 -
	Client *clients;
45 -
	Client *sel;
42 +
	Client *stack;
46 43
	XRectangle r;
44 +
	Tag *next;
45 +
	Tag *cnext;
47 46
};
48 47
49 48
extern Display *dpy;
50 -
extern Window root;
51 -
extern XRectangle rect;
52 -
extern Atom wm_atom[WMLast];
53 -
extern Atom net_atom[NetLast];
49 +
extern Window root, barwin;
50 +
extern Atom wm_atom[WMLast], net_atom[NetLast];
54 51
extern Cursor cursor[CurLast];
55 -
extern Pixmap pmap;
52 +
extern XRectangle rect, barrect;
53 +
extern Bool running;
54 +
extern void (*handler[LASTEvent]) (XEvent *);
56 55
57 56
extern int screen, sel_screen;
58 -
extern unsigned int kmask, numlock_mask;
57 +
extern unsigned int lock_mask, numlock_mask;
58 +
extern char *bartext, *shell;
59 59
60 60
extern Brush brush;
61 61
62 +
/* bar.c */
63 +
extern void draw_bar();
64 +
65 +
/* client.c */
66 +
extern Client *create_client(Window w, XWindowAttributes *wa);
67 +
extern void manage(Client *c);
68 +
62 69
/* wm.c */
70 +
extern int win_proto(Window w);