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