[comp.windows.x] uwm patches. This is shar file 1 of 3

jkh@COGSCI.BERKELEY.EDU (Jordan K. Hubbard) (12/13/87)

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# uwm.new/FocusChange.c uwm.new/TitleBar.c uwm.new/grey.b
#
# This is archive 1 of 3. Run this first! Also make sure you're in
# $(TOPDIR)/clients.
#
if [ -d uwm.new ]; then
	echo uwm.new already exists.. Maybe the patches are already applied..
	exit 0
fi
if [ -d uwm ]; then
	echo Making uwm.new directory...
	mkdir uwm.new
	echo Copying old uwm to it...
	cp uwm/* uwm.new
	echo Done.
	echo After the files have extracted, please apply the two patch kits.
	echo
else
	echo There doesn't appear to be a uwm directory here. Are we in
	echo the clients directory\?
	exit 0
fi
echo x - uwm.new/FocusChange.c
sed 's/^	//' > "uwm.new/FocusChange.c" << '//E*O*F uwm.new/FocusChange.c//'
	#ifndef lint
	static char *rcsid_FocusChange_c = "$Header: FocusChange.c,v 1.0 87/11/23 03:26:00 jkh Exp $";
	#endif	lint
	
	/*
	 * MODIFICATION HISTORY
	 *
	 * 002 -- Jordan Hubbard, U.C. Berkeley.
		Hacks for autoraise and titles.
	 */
	
	#include "uwm.h"
	#include "grey.b"
	
	#ifdef sun
	#include <sys/time.h>
	#else
	#include <time.h>
	#endif
	Pixmap greybordertile;
	
	/* get a grey pixmap for the border */
	Pixmap get_grey_pixmap()
	{
		Pixmap tmp;
	
		tmp = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), grey_bits,
		  grey_width, grey_height);
		if (!tmp) {
			fprintf(stderr, "uwm: Can't allocate grey pixmap for border!\n");
			exit(1);
		}
		return(tmp);
	}
	
	extern Bool Snatched;
	Bool Eventp();
	
	HandleFocusIn(ev)
	XEvent *ev;
	{
		XEnterWindowEvent *e = (XEnterWindowEvent *)ev;
		XEvent junk;
	
		if (e->mode == NotifyNormal && e->focus && (Hilite || Autoraise)) {
			struct timeval foo;
			Window w = e->window;
			TitleData *dat;
	
			if (!RaiseDelay)
				RaiseDelay = 200;
			foo.tv_sec = 0;
			foo.tv_usec = RaiseDelay * 1000; 
			/* If it's a titled window, we really want to pound on the frame */
			/*
			 * Sleep for awhile to avoid race conditions and give any potential
			 * leave events a chance to get here..
			 */
			select(0, 0, 0, 0, &foo);
			/* Did we leave this window already? */
			if (Eventp(w, LeaveNotify, False))
				return;
			if ((dat = GetTitleInfo(w)) != NULL)
				w = dat->parent;
			/* light the border */
			if (Hilite == True) {
				XSetWindowBorder(dpy, w, WhitePixel(dpy, DefaultScreen(dpy)));
				if (dat != NULL)
					PaintTitle(dat);
			}
			/*
			 * If Autoraise is set and we're not currently using a menu,
			 * raise that puppy..
			 */
			if (Autoraise == True && Snatched == False)
				XRaiseWindow(e->display, w);
			XSync(dpy, False);
		}
	}
	
	HandleFocusOut(ev)
	XEvent *ev;
	{
		XLeaveWindowEvent *e = (XEnterWindowEvent *)ev;
		TitleData *dat;
		Window w = e->window;
	
		if (e->mode == NotifyNormal && (Hilite || Autoraise)) {
			/* Did we come back into this window? */
			if (Eventp(w, EnterNotify, False))
				return;
			/* set the window to grey */
			if ((dat = GetTitleInfo(w)) != NULL)
				w = dat->parent;
			if (Hilite == True) {
				if (!greybordertile)
					greybordertile = get_grey_pixmap();
				XSetWindowBorderPixmap(dpy, w, greybordertile);
				if (dat != NULL)
					PaintTitle(dat, False);
			}
			XSync(dpy, False);
		}
	}
	
	/*
	 * Doesn't seem to be an event routine that does exactly what I want
	 * (find a given event without blocking or removing it from the queue),
	 * hence this cruft.. It also removes from the queue if desired and seems to
	 * work better than XCheckTypedWindowEvent too. so.. oh well..
	 */
	Bool Eventp(win, evt, removep)
	Window win;
	unsigned int evt; 
	Bool removep;
	{
		static struct evq {
			struct evq *prev;
			XEvent *an_event;
		} *head = 0, *ptr;
		Bool gotEvent = False;
	
		while (XPending(dpy) && gotEvent == False) {
			XEvent event;
	
			XNextEvent(dpy, &event);
			if (event.xany.window == win && event.xany.type == evt)
				gotEvent = True;
			if (!gotEvent || (gotEvent && !removep)) {
				if (!head) {
					head = (struct evq *)malloc(sizeof(struct evq));
					head->prev = 0;
				}
				else {
					ptr = (struct evq *)malloc(sizeof(struct evq));
					ptr->prev = head;
					head = ptr;
				}
				head->an_event = (XEvent *)malloc(sizeof(XEvent));
				bcopy(&event, head->an_event, sizeof(XEvent));
			}
		}
		while (head) {
			XPutBackEvent(dpy, head->an_event);
			free(head->an_event);
			free(head);
			head = head->prev;
		}
		return(gotEvent);
	}
//E*O*F uwm.new/FocusChange.c//

echo x - uwm.new/TitleBar.c
sed 's/^	//' > "uwm.new/TitleBar.c" << '//E*O*F uwm.new/TitleBar.c//'
	
	#ifndef lint
	static char *rcsid_TitleBar_c = "$Header: TitleBar.c,v 1.0 87/12/02 03:26:00 jkh Exp $";
	#endif	lint
	
	/*
	 * MODIFICATION HISTORY
	 *
	 * 002 -- Jordan Hubbard, U.C. Berkeley.
		Title bar support routines.
	 */
	
	#include "uwm.h"
	
	#include <X11/cursorfont.h>
	#include <X11/Xutil.h>
	#include <X11/Xatom.h>
	#include <stdio.h>
	
	#define PAD	2
	
	XContext Title_context;
	int Pad = PAD;
	int Fheight;
	static Bool init_done = False;
	Cursor TitleCursor;
	
	Init_Titles()
	{
		if (!TFontInfo) {
			TFontInfo = XLoadQueryFont(dpy, TFontName);
			if (TFontInfo == NULL) {
				fprintf(stderr, "uwm: Unable to open title font '%s', using server default.\n",
				  TFontInfo);
				TFontInfo = XQueryFont(dpy, DefaultGC(dpy, scr)->gid);
			}
		}
		if (strlen(TFontBoldName) > 0) {
			TFontBoldInfo = XLoadQueryFont(dpy, TFontBoldName);
			if (TFontBoldInfo == NULL)
				fprintf(stderr, "uwm: Can't open bold title font '%s', using reverse video.\n",
				  TFontBoldName);
		}
		if (!Fheight) {
		     Fheight = TFontInfo->max_bounds.ascent + TFontInfo->max_bounds.descent
			  + (Pad * 2);
		     if (TFontBoldInfo) {
			  int foo;
	
			  foo = TFontBoldInfo->max_bounds.ascent + TFontBoldInfo->max_bounds.descent + (Pad * 2);
			  if (foo > Fheight)
			       Fheight = foo;
		     }
		}
	
		if (!Title_context)
			Title_context = XUniqueContext();
		if (!TitleCursor) {
			TitleCursor = XCreateFontCursor(dpy, XC_left_ptr);
			if (!TitleCursor)
				Error("Init_Titles: Can't get XC_left_ptr cursor!\n");
		}
		init_done = True;
	}
	
	/* Function for f.title */
	FAddTitle(w, mask, button, x, y)
	Window w;
	int mask, button, x, y;
	{
	     TitleData *dat;
	
	     if (w == RootWindow(dpy, scr))
		  return(FALSE);
	     if ((dat = GetTitleInfo(w)) != NULL)
		  return(FALSE);
	     AddTitle(w, True);
	     return(TRUE);
	}
	
	char *GetTitleName(w)
	Window w;
	{
		char *cp, *tmp;
	
		if (!XFetchName(dpy, w, &cp))
			cp = "Untitled Window";
		tmp = (char *)malloc(strlen(cp) + 3);
	
		/*
		 * We add a space on both ends for asthetic effect
		 * (only apparent if we're using inverse video).
		 */
		tmp[0] = ' ';
		strcpy(tmp + 1, cp);
		strcat(tmp, " ");
		free(cp);
		return(tmp);
	}
	
	Window AddTitle(w, map)
	Window w;
	Bool map;
	{
		Window root;
		int x, y, width, height, bw, depth;
		XSetWindowAttributes swa;
		Window foster, title;
		TitleData *tinfo;
		char *icon_name, *cp;
		XWMHints *wm_hints;
		XSizeHints sz_hints;
		Binding *bptr;
	
		if (!init_done)
			Init_Titles();
		XAddToSaveSet(dpy, w);
	 	XGetGeometry(dpy, (Drawable)w, &root, &x, &y, &width, &height, &bw,
	      &depth);
		foster = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), x, y,
		  width, height + Fheight + 2, (bw ? bw : 1), MBorder, MBackground);
		if (!foster)
			Error("AddTitle: Can't create foster parent!");
		title = XCreateSimpleWindow(dpy, foster, 0, 0, width - 2, Fheight,
		  1, MBorder, MBackground);
		if (!title)
			Error("Title: Can't create title bar!");
		XSetWindowBorderWidth(dpy, w, 0);
		swa.bit_gravity = CenterGravity;
		XChangeWindowAttributes(dpy, title, CWBitGravity, &swa);
		XDefineCursor(dpy, title, TitleCursor);
		XSelectInput(dpy, title, ExposureMask);
		XMapWindow(dpy, title);
		XReparentWindow(dpy, w, foster, 0, Fheight + 2);
		XMapWindow(dpy, w);
		if (map)
			XMapWindow(dpy, foster);
		XSelectInput(dpy, foster, (SubstructureNotifyMask |
		  SubstructureRedirectMask));
		/* Grab on the title bar if necessary */
		for (bptr = Blist; bptr; bptr = bptr->next)
		     if (bptr->context == TITLE)
			  Grab(bptr->mask, title);
		tinfo = (TitleData *)malloc(sizeof(TitleData));
		tinfo->subwin = w;
		tinfo->title = title;
		tinfo->parent = foster;
		tinfo->border_width = bw;
		tinfo->name = GetTitleName(w);
		/* Make titlebar "frame" inherit characteristics of victim */
		XStoreName(dpy, foster, tinfo->name);
		XGetIconName(dpy, w, &icon_name);
		XSetIconName(dpy, foster, icon_name);
		free(icon_name);
		wm_hints = XGetWMHints(dpy, w);
		XSetWMHints(dpy, foster, wm_hints);
		XFree(wm_hints);
		XGetSizeHints(dpy, w, &sz_hints, XA_WM_NORMAL_HINTS);
		XSetSizeHints(dpy, foster, &sz_hints, XA_WM_NORMAL_HINTS);
		XSaveContext(dpy, title, Title_context, tinfo);
		XSaveContext(dpy, foster, Title_context, tinfo);
		XSaveContext(dpy, w, Title_context, tinfo);
		return(foster);
	}
	
	FDestroyTitle(w, mask, button, x, y)
	Window w;
	int mask, button, x, y;
	{
	     TitleData *dat;
	
	     if (w == RootWindow(dpy, scr))
		  return(FALSE);
	     if ((dat = GetTitleInfo(w)) == NULL)
		  return(FALSE);
	     DestroyTitle(dat, False);
	     return(TRUE);
	}
	
	DestroyTitle(t_data, mung)
	TitleData *t_data;
	Bool mung;
	{
		XWindowAttributes xwa;
	
		/* Either set it back the way it was or kill it */
		if (!mung) {
			if (XGetWindowAttributes(dpy, t_data->parent, &xwa) != BadWindow) {
				XSetWindowBorderWidth(dpy, t_data->subwin, t_data->border_width);
				/*
				 * I could just destroy the frame, like wm does, and let the
				 * saveset take care of it, but the window always seems to croak
				 * when I do that. If you remove this reparent, you lose. Bug?
				 */
				XReparentWindow(dpy, t_data->subwin, RootWindow(dpy, scr), xwa.x +
				  t_data->border_width, xwa.y + t_data->border_width);
				XRemoveFromSaveSet(dpy, t_data->subwin);
				XMapRaised(dpy, t_data->subwin);
			}
		}
		else
			XDestroyWindow(dpy, t_data->subwin);
		XDestroyWindow(dpy, t_data->parent);
		XDestroyWindow(dpy, t_data->title);
		free(t_data->name);
		free(t_data);
		XDeleteContext(dpy, t_data->parent, Title_context);
		XDeleteContext(dpy, t_data->title, Title_context);
		XDeleteContext(dpy, t_data->subwin, Title_context);
		XSync(dpy, False);
	}
	
	PaintTitle(t_data)
	TitleData *t_data;
	{
		static GC gc, rgc;
		int x, y, ijunk;
		XWindowAttributes xwa;
		Window junk, chld;
		Bool reversed;
	
		XGetWindowAttributes(dpy, t_data->title, &xwa);
		XQueryPointer(dpy, t_data->parent, &junk, &chld, &ijunk, &ijunk,
		  &ijunk, &ijunk, &ijunk);
		reversed = (chld == t_data->subwin);
		if (!gc) {
			XGCValues gcv;
	
			gcv.font = TFontInfo->fid;
			gcv.foreground = MTextForground;
			gcv.background = MTextBackground;
			gc = XCreateGC(dpy, t_data->title, (GCFont | GCForeground |
							    GCBackground), &gcv);
			/* Now create the gc for reverse video text (if we have no bold font) */
			if (TFontBoldInfo == NULL) {
				gcv.foreground = MTextBackground;
				gcv.background = MTextForground;
				rgc = XCreateGC(dpy, t_data->title, (GCFont | GCForeground |
								     GCBackground), &gcv);
			}
			else {
				gcv.font = TFontBoldInfo->fid;
				rgc = XCreateGC(dpy, t_data->title, (GCFont | GCForeground |
								     GCBackground), &gcv);
			}
		}
		x = (xwa.width - XTextWidth(TFontInfo, t_data->name,
		  strlen(t_data->name))) / 2;
		y = TFontInfo->max_bounds.ascent + Pad;
		XClearWindow(dpy, t_data->title);
		  XDrawImageString(dpy, t_data->title, (reversed ? rgc : gc), x, y,
				   t_data->name, strlen(t_data->name));
	}
	
	ConfigureTitle(t_data, x, y, width, height)
	TitleData *t_data;
	unsigned int x, y, width, height;
	{
		XWindowAttributes xwa;
	
		XGetWindowAttributes(dpy, t_data->parent, &xwa);
		if (xwa.height == height + Fheight && xwa.width == width &&
		  xwa.x == x && xwa.y == y)
			return;
	
		XResizeWindow(dpy, t_data->subwin, width, height);
		XResizeWindow(dpy, t_data->title, width, Fheight);
		XMoveResizeWindow(dpy, t_data->parent, x, y, width, height + Fheight + 2);
	}
	
	TitleData *GetTitleInfo(w)
	Window w;
	{
		TitleData *stuff;
	
		if (XFindContext(dpy, w, Title_context, &stuff))
			return((TitleData *)NULL);
		else
			return(stuff);
	}
//E*O*F uwm.new/TitleBar.c//

echo x - uwm.new/grey.b
sed 's/^	//' > "uwm.new/grey.b" << '//E*O*F uwm.new/grey.b//'
	/* @(#)grey.c */
	#define grey_width 16
	#define grey_height 16
	static char grey_bits[] = {
	   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
	   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
	   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
	   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
//E*O*F uwm.new/grey.b//

exit 0