Browse Source

added several other stuff

Anselm R. Garbe 20 năm trước cách đây
mục cha
commit
439e15d09f
12 tập tin đã thay đổi với 476 bổ sung và 39 xóa
  1. 2 2
      Makefile
  2. 18 0
      bar.c
  3. 89 0
      client.c
  4. 2 2
      config.h
  5. 6 0
      draw.c
  6. 1 0
      draw.h
  7. 264 0
      event.c
  8. 4 5
      menu.c
  9. 23 0
      util.c
  10. 4 2
      util.h
  11. 39 12
      wm.c
  12. 24 16
      wm.h

+ 2 - 2
Makefile

@@ -3,11 +3,11 @@
 
 include config.mk
 
-WMSRC = wm.c draw.c util.c
+WMSRC = bar.c client.c draw.c event.c util.c wm.c
 WMOBJ = ${WMSRC:.c=.o}
 MENSRC = menu.c draw.c util.c
 MENOBJ = ${MENSRC:.c=.o}
-MAN = gridwm.1
+MAN1 = gridwm.1 gridmenu.1
 BIN = gridwm gridmenu     
 
 all: config gridwm gridmenu

+ 18 - 0
bar.c

@@ -0,0 +1,18 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include "wm.h"
+
+void
+draw_bar()
+{
+	brush.rect = barrect;
+	brush.rect.x = brush.rect.y = 0;
+	draw(dpy, &brush, False, 0);
+
+	XCopyArea(dpy, brush.drawable, barwin, brush.gc, 0, 0, barrect.width,
+			barrect.height, 0, 0);
+	XFlush(dpy);
+}

+ 89 - 0
client.c

@@ -0,0 +1,89 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <string.h>
+#include <X11/Xatom.h>
+
+#include "util.h"
+#include "wm.h"
+
+static void
+update_client_name(Client *c)
+{
+	XTextProperty name;
+	int n;
+	char **list = 0;
+
+	name.nitems = 0;
+	c->name[0] = 0;
+	XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
+	if(!name.nitems)
+		XGetWMName(dpy, c->win, &name);
+	if(!name.nitems)
+		return;
+	if(name.encoding == XA_STRING)
+		strncpy(c->name, (char *)name.value, sizeof(c->name));
+	else {
+		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
+				&& n > 0 && *list)
+		{
+			strncpy(c->name, *list, sizeof(c->name));
+			XFreeStringList(list);
+		}
+	}
+	XFree(name.value);
+}
+
+Client *
+create_client(Window w, XWindowAttributes *wa)
+{
+	Client *c;
+	XSetWindowAttributes twa;
+	long msize;
+
+	c = emallocz(sizeof(Client));
+	c->win = w;
+	c->r[RFloat].x = wa->x;
+	c->r[RFloat].y = wa->y;
+	c->r[RFloat].width = wa->width;
+	c->r[RFloat].height = wa->height;
+	c->border = wa->border_width;
+	XSetWindowBorderWidth(dpy, c->win, 0);
+	c->proto = win_proto(c->win);
+	XGetTransientForHint(dpy, c->win, &c->trans);
+	if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags)
+		c->size.flags = PSize;
+	c->fixedsize =
+		(c->size.flags & PMinSize && c->size.flags & PMaxSize
+		 && c->size.min_width == c->size.max_width
+		 && c->size.min_height == c->size.max_height);
+	XAddToSaveSet(dpy, c->win);
+	update_client_name(c);
+	twa.override_redirect = 1;
+	twa.background_pixmap = ParentRelative;
+	twa.event_mask = ExposureMask;
+
+	c->title = XCreateWindow(dpy, root, c->r[RFloat].x, c->r[RFloat].y,
+			c->r[RFloat].width, barrect.height, 0,
+			DefaultDepth(dpy, screen), CopyFromParent,
+			DefaultVisual(dpy, screen),
+			CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
+	XFlush(dpy);
+
+#if 0
+	for(t=&client, i=0; *t; t=&(*t)->next, i++);
+	c->next = *t; /* *t == nil */
+	*t = c;
+#endif
+	return c;
+}
+
+void
+manage(Client *c)
+{
+	XMapRaised(dpy, c->win);
+	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
+	XFlush(dpy);
+}

+ 2 - 2
config.h

@@ -4,6 +4,6 @@
  */
 
 #define FONT		"-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*"
-#define FGCOLOR		"#000000"
-#define BGCOLOR		"#ffaa00"
+#define BGCOLOR		"#000000"
+#define FGCOLOR		"#ffaa00"
 #define BORDERCOLOR	"#000000"

+ 6 - 0
draw.c

@@ -162,3 +162,9 @@ loadfont(Display *dpy, Fnt *font, const char *fontstr)
 	}
 	font->height = font->ascent + font->descent;
 }
+
+unsigned int
+labelheight(Fnt *font)
+{
+	return font->height + 4;
+}

+ 1 - 0
draw.h

@@ -33,3 +33,4 @@ extern void loadcolors(Display *dpy, int screen, Brush *b,
 extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
 extern unsigned int textwidth_l(Fnt *font, char *text, unsigned int len);
 extern unsigned int textwidth(Fnt *font, char *text);
+extern unsigned int labelheight(Fnt *font);

+ 264 - 0
event.c

@@ -0,0 +1,264 @@
+/*
+ * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/keysym.h>
+
+#include "wm.h"
+
+/* local functions */
+static void configurerequest(XEvent *e);
+static void destroynotify(XEvent *e);
+static void enternotify(XEvent *e);
+static void leavenotify(XEvent *e);
+static void expose(XEvent *e);
+static void keypress(XEvent *e);
+static void keymapnotify(XEvent *e);
+static void maprequest(XEvent *e);
+static void propertynotify(XEvent *e);
+static void unmapnotify(XEvent *e);
+
+void (*handler[LASTEvent]) (XEvent *) = {
+	[ConfigureRequest] = configurerequest,
+	[DestroyNotify] = destroynotify,
+	[EnterNotify] = enternotify,
+	[LeaveNotify] = leavenotify,
+	[Expose] = expose,
+	[KeyPress] = keypress,
+	[KeymapNotify] = keymapnotify,
+	[MapRequest] = maprequest,
+	[PropertyNotify] = propertynotify,
+	[UnmapNotify] = unmapnotify
+};
+
+unsigned int
+flush_masked_events(long even_mask)
+{
+	XEvent ev;
+	unsigned int n = 0;
+	while(XCheckMaskEvent(dpy, even_mask, &ev)) n++;
+	return n;
+}
+
+static void
+configurerequest(XEvent *e)
+{
+#if 0
+	XConfigureRequestEvent *ev = &e->xconfigurerequest;
+	XWindowChanges wc;
+	XRectangle *frect;
+	Client *c;
+
+	c = client_of_win(ev->window);
+	ev->value_mask &= ~CWSibling;
+	if(c) {
+		gravitate_client(c, True);
+
+		if(ev->value_mask & CWX)
+			c->rect.x = ev->x;
+		if(ev->value_mask & CWY)
+			c->rect.y = ev->y;
+		if(ev->value_mask & CWWidth)
+			c->rect.width = ev->width;
+		if(ev->value_mask & CWHeight)
+			c->rect.height = ev->height;
+		if(ev->value_mask & CWBorderWidth)
+			c->border = ev->border_width;
+
+		gravitate_client(c, False);
+
+		if(c->frame) {
+			if(c->sel->area->floating)
+				frect=&c->sel->rect;
+			else
+				frect=&c->sel->revert;
+
+			if(c->rect.width >= screen->rect.width && c->rect.height >= screen->rect.height) {
+				frect->y = wc.y = -height_of_bar();
+				frect->x = wc.x = -def.border;
+			}
+			else {
+				frect->y = wc.y = c->rect.y - height_of_bar();
+				frect->x = wc.x = c->rect.x - def.border;
+			}
+			frect->width = wc.width = c->rect.width + 2 * def.border;
+			frect->height = wc.height = c->rect.height + def.border
+				+ height_of_bar();
+			wc.border_width = 1;
+			wc.sibling = None;
+			wc.stack_mode = ev->detail;
+			if(c->sel->area->view != screen->sel)
+				wc.x += 2 * screen->rect.width;
+			if(c->sel->area->floating) {
+				XConfigureWindow(dpy, c->framewin, ev->value_mask, &wc);
+				configure_client(c);
+			}
+		}
+	}
+
+	wc.x = ev->x;
+	wc.y = ev->y;
+	wc.width = ev->width;
+	wc.height = ev->height;
+
+	if(c && c->frame) {
+		wc.x = def.border;
+		wc.y = height_of_bar();
+		wc.width = c->sel->rect.width - 2 * def.border;
+		wc.height = c->sel->rect.height - def.border - height_of_bar();
+	}
+
+	wc.border_width = 0;
+	wc.sibling = None;
+	wc.stack_mode = Above;
+	ev->value_mask &= ~CWStackMode;
+	ev->value_mask |= CWBorderWidth;
+	XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
+
+	XFlush(dpy);
+#endif
+}
+
+static void
+destroynotify(XEvent *e)
+{
+#if 0
+	Client *c;
+	XDestroyWindowEvent *ev = &e->xdestroywindow;
+
+	if((c = client_of_win(ev->window)))
+		destroy_client(c);
+#endif
+}
+
+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);
+	}
+	else if(ev->window == root) {
+		sel_screen = True;
+		draw_frames();
+	}
+#endif
+}
+
+static void
+leavenotify(XEvent *e)
+{
+	XCrossingEvent *ev = &e->xcrossing;
+
+	if((ev->window == root) && !ev->same_screen) {
+		sel_screen = True;
+		/*draw_frames();*/
+	}
+}
+
+static void
+expose(XEvent *e)
+{
+	XExposeEvent *ev = &e->xexpose;
+
+	if(ev->count == 0) {
+		if(ev->window == barwin)
+			draw_bar();
+	}
+}
+
+static void
+keypress(XEvent *e)
+{
+#if 0
+	XKeyEvent *ev = &e->xkey;
+	KeySym k = 0;
+	char buf[32];
+	int n;
+	static Frame *f;
+
+
+	ev->state &= valid_mask;
+	if((f = frame_of_win(ev->window))) {
+		buf[0] = 0;
+		n = XLookupString(ev, buf, sizeof(buf), &k, 0);
+		if(IsFunctionKey(k) || IsKeypadKey(k) || IsMiscFunctionKey(k)
+				|| IsPFKey(k) || IsPrivateKeypadKey(k))
+			return;
+		buf[n] = 0;
+		blitz_kpress_input(&f->tagbar, ev->state, k, buf);
+	}
+	else
+		key(root, ev->state, (KeyCode) ev->keycode);
+#endif
+}
+
+static void
+keymapnotify(XEvent *e)
+{
+#if 0
+	update_keys();
+#endif
+}
+
+static void
+maprequest(XEvent *e)
+{
+#if 0
+	XMapRequestEvent *ev = &e->xmaprequest;
+	static XWindowAttributes wa;
+
+	if(!XGetWindowAttributes(dpy, ev->window, &wa))
+		return;
+
+	if(wa.override_redirect) {
+		XSelectInput(dpy, ev->window,
+				(StructureNotifyMask | PropertyChangeMask));
+		return;
+	}
+
+	if(!client_of_win(ev->window))
+		manage_client(create_client(ev->window, &wa));
+#endif
+}
+
+static void
+propertynotify(XEvent *e)
+{
+#if 0
+	XPropertyEvent *ev = &e->xproperty;
+	Client *c;
+
+	if(ev->state == PropertyDelete)
+		return; /* ignore */
+
+	if((c = client_of_win(ev->window)))
+		prop_client(c, ev);
+#endif
+}
+
+static void
+unmapnotify(XEvent *e)
+{
+#if 0
+	Client *c;
+	XUnmapEvent *ev = &e->xunmap;
+
+	if((c = client_of_win(ev->window)))
+		destroy_client(c);
+#endif
+}

+ 4 - 5
menu.c

@@ -53,7 +53,7 @@ static const int seek = 30;		/* 30px */
 
 static Brush brush = {0};
 
-static void draw_menu(void);
+static void draw_menu();
 static void kpress(XKeyEvent * e);
 
 static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
@@ -397,11 +397,10 @@ main(int argc, char *argv[])
 
 	wa.override_redirect = 1;
 	wa.background_pixmap = ParentRelative;
-	wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask
-		| SubstructureRedirectMask | SubstructureNotifyMask;
+	wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;
 
 	rect.width = DisplayWidth(dpy, screen);
-	rect.height = brush.font.height + 4;
+	rect.height = labelheight(&brush.font);
 	rect.y = DisplayHeight(dpy, screen) - rect.height;
 	rect.x = 0;
 
@@ -413,7 +412,7 @@ main(int argc, char *argv[])
 	XFlush(dpy);
 
 	/* pixmap */
-	brush.gc = XCreateGC(dpy, win, 0, 0);
+	brush.gc = XCreateGC(dpy, root, 0, 0);
 	brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height,
 			DefaultDepth(dpy, screen));
 	XFlush(dpy);

+ 23 - 0
util.c

@@ -7,6 +7,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "util.h"
 
 void
 error(char *errstr, ...) {
@@ -75,3 +80,21 @@ swap(void **p1, void **p2)
 	*p1 = *p2;
 	*p2 = tmp;
 }
+
+void
+spawn(Display *dpy, const char *shell, const char *cmd)
+{
+	if(!cmd || !shell)
+		return;
+	if(fork() == 0) {
+		if(fork() == 0) {
+			if(dpy)
+				close(ConnectionNumber(dpy));
+			execl(shell, shell, "-c", cmd, (const char *)0);
+			fprintf(stderr, "gridwm: execl %s", shell);
+			perror(" failed");
+		}
+		exit (0);
+	}
+	wait(0);
+}

+ 4 - 2
util.h

@@ -2,6 +2,7 @@
  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
  * See LICENSE file for license details.
  */
+#include <X11/Xlib.h>
 
 extern void error(char *errstr, ...);
 extern void *emallocz(unsigned int size);
@@ -12,5 +13,6 @@ extern char *estrdup(const char *str);
 		if(!(a)) \
 			failed_assert(#a, __FILE__, __LINE__); \
 	} while (0)
-void failed_assert(char *a, char *file, int line);
-void swap(void **p1, void **p2);
+extern void failed_assert(char *a, char *file, int line);
+extern void swap(void **p1, void **p2);
+extern void spawn(Display *dpy, const char *shell, const char *cmd);

+ 39 - 12
wm.c

@@ -15,15 +15,15 @@
 
 /* X structs */
 Display *dpy;
-Window root;
-XRectangle rect;
-Pixmap pmap;
-Atom wm_atom[WMLast];
-Atom net_atom[NetLast];
+Window root, barwin;
+Atom wm_atom[WMLast], net_atom[NetLast];
 Cursor cursor[CurLast];
+XRectangle rect, barrect;
+Bool running = True;
 
+char *bartext, *shell;
 int screen, sel_screen;
-unsigned int kmask, numlock_mask;
+unsigned int lock_mask, numlock_mask;
 
 /* draw structs */
 Brush brush = {0};
@@ -166,7 +166,7 @@ init_lock_keys()
 	}
 	XFreeModifiermap(modmap);
 
-	kmask = 255 & ~(numlock_mask | LockMask);
+	lock_mask = 255 & ~(numlock_mask | LockMask);
 }
 
 static void
@@ -187,6 +187,7 @@ main(int argc, char *argv[])
 	XSetWindowAttributes wa;
 	unsigned int mask;
 	Window w;
+	XEvent ev;
 
 	/* command line args */
 	for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
@@ -218,6 +219,9 @@ main(int argc, char *argv[])
 	if(other_wm_running)
 		error("gridwm: another window manager is already running\n");
 
+	if(!(shell = getenv("SHELL")))
+		shell = "/bin/sh";
+
 	rect.x = rect.y = 0;
 	rect.width = DisplayWidth(dpy, screen);
 	rect.height = DisplayHeight(dpy, screen);
@@ -244,19 +248,42 @@ main(int argc, char *argv[])
 
 	init_lock_keys();
 
-	pmap = XCreatePixmap(dpy, root, rect.width, rect.height,
+	brush.drawable = 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);
+	brush.gc = XCreateGC(dpy, root, 0, 0);
 
 	/* style */
 	loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
 	loadfont(dpy, &brush.font, FONT);
 
+	wa.override_redirect = 1;
+	wa.background_pixmap = ParentRelative;
+	wa.event_mask = ExposureMask;
+
+	barrect = rect;
+	barrect.height = labelheight(&brush.font);
+	barrect.y = rect.height - barrect.height;
+	barwin = XCreateWindow(dpy, root, barrect.x, barrect.y,
+			barrect.width, barrect.height, 0, DefaultDepth(dpy, screen),
+			CopyFromParent, DefaultVisual(dpy, screen),
+			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+	bartext = 0;
+	XDefineCursor(dpy, barwin, cursor[CurNormal]);
+	XMapRaised(dpy, barwin);
+	draw_bar();
+
+	wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
+	wa.cursor = cursor[CurNormal];
+	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
+
 	scan_wins();
 
+	while(running) {
+		XNextEvent(dpy, &ev);
+		if(handler[ev.type])
+			(handler[ev.type]) (&ev); /* call handler */
+	}
+
 	cleanup();
 	XCloseDisplay(dpy);
 

+ 24 - 16
wm.h

@@ -9,16 +9,14 @@
 
 #include <X11/Xutil.h>
 
-/* WM atoms */
+/* atoms */
 enum { WMState, WMProtocols, WMDelete, WMLast };
-
-/* NET atoms */
 enum { NetSupported, NetWMName, NetLast };
 
-/* Cursor */
+/* cursor */
 enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
 
-/* Rects */
+/* rects */
 enum { RFloat, RGrid, RLast };
 
 typedef struct Client Client;
@@ -28,35 +26,45 @@ struct Client {
 	Tag *tag;
 	char name[256];
 	int proto;
+	unsigned int border;
+	Bool fixedsize;
 	Window win;
 	Window trans;
 	Window title;
-	GC gc;
 	XSizeHints size;
 	XRectangle r[RLast];
 	Client *next;
-	Client *tnext;
-	Client *tprev;
+	Client *snext;
 };
 
 struct Tag {
 	char name[256];
-	Client *clients;
-	Client *sel;
+	Client *stack;
 	XRectangle r;
+	Tag *next;
+	Tag *cnext;
 };
 
 extern Display *dpy;
-extern Window root;
-extern XRectangle rect;
-extern Atom wm_atom[WMLast];
-extern Atom net_atom[NetLast];
+extern Window root, barwin;
+extern Atom wm_atom[WMLast], net_atom[NetLast];
 extern Cursor cursor[CurLast];
-extern Pixmap pmap;
+extern XRectangle rect, barrect;
+extern Bool running;
+extern void (*handler[LASTEvent]) (XEvent *);
 
 extern int screen, sel_screen;
-extern unsigned int kmask, numlock_mask;
+extern unsigned int lock_mask, numlock_mask;
+extern char *bartext, *shell;
 
 extern Brush brush;
 
+/* bar.c */
+extern void draw_bar();
+
+/* client.c */
+extern Client *create_client(Window w, XWindowAttributes *wa);
+extern void manage(Client *c);
+
 /* wm.c */
+extern int win_proto(Window w);