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