jkh@ardent.UUCP (Jordan K. Hubbard) (06/16/88)
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 11 (of 17)."
# Contents: awm/GetButton.c
# Wrapped by jkh@ardent on Thu Jun 16 00:44:19 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'awm/GetButton.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'awm/GetButton.c'\"
else
echo shar: Extracting \"'awm/GetButton.c'\" \(20345 characters\)
sed "s/^X//" >'awm/GetButton.c' <<'END_OF_FILE'
X#ident "%W% %G%"
X
X#ifndef lint
static char *rcsid_GetButton_c = "$Header: GetButton.c,v 1.1 88/06/15 15:20:45 jjkh Exp $";
X#endif lint
X
X#include "X11/copyright.h"
X/*
X *
X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
X *
X * Copyright 1987 by Jordan Hubbard.
X *
X *
X * All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Ardent Computer
X * Corporation or Jordan Hubbard not be used in advertising or publicity
X * pertaining to distribution of the software without specific, written
X * prior permission.
X *
X */
X
X/*
X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
X *
X * All Rights Reserved
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of Digital Equipment
X * Corporation not be used in advertising or publicity pertaining to
X * distribution of the software without specific, written prior permission.
X *
X *
X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
X * SOFTWARE.
X */
X
X
X
X/*
X * MODIFICATION HISTORY
X *
X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
X * 001 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab
X * February 16, 1987
X * Add EnterWindow, LeaveWindow, and MouseMotion as recognized
X * awm buttons for awm menus. Add bug fixes to prevent mem faults
X * if icon_str is NULL.
X * 002 -- L. Guarino Reid, DEC Ultrix Engineering Group
X * April 16, 1987
X * Convert to X11
X * 003 -- J. Hubbard, U.C. Berkeley. Title/gadget box event handling.
X * December 3, 1987.
X * 004 -- J.Hubbard, Ardent Computer. More conformance with ICCCM. Merge of
X * changes from R2 uwm.
X */
X
X#ifndef lint
static char *sccsid = "@(#)GetButton.c 3.8 1/24/86";
X#endif
X/*
X * GetButton - This subroutine is used by the Ardent Window Manager (awm)
X * to acquire button events. It waits for a button event to occur
X * and handles all event traffic in the interim.
X *
X * File: GetButton.c
X */
X
X#include "awm.h"
X#include "X11/Xutil.h"
X
extern XContext AwmContext;
X
X#define ICONSTR (icon_str ? icon_str : "")
X/* Amount of padding between text in a title bar and the edge of the bar */
X#define PAD 1
X
static Icon_modified = FALSE;
X
Boolean GetButton(b_ev)
XXEvent *b_ev; /* Button event packet. */
X{
X#define STRLEN 50
X XKeyPressedEvent *kp_event; /* Key pressed event. */
X char *icon_str; /* Icon's name string. */
X register int icon_str_len; /* Icon name string lenght. */
X register int key_char; /* Key press character code. */
X register int icon_x; /* Icon window X coordinate. */
X register int icon_y; /* Icon window Y coordinate. */
X register int icon_w; /* Icon window width. */
X register int icon_h; /* Icon window height. */
X int status; /* Routine call return status. */
X Window icon; /* Icon window. */
X Window appl; /* Application window. */
X XWindowAttributes win_info; /* Icon window info structure. */
X char kbd_str[STRLEN]; /* Keyboard string. */
X int nbytes; /* Keyboard string length. */
X int i; /* Iteration counter. */
X Window win; /* scratch */
X AwmInfoPtr awi;
X
X Entry("GetButton")
X
X /*
X * Get next event from input queue and store it in the event packet
X * passed to GetButton.
X */
X
X XNextEvent(dpy, b_ev);
X /* print_event_info("mainloop", b_ev); /* debugging for event handling */
X
X /*
X * The event occured on the root window, check for substructure
X * changes. Otherwise, it must be a mouse button event.
X */
X win = b_ev->xany.window;
X
X if (win == RootWindow(dpy, scr)) {
X switch (b_ev->xany.type) {
X case CreateNotify:
X case UnmapNotify:
X case ReparentNotify:
X case ConfigureNotify:
X case GravityNotify:
X case MapNotify:
X case CirculateNotify:
X Leave(FALSE)
X
X case MappingNotify:
X XRefreshKeyboardMapping(b_ev);
X Leave(FALSE)
X
X case MapRequest:
X CheckMap(b_ev->xmap.window);
X Leave(FALSE)
X
X case ConfigureRequest:
X Configure((XConfigureEvent *)b_ev);
X Leave(FALSE)
X
X case CirculateRequest:
X Circulate((XCirculateEvent *)b_ev);
X Leave(FALSE)
X
X case DestroyNotify:
X RemoveIcon(b_ev->xdestroywindow.window);
X Leave(FALSE)
X
X case FocusIn:
X if (b_ev->xfocus.detail == NotifyPointerRoot) {
X if (FocusSetByUser) {
X XSetInputFocus(dpy, PointerRoot, None,
X CurrentTime);
X FocusSetByUser = FALSE;
X }
X }
X Leave(FALSE)
X
X case FocusOut:
X if (b_ev->xfocus.detail == NotifyPointerRoot) {
X if (FocusSetByUser == FALSE)
X XSetInputFocus(dpy, PointerRoot, None,
X CurrentTime);
X }
X Leave(FALSE)
X
X case ButtonPress:
X case ButtonRelease:
X Leave(TRUE)
X
X default:
X fprintf(stderr, "awm: Got weird event #%d on root window\n",
X b_ev->xany.type);
X Leave(FALSE)
X }
X }
X
X /*
X * If the event type is EnterWindow, LeaveWindow, or MouseMoved,
X * we are processing a menu.
X * If the event type is ButtonPress or ButtonRelease,
X * we have a button event.
X * If it's an expose, then we may have exposed a title bar.
X * If it's a Notify, we've probably frobbed a titled window.
X */
X
X awi = GetAwmInfo(win);
X switch (b_ev->type) {
X
X case MotionNotify:
X case ButtonPress:
X case ButtonRelease:
X Leave(TRUE)
X
X case EnterNotify:
X HandleFocusIn(b_ev);
X Leave(FALSE)
X
X case LeaveNotify:
X HandleFocusOut(b_ev);
X Leave(FALSE)
X
X case ConfigureRequest:
X Configure((XConfigureEvent *)b_ev);
X Leave(FALSE)
X
X case MapRequest:
X CheckMap(b_ev->xmap.window);
X Leave(FALSE);
X
X case MapNotify:
X if (!awi)
X Leave(FALSE)
X if (IsIcon(win, FALSE))
X Leave(FALSE)
X if (awi->frame)
X XMapWindow(dpy, awi->frame);
X else
X XMapWindow(dpy, awi->client);
X Leave(FALSE)
X break;
X
X case UnmapNotify:
X if (!awi)
X Leave(FALSE)
X if (IsIcon(win, FALSE))
X Leave(FALSE)
X if (awi->frame)
X XUnmapWindow(dpy, awi->frame);
X else
X XUnmapWindow(dpy, awi->client);
X Leave(FALSE)
X break;
X
X case DestroyNotify:
X if (!awi)
X Leave(FALSE)
X /* remove any icon associated with this window */
X RemoveIcon(win);
X /* remove the frame/titlebar (if present) */
X DestroyTitle(win);
X /* punt the rest of the per-window info */
X XDeleteContext(dpy, awi->client, AwmContext);
X free(awi);
X Leave(FALSE)
X
X case PropertyNotify:
X if (!awi)
X Leave(FALSE)
X switch(b_ev->xproperty.atom) {
X
X case XA_WM_COMMAND:
X case XA_WM_HINTS:
X case XA_WM_CLIENT_MACHINE:
X break;
X
X case XA_WM_ICON_NAME:
X /*
X * Icon was modified by type-in (I still think that's a
X * gross feature, but some people like it... sigh),
X * ignore this event.
X */
X if (Icon_modified == TRUE) {
X Icon_modified = FALSE; /* reset */
X Leave(FALSE)
X }
X if (awi->icon && awi->own && awi->iconPixmap == IBackPixmap) {
X win = awi->icon;
X status = XGetWindowAttributes(dpy, win, &win_info);
X icon_str = GetIconName(awi->client);
X icon_str_len = icon_str ? strlen(icon_str) : 0;
X if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
X strlen(ICONSTR)) +
X (HIconPad << 1)) {
X XResizeWindow(dpy, win,
X XTextWidth(IFontInfo, ICONSTR,
X strlen(ICONSTR)) +
X (HIconPad << 1), IFontInfo->ascent +
X IFontInfo->descent + (VIconPad << 1));
X }
X XClearWindow(dpy, win);
X if (icon_str_len != 0) {
X XDrawImageString(dpy, win, IconGC, HIconPad,
X VIconPad+IFontInfo->ascent, icon_str,
X icon_str_len);
X free(icon_str);
X }
X }
X break;
X
X case XA_WM_ICON_SIZE:
X break;
X
X case XA_WM_NAME:
X if (awi->title) {
X if (awi->name)
X free(awi->name);
X awi->name = (char *)GetTitleName(win);
X PaintTitle(win);
X }
X break;
X
X case XA_WM_NORMAL_HINTS:
X case XA_WM_SIZE_HINTS:
X case XA_WM_ZOOM_HINTS:
X break;
X
X default:
X fprintf(stderr, "awm: Got unknown property %d\n",
X b_ev->xproperty.atom);
X }
X Leave(FALSE)
X break;
X
X
X case Expose:
X if (!awi) /* probably a menu */
X Leave(FALSE)
X if (awi->title == win) {
X if (b_ev->xexpose.count == 0) {
X XEvent evt;
X
X while (XCheckTypedWindowEvent(dpy, awi->title, Expose, &evt));
X PaintTitle(win);
X if (awi->gadgets)
X PaintGadgets(win);
X }
X Leave(FALSE)
X }
X break;
X
X default:
X break;
X }
X
X /*
X * If we got this far, the event must be for an icon.
X */
X
X if (!awi)
X Leave(FALSE)
X status = XGetWindowAttributes(dpy, win, &win_info);
X if (status == FAILURE)
X Leave(FALSE)
X
X if (b_ev->type == MapNotify ||
X b_ev->type == UnmapNotify ||
X b_ev->type == CreateNotify ||
X b_ev->type == ReparentNotify ||
X b_ev->type == GravityNotify ||
X b_ev->type == CirculateNotify ||
X b_ev->type == ConfigureNotify)
X Leave(FALSE)
X
X /*
X * Initialize the icon position variables.
X */
X icon_x = win_info.x;
X icon_y = win_info.y;
X
X /*
X * Get the name of the window associated with the icon and
X * determine its length.
X */
X if (!awi->icon)
X Leave(FALSE)
X /*
X * If we don't own it, or it's got a background pixmap, we don't have
X * to repaint it.
X */
X if (!awi->own || (awi->iconPixmap != IBackPixmap))
X Leave(FALSE)
X icon = awi->icon;
X icon_str = GetIconName(awi->client);
X icon_str_len = icon_str ? strlen(icon_str) : 0;
X
X /*
X * If the event is a window exposure event and the icon's name string
X * is not of zero length, simply repaint the text in the icon window
X * and return FALSE.
X */
X if (b_ev->type == Expose && (!Freeze || Frozen == 0)) {
X if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
X strlen(ICONSTR))+(HIconPad << 1)) {
X XResizeWindow(dpy, icon,
X XTextWidth(IFontInfo, ICONSTR,
X strlen(ICONSTR)) + (HIconPad << 1),
X IFontInfo->ascent + IFontInfo->descent +
X (VIconPad << 1));
X }
X XClearWindow(dpy, icon);
X if (icon_str_len != 0) {
X XDrawImageString(dpy, icon,
X IconGC, HIconPad, VIconPad+IFontInfo->ascent,
X icon_str, icon_str_len);
X /*
X * Remember to free the icon name string.
X */
X free(icon_str);
X }
X Leave(FALSE)
X }
X
X#ifndef NO_ICON_TYPIN
X /*
X * If we have gotten this far event can only be a key pressed event.
X */
X kp_event = (XKeyPressedEvent *) b_ev;
X
X /*
X * We convert the key pressed event to ascii.
X */
X nbytes = XLookupString(kp_event, kbd_str, STRLEN, NULL);
X
X /*
X * If kbd_str is a "non-string", then don't do anything.
X */
X if (nbytes == 0) {
X if (icon_str)
X free(icon_str);
X Leave(FALSE)
X }
X for (i = 0; i < nbytes; i++) {
X key_char = kbd_str[i];
X /*
X * If the key was <DELETE>, then delete a character from the end of
X * the name, return FALSE.
X *
X * If the key was <CTRL-U>, then wipe out the entire window name
X * and return FALSE.
X *
X * All other ctrl keys are squashed and we return FALSE.
X *
X * All printable characters are appended to the window's name, which
X * may have to be grown to allow for the extra length.
X */
X if (key_char == '\177') {
X /*
X * <DELETE>
X */
X if (icon_str_len > 0) {
X icon_str_len--;
X icon_str[icon_str_len] = '\0';
X }
X }
X else if (key_char == '\025') {
X /*
X * <CTRL-U>
X */
X if (icon_str_len > 0) {
X icon_str_len = 0;
X icon_str[0] = '\0';
X }
X }
X else if (key_char < IFontInfo->min_char_or_byte2 ||
X key_char > IFontInfo->max_char_or_byte2) {
X /*
X * Any other random (non-printable) key; ignore it.
X */
X /* do nothing */ ;
X }
X else {
X /*
X * ASCII Alphanumerics.
X */
X if (icon_str == NULL)
X icon_str = (char *) malloc (icon_str_len + 2);
X else
X icon_str = (char *)realloc(icon_str, (icon_str_len + 2));
X if (icon_str == NULL) {
X errno = ENOMEM;
X Error("GetButton -> Realloc of window name string memory failed.");
X }
X icon_str[icon_str_len] = key_char;
X icon_str[icon_str_len + 1] = '\0';
X icon_str_len += 1;
X }
X }
X
X /*
X * Now that we have changed the size of the icon we have to reconfigure
X * it so that everything looks good. Oh yes, don't forget to move the
X * mouse so that it stays in the window!
X */
X
X /*
X * Set the window name to the new string. Icon_modified is a kludge
X * that tells us to avoid the next PropertyNotify, as it's a result of
X * this call.
X */
X XSetIconName(dpy, awi->client, ICONSTR);
X Icon_modified = TRUE;
X /*
X * Determine the new icon window configuration.
X */
X icon_h = IFontInfo->ascent + IFontInfo->descent + (VIconPad << 1);
X icon_w = XTextWidth(IFontInfo, ICONSTR, strlen(ICONSTR));
X if (icon_w == 0) {
X icon_w = icon_h;
X }
X else {
X icon_w += (HIconPad << 1);
X }
X
X if (icon_x < 0) icon_x = 0;
X if (icon_y < 0) icon_y = 0;
X if (icon_x - 1 + icon_w + (IBorderWidth << 1) > ScreenWidth) {
X icon_x = ScreenWidth - icon_w - (IBorderWidth << 1) + 1;
X }
X if (icon_y - 1 + icon_h + (IBorderWidth << 1) > ScreenHeight) {
X icon_y = ScreenHeight - icon_h - (IBorderWidth << 1) + 1;
X }
X
X XMoveResizeWindow(dpy, icon, icon_x, icon_y, icon_w, icon_h);
X XWarpPointer(dpy, None, icon,
X 0, 0, 0, 0, (icon_w >> 1), (icon_h >> 1));
X
X /*
X * Free the local storage and return FALSE.
X */
X if (icon_str)
X free(icon_str);
X#endif
X Leave(FALSE)
X}
X
CheckMap(window)
Window window;
X{
X XWMHints *XGetWMHints();
X XWMHints *wmhints;
X int x, y, w, h;
X Window transient_for;
X Window jW;
X int border_width, j;
X Binding *bptr;
X AwmInfoPtr awi;
X unsigned long event_mask;
X
X Entry("CheckMap")
X
X /* if it's a transient window, we won't rubber-band
X * note that this call always sets transient_for.
X */
X if (!XGetTransientForHint( dpy, window, &transient_for )) {
X /*
X * Handle any registered grabs for this window. We do this here
X * because we may be about to make an icon out of this window
X * and we want to register any potential grabs on it before this
X * happens.
X */
X awi = GetAwmInfo(window);
X if (!awi) {
X for (bptr = Blist; bptr; bptr = bptr->next)
X if (bptr->context & WINDOW)
X Grab(bptr->mask, window);
X awi = RegisterWindow(window);
X if (Titles) {
X AddTitle(window);
X if (UseGadgets)
X PutGadgets(window);
X }
X event_mask = PropertyChangeMask;
X if (!awi->frame || !FrameFocus)
X event_mask |= (EnterWindowMask | LeaveWindowMask);
X XSelectInput(dpy, window, event_mask);
X SetBorderPixmaps(dpy, GrayPixmap);
X }
X if ((wmhints = XGetWMHints(dpy, window))) {
X if ((wmhints->flags & StateHint) && (awi->state == WINDOW) &&
X (wmhints->initial_state == IconicState)) {
X /* window wants to be created as an icon. Leave size
X /* and position alone, create as icon. */
X XFree(wmhints);
X Iconify(window, 0, 0, 0, 0);
X Leave_void
X }
X XFree(wmhints);
X }
X }
X else
X if ((awi = GetAwmInfo(window)) == NULL)
X awi = RegisterWindow(window);
X if (awi->state == WINDOW) {
X PlaceWindow(window);
X if (awi->frame) {
X XMapRaised(dpy, awi->frame);
X XMapWindow(dpy, awi->client);
X }
X else
X XMapRaised(dpy, awi->client);
X }
X Leave_void
X}
X
Configure(event)
XXConfigureRequestEvent *event;
X{
X XWindowChanges values;
X AwmInfoPtr awi;
X
X Entry("Configure")
X
X values.x = event->x;
X values.y = event->y;
X values.width = event->width;
X values.height = event->height;
X values.border_width = event->border_width;
X values.stack_mode = event->detail;
X values.sibling = event->above;
X
X ConfigureWindow(event->window, event->value_mask, &values);
X Leave_void
X}
X
Circulate(event)
XXCirculateEvent *event;
X{
X Entry("Circulate")
X
X if (event->place == PlaceOnTop)
X XRaiseWindow(event->display, event->window);
X else
X XLowerWindow(event->display, event->window);
X Leave_void
X}
X
PlaceWindow(window)
Window window;
X{
X XSizeHints wsh;
X int x, y, w, h;
X Boolean configureit = False;
X XWindowChanges xwc;
X AwmInfoPtr awi;
X long flags;
X
X wsh.flags = 0;
X flags = CWX | CWY | CWWidth | CWHeight;
X awi = GetAwmInfo(window);
X XGetSizeHints(dpy, window, &wsh, XA_WM_NORMAL_HINTS);
X CheckConsistency(&wsh);
X AskUser(dpy, scr, window, &x, &y, &w, &h, &wsh);
X
X wsh.flags |= (USPosition | USSize);
X wsh.x = x;
X wsh.y = y;
X wsh.width = w;
X wsh.height = h;
X if (x < 0 || y < 0) {
X Window jW;
X int j, border_width;
X
X XGetGeometry(dpy, window, &jW, &j, &j, &j, &j, &border_width, &j);
X
X if (x < 0)
X x += DisplayWidth(dpy, scr) - w - (border_width<<1);
X if (y < 0)
X y += DisplayHeight(dpy, scr) - h - (border_width<<1);
X }
X if (IsTitled(window))
X XSetSizeHints(dpy, awi->frame, &wsh, XA_WM_NORMAL_HINTS);
X XSetSizeHints(dpy, awi->client, &wsh, XA_WM_NORMAL_HINTS);
X#ifdef titan /* 5x4 alignment */
X x += (x % 5);
X y += (y % 4);
X#endif
X xwc.x = x;
X xwc.y = y;
X xwc.height = h;
X xwc.width = w;
X ConfigureWindow(window, flags, &xwc);
X awi->placed = TRUE;
X}
X
Boolean ConfigureWindow(w, mask, xwc)
Window w;
unsigned long mask;
XXWindowChanges *xwc;
X{
X XWindowAttributes xwa;
X AwmInfoPtr awi;
X Boolean compensate = TRUE;
X
X Entry("ConfigureWindow")
X
X awi = GetAwmInfo(w);
X if (!awi)
X Leave(FALSE)
X if (w == awi->frame)
X compensate = FALSE;
X
X if (awi->frame) {
X if (compensate)
X xwc->width += (BContext ? (BContext * 2) + 2 : 0);
X XResizeWindow(dpy, awi->title, xwc->width, titleHeight);
X if (compensate)
X xwc->height += (titleHeight + 2 +
X (BContext ? BContext + 1 : 0));
X if (TitlePush == FALSE && compensate) {
X xwc->y -= (titleHeight + 2);
X if (xwc->y < 0)
X xwc->y = 0;
X }
X XConfigureWindow(dpy, awi->frame, mask, xwc);
X xwc->height -= (titleHeight + 2 + (BContext ? BContext + 1 : 0));
X xwc->width -= (BContext ? ((BContext * 2) + 2) : 0);
X xwc->y = titleHeight + 2;
X if (BContext)
X xwc->x = BContext;
X else
X xwc->x = 0;
X if (awi->gadgets)
X PutGadgets(w);
X }
X XConfigureWindow(dpy, awi->client, mask, xwc);
X Leave(TRUE)
X}
X
int
ProcessRequests(box, num_vectors)
XXSegment *box;
int num_vectors;
X{
X XEvent event;
X
X XPeekEvent(dpy, &event);
X switch (event.type) {
X
X case MapRequest:
X case ConfigureRequest:
X case CirculateRequest:
X
X DrawBox();
X GetButton(&event);
X DrawBox();
X return TRUE;
X }
X return FALSE;
X}
END_OF_FILE
if test 20345 -ne `wc -c <'awm/GetButton.c'`; then
echo shar: \"'awm/GetButton.c'\" unpacked with wrong size!
fi
# end of 'awm/GetButton.c'
fi
echo shar: End of archive 11 \(of 17\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 17 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0