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