v12i059: olvwm - Open Look Virtual Window Manager, Part03/16

Scott Oaks - Sun Consulting NYC sdo at soliado.East.Sun.COM
Mon Apr 29 03:29:08 AEST 1991


Submitted-by: sdo at soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
Posting-number: Volume 12, Issue 59
Archive-name: olvwm/part03

#! /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 3 (of 16)."
# Contents:  Error.c olvwm.man win.c winbutton.c winpush.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:03 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Error.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Error.c'\"
else
echo shar: Extracting \"'Error.c'\" \(9113 characters\)
sed "s/^X//" >'Error.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
X *      file for terms of the license.
X *
X *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char sccsid[] = "@(#)Error.c	1.2 olvwm version 3/30/91";
X/*
X * Based on
static	char	sccsid[] = "@(#) Error.c 25.4 90/05/30 Crucible";
X */
X
X#include <stdio.h>
X#include <X11/Xproto.h>
X#include <X11/Xlib.h>
X
X/* globals */
X
X/* locals */
static char	*hyperSensitive = NULL;
X
X#define NXOPCODES	128	/* # of X opcodes */
typedef struct {
X	unsigned int fatal, warning, ignore;
X} ErrorEntry;
X
X/* The following defines create bitmasks from the X Error Codes */
X#define BReq	(1<<BadRequest)
X#define BVal	(1<<BadValue)
X#define BWin	(1<<BadWindow)
X#define BPix	(1<<BadPixmap)
X#define BAtm	(1<<BadAtom)
X#define BCur	(1<<BadCursor)
X#define BFnt	(1<<BadFont)
X#define BMch	(1<<BadMatch)
X#define BDrw	(1<<BadDrawable)
X#define BAcc	(1<<BadAccess)
X#define BAlc	(1<<BadAlloc)
X#define BCol	(1<<BadColor)
X#define BGC	(1<<BadGC)
X#define BIDC	(1<<BadIDChoice)
X#define BNam	(1<<BadName)
X#define BLen	(1<<BadLength)
X#define BImp	(1<<BadImplementation)
X
X#define BAll	(~0)	/* matches all error bitmasks */
X
X/* This error table encodes the severity of an error in relation to
X * an X primitive. For instance if BadWindow was fatal for
X * a certain primitive but BadColor was not, the following entry would be used:
X *	{BWin,	BCol,	0}
X */
static ErrorEntry errorTable[NXOPCODES] = {
X	{BAll,	0,	0},	/* 0, Not Used */
X	{BAll,	0,	0},	/* 1, X_CreateWindow */
X	{0,	~BWin,	BWin},	/* 2, X_ChangeWindowAttributes */
X	{0,	~BWin,	BWin},	/* 3, X_GetWindowAttributes */
X	{0,	BAll,	0},	/* 4, X_DestroyWindow */
X	{0,	BAll,	0},	/* 5, X_DestroySubwindows */
X	{0,	~BWin,	BWin},	/* 6, X_ChangeSaveSet */
X	{0,	~BWin,	BWin},	/* 7, X_ReparentWindow */
X	{0,	BAll,	0},	/* 8, X_MapWindow */
X	{0,	BAll,	0},	/* 9, X_MapSubwindows */
X	{0,	~BWin,	BWin},	/* 10, X_UnmapWindow */
X	{0,	BAll,	0},	/* 11, X_UnmapSubwindows */
X	{0,	~BWin,	BWin},	/* 12, X_ConfigureWindow */
X	{0,	BAll,	0},	/* 13, X_CirculateWindow */
X	{0,	BAll,	0},	/* 14, X_GetGeometry */
X	{0,	~BWin,	BWin},	/* 15, X_QueryTree */
X	{0,	BAll,	0},	/* 16, X_InternAtom */
X	{0,	BAll,	0},	/* 17, X_GetAtomName */
X	{0,	~BWin,	BWin},	/* 18, X_ChangeProperty */
X	{0,	BAll,	0},	/* 19, X_DeleteProperty */
X	{0,	~BWin,	BWin},	/* 20, X_GetProperty */
X	{0,	BAll,	0},	/* 21, X_ListProperties */
X	{0,	BAll,	0},	/* 22, X_SetSelectionOwner */
X	{0,	BAll,	0},	/* 23, X_GetSelectionOwner */
X	{0,	BAll,	0},	/* 24, X_ConvertSelection */
X	{0,	~BWin,	BWin},	/* 25, X_SendEvent */
X	{0,	0,	BAll},	/* 26, X_GrabPointer */
X	{0,	0,	BAll},	/* 27, X_UngrabPointer */
X	{0,	0,	BAll},	/* 28, X_GrabButton */
X	{0,	0,	BAll},	/* 29, X_UngrabButton */
X	{0,	0,	BAll},	/* 30, X_ChangeActivePointerGrab */
X	{0,	BAll,	0},	/* 31, X_GrabKeyboard */
X	{0,	BAll,	0},	/* 32, X_UngrabKeyboard */
X	{0,	BAll,	0},	/* 33, X_GrabKey */
X	{0,	BAll,	0},	/* 34, X_UngrabKey */
X	{0,	BAll,	0},	/* 35, X_AllowEvents */
X	{BAll,	0,	0},	/* 36, X_GrabServer */
X	{0,	BAll,	0},	/* 37, X_UngrabServer */
X	{0,	BAll,	0},	/* 38, X_QueryPointer */
X	{0,	BAll,	0},	/* 39, X_GetMotionEvents */
X	{0,	BAll,	0},	/* 40, X_TranslateCoords */
X	{0,	BAll,	0},	/* 41, X_WarpPointer */
X	{0,	~(BMch|BWin),	BMch|BWin},	/* 42, X_SetInputFocus */
X	{0,	BAll,	0},	/* 43, X_GetInputFocus */
X	{0,	BAll,	0},	/* 44, X_QueryKeymap */
X	{0,	BAll,	0},	/* 45, X_OpenFont */
X	{0,	BAll,	0},	/* 46, X_CloseFont */
X	{0,	BAll,	0},	/* 47, X_QueryFont */
X	{0,	BAll,	0},	/* 48, X_QueryTextExtents */
X	{0,	BAll,	0},	/* 49, X_ListFonts */
X	{0,	BAll,	0},	/* 50, X_ListFontsWithInfo */
X	{0,	BAll,	0},	/* 51, X_SetFontPath */
X	{0,	BAll,	0},	/* 52, X_GetFontPath */
X	{0,	BAll,	0},	/* 53, X_CreatePixmap */
X	{0,	BAll,	0},	/* 54, X_FreePixmap */
X	{0,	BAll,	0},	/* 55, X_CreateGC */
X	{0,	BAll,	0},	/* 56, X_ChangeGC */
X	{0,	BAll,	0},	/* 57, X_CopyGC */
X	{0,	BAll,	0},	/* 58, X_SetDashes */
X	{0,	BAll,	0},	/* 59, X_SetClipRectangles */
X	{0,	BAll,	0},	/* 60, X_FreeGC */
X	{0,	~BMch,	BMch},	/* 61, X_ClearArea */
X	{0,	BAll,	0},	/* 62, X_CopyArea */
X	{0,	BAll,	0},	/* 63, X_CopyPlane */
X	{0,	BAll,	0},	/* 64, X_PolyPoint */
X	{0,	BAll,	0},	/* 65, X_PolyLine */
X	{0,	BAll,	0},	/* 66, X_PolySegment */
X	{0,	BAll,	0},	/* 67, X_PolyRectangle */
X	{0,	BAll,	0},	/* 68, X_PolyArc */
X	{0,	BAll,	0},	/* 69, X_FillPoly */
X	{0,	BAll,	0},	/* 70, X_PolyFillRectangle */
X	{0,	BAll,	0},	/* 71, X_PolyFillArc */
X	{0,	BAll,	0},	/* 72, X_PutImage */
X	{0,	BAll,	0},	/* 73, X_GetImage */
X	{0,	BAll,	0},	/* 74, X_PolyText8 */
X	{0,	BAll,	0},	/* 75, X_PolyText16 */
X	{0,	BAll,	0},	/* 76, X_ImageText8 */
X	{0,	BAll,	0},	/* 77, X_ImageText16 */
X	{0,	BAll,	0},	/* 78, X_CreateColormap */
X	{0,	BAll,	0},	/* 79, X_FreeColormap */
X	{0,	BAll,	0},	/* 80, X_CopyColormapAndFree */
X	{0,	BAll,	0},	/* 81, X_InstallColormap */
X	{0,	BAll,	0},	/* 82, X_UninstallColormap */
X	{0,	BAll,	0},	/* 83, X_ListInstalledColormaps */
X	{0,	BAll,	0},	/* 84, X_AllocColor */
X	{0,	BAll,	0},	/* 85, X_AllocNamedColor */
X	{0,	BAll,	0},	/* 86, X_AllocColorCells */
X	{0,	BAll,	0},	/* 87, X_AllocColorPlanes */
X	{0,	BAll,	0},	/* 88, X_FreeColors */
X	{0,	BAll,	0},	/* 89, X_StoreColors */
X	{0,	BAll,	0},	/* 90, X_StoreNamedColor */
X	{0,	BAll,	0},	/* 91, X_QueryColors */
X	{0,	BAll,	0},	/* 92, X_LookupColor */
X	{0,	BAll,	0},	/* 93, X_CreateCursor */
X	{0,	BAll,	0},	/* 94, X_CreateGlyphCursor */
X	{0,	BAll,	0},	/* 95, X_FreeCursor */
X	{0,	BAll,	0},	/* 96, X_RecolorCursor */
X	{0,	BAll,	0},	/* 97, X_QueryBestSize */
X	{0,	BAll,	0},	/* 98, X_QueryExtension */
X	{0,	BAll,	0},	/* 99, X_ListExtensions */
X	{0,	BAll,	0},	/* 100, X_ChangeKeyboardMapping */
X	{0,	BAll,	0},	/* 101, X_GetKeyboardMapping */
X	{0,	BAll,	0},	/* 102, X_ChangeKeyboardControl */
X	{0,	BAll,	0},	/* 103, X_GetKeyboardControl */
X	{0,	BAll,	0},	/* 104, X_Bell */
X	{0,	BAll,	0},	/* 105, X_ChangePointerControl */
X	{0,	BAll,	0},	/* 106, X_GetPointerControl */
X	{0,	BAll,	0},	/* 107, X_SetScreenSaver */
X	{0,	BAll,	0},	/* 108, X_GetScreenSaver */
X	{0,	BAll,	0},	/* 109, X_ChangeHosts */
X	{0,	BAll,	0},	/* 110, X_ListHosts */
X	{0,	BAll,	0},	/* 111, X_SetAccessControl */
X	{0,	BAll,	0},	/* 112, X_SetCloseDownMode */
X	{0,	BAll,	0},	/* 113, X_KillClient */
X	{0,	BAll,	0},	/* 114, X_RotateProperties */
X	{0,	BAll,	0},	/* 115, X_ForceScreenSaver */
X	{0,	BAll,	0},	/* 116, X_SetPointerMapping */
X	{0,	BAll,	0},	/* 117, X_GetPointerMapping */
X	{0,	BAll,	0},	/* 118, X_SetModifierMapping */
X	{0,	BAll,	0},	/* 119, X_GetModifierMapping */
X	{BAll,	0,	0},	/* 120, Not Used */
X	{BAll,	0,	0},	/* 121, Not Used */
X	{BAll,	0,	0},	/* 122, Not Used */
X	{BAll,	0,	0},	/* 123, Not Used */
X	{BAll,	0,	0},	/* 124, Not Used */
X	{BAll,	0,	0},	/* 125, Not Used */
X	{BAll,	0,	0},	/* 126, Not Used */
X	{0,	BAll,	0},	/* 127, X_NoOperation */
X	};
X/*
X * ErrorSensitive -- cause an exit on all X errors
X */
XErrorSensitive(s)
char	*s;
X{
X	hyperSensitive = s;
X}
X
X/*
X * ErrorInsensitive -- perform normal X error processing
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
XErrorInsensitive(dpy)
Display	*dpy;
X{
X	hyperSensitive = NULL;
X}
X
X/*
X * ErrorHandler -- this routine is called whenever an error in the X
X *	protocol is detected.
X */
XErrorHandler(dpy, event)
Display	*dpy;
XXErrorEvent	*event;
X{
X	char	buffer[BUFSIZ];
X	int	errBitmask;
X
X	XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
X
X	if (hyperSensitive != NULL)
X	{
X		/* treat all errors as fatal */
X		(void) fprintf(stderr, "olvwm: Fatal X Error: %s\n", buffer);
X		(void) fprintf(stderr, "%s\n", hyperSensitive);
X		exit(-1);
X		/*NOTREACHED*/
X	}
X
X	errBitmask = 1 << event->error_code;
X
X	if (errBitmask & errorTable[event->request_code].ignore)
X		return 0;
X	else if (errBitmask & errorTable[event->request_code].warning)
X	{
X		(void) fprintf(stderr, "olvwm: Warning, X Error: %s\n", buffer);
X		(void) fprintf(stderr, "  Request Major code: %d\n",
X				event->request_code);
X		(void) fprintf(stderr, "  Request Minor code: %d\n",
X				event->minor_code);
X		(void) fprintf(stderr, "  ResourceId 0x%x\n",
X				event->resourceid);
X
X		return 0;
X	}
X	else if (errBitmask & errorTable[event->request_code].fatal)
X	{
X		(void) fprintf(stderr, "olvwm: Fatal X Error: %s\n", buffer);
X		(void) fprintf(stderr, "  Request Major code: %d\n",
X				event->request_code);
X		(void) fprintf(stderr, "  Request Minor code: %d\n",
X				event->minor_code);
X		(void) fprintf(stderr, "  ResourceId 0x%x\n",
X				event->resourceid);
X		(void) fprintf(stderr, "  Error Serial #%d\n", event->serial);
X		(void) fprintf(stderr, "  Current Serial #%d\n", dpy->request);
X
X		/* do not return from fatal errors */
X		exit(-1);
X		/*NOTREACHED*/
X	}
X
X	return 0;
X}
X
X/*
X * ErrorGeneral -- this routine is called whenever a general error occurs
X *      within OLWM.  Exits from olwm.
X */
void
XErrorGeneral(txt)
char *txt;
X{
X        (void) fprintf(stderr,"olvwm: Fatal Error: %s\n", txt);
X#ifdef DEBUG
X	abort();
X#else
X        exit(-1);
X#endif
X}
X
X/*
X * ErrorWarning -- this routine is called whenever a condition requiring
X *      a warning message occurs within OLWM.
X */
void
XErrorWarning(txt)
char *txt;
X{
X        (void) fprintf(stderr,"olvwm: Warning: %s\n", txt);
X}
X
END_OF_FILE
if test 9113 -ne `wc -c <'Error.c'`; then
    echo shar: \"'Error.c'\" unpacked with wrong size!
fi
# end of 'Error.c'
fi
if test -f 'olvwm.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'olvwm.man'\"
else
echo shar: Extracting \"'olvwm.man'\" \(10814 characters\)
sed "s/^X//" >'olvwm.man' <<'END_OF_FILE'
X.\" @(#)olvwm.1	1.3 olvwm version 4/17/91
X.TH OLVWM 1 "31 March 1991"
X.SH NAME
olvwm \- OPEN LOOK virtual window manager for OpenWindows
X.SH SYNOPSIS
X.B olvwm
X[
X.B \-2d
X] [
X.B \-3d
X] [
X.B \-c
X] [
X.B \-click
X] [
X.B \-f
X] [
X.B \-follow
X] [
X.B \-parent
X]
X.br
X[
X.B \-display
X.I displaystring
X] [
X.B \-fn
X.I fontname
X] [
X.B \-font
X.I fontname
X] [
X.B \-name
X.I rsrcname
X] [
X.B \-xrm
X.I rsrcstring
X]
X.br
X[
X.B \-all
X] [
X.B \-debug
X] [
X.B \-orphans
X] [
X.B \-synchronize
X]
X.\" ========================================================================
X.SH DESCRIPTION
X.LP
X.B olvwm
is a virtual window manager for the X Window System that implements
parts of the OPEN LOOK graphical user interface.
X.B olvwm
differs from 
X.B olwm
in that olvwm manages a virtual desktop which is larger than the actual
screen.  However, 
X.B olvwm
is equivalent in all other respects to 
X.B olwm
X[though
X.B olvwm breaks
parts of the OPEN LOOK user interface that
X.B olwm
respects.]
This manual page discusses only the interface for the virtual desktop;
for all other information, see the
X.B olwm
manual page.
X.LP
When it is started,
X.B olvwm
displays a virtual desktop manager (VDM) window along with any other tools
normally started in your .xinitrc file.  The virtual desktop manager
is a reduced display of all windows active on the desktop at any
time.  The area of the desktop which is visible (that is, which appears
on your screen) is outlined in the virtual desktop manager.
X.LP
This window manager also includes David Plotkin's auto-pinned root menu
resources.
X.SH MOVING WINDOWS
X.LP
You move windows on the screen just as you normally would in
X.B olwm.
You can also drag windows from the screen into the virtual desktop manager
or from the virtual desktop manager to the screen, or just within the
virtual desktop manager.  Note that if you select on a window's frame
which is overlapping the virtual desktop manager you will end up dragging
the window into the virtual desktop manager.  You can set the
AllowMoveIntoDesktop resource to false if you are bothered by this
behaviour.
X.SH MANIPULATING THE VIRTUAL DESKTOP
X.LP
If you select a window inside the virtual desktop manager, you can move
the window.  If, however, you select the background area of the virtual
desktop manager within the viewing rectangle, you can move the viewing
rectangle of the desktop.  When you release the mouse button, the
desktop will shift and you will now see the windows within the
virtual desktop manager's viewing rectangle.
X.LP
You can also use the arrow keys to move the viewing rectangle and affect
your view.  If the virtual desktop manager has the keyboard focus,
simply press the right arrow to move your view into the desktop to
the right, etc.  If your set the allowArrowInRoot resource to true (which,
in fact, is it's default value), then arrows keys will work when the
root window has the keyboard focus as well.
X.LP
You can use the arrow keys when the virtual desktop manager has been
iconified (though you must keep track mentally of where on the desktop
you are).
X.SH RESIZING THE VIRTUAL DESKTOP
X.LP
You can use the resize corners on the virtual desktop manager to resize
the virtual desktop at will.  If you make the virtual desktop smaller,
windows which might be off the new virtual desktop will NOT be moved
X(though they will not be lost, either, and you can get them back by
resizing the desktop again).  Note that after a resize the virtual desktop
will be shifted to the upper-left hand corner of the virtual desktop
manager; this means that if you pick the left-hand corner of the VDM
and make it larger, you'll get extra desktop area on the righthand side
of the virtual desktop.
X.SH STICKY WINDOWS
X.LP
You'll notice that the virtual desktop manager never moves on your
screen if you change views.  That's because the desktop manager is
permanently "sticky."
X.LP
Windows which are "sticky" never move position on the screen when you
change your view into the desktop.  To set a particular window as
sticky, simply select "Stick" in it's frame menu. You may similarly
unstick the window via it's menu.
X.LP
X[Note:  Only
base frames are eligible to become sticky; frames inherit the stickyness
of their base frames.  Thus, for a particular application, either
all windows are sticky or none of them are.  The exception to this is
that base frames created after a base frame is set to be "sticky" are created
as unsticky.  For most OPEN LOOK applications, this affects only pin-up
menus; you should pin any menus you want to be sticky BEFORE you set
the base frame to be sticky.]
X.LP
Windows are sticky by default it their class name (set via the WM_CLASS)
property is in the list of strings for VirtualSticky (see RESOURCES below)
X.SH PLACING WINDOWS
X.LP
If you specify a window placement directly (via -Wp arguments or
XX11 geometry screens), the window will appear at that location on
the virtual desktop (even if that location is not currently visible).
X.LP
If you do not specify a window position, then
X.B olvwm
will place it somewhere on your visible screen using similar window/icon
placement rules as
X.B olwm.
X.\" ========================================================================
X.SH WINDOW MENU
X.LP
The window menu of most windows has all the tools defined in
X.B olwm.
In addition, the menu of base windows has the following command
X.TP
X.B Stick/Unstick
Affect the stickyness of the particular window.  Windows which are sticky
will always appear in the same place on the screen no matter which part
of the virtual desktop you're looking at.  Windows which are not sticky
X(by default, all windows) will move when you change the view on the virtual
desktop.
X.\" ========================================================================
X.SH RESOURCES
See the man page for
X.B olwm
for a complete description of resources.  All resources of class OpenWindows
described there are supported by
X.B olvwm.
In addition, for
X.B olvwm
only, resources of instance "olvwm" are also read.
You can thus name the following resources as olvwm.<resource> or
as OpenWindows.<resource> depending on your naming preference.
X.TP
X.BI VirtualDesktop " (string)"
Specifies the size of the virtual desktop.  You can specify this in
terms of screen sizes, so that a virtual desktop of 3 screens across
and 2 screens high would appear as the string "3x2".  You may also
specify this in terms of absolute pixel sizes, e.g. "3800x1800" as
long as the pixel size is greater than the size of your framebuffer.
X.I
Default value: "3x2"
X.P
X.TP
X.BI PannerScale " (int)"
Sets the scale in which the virtual desktop manager will be drawn.
X.I
Default value: 15.
X.P
X.TP
X.BI VirtualGeometry " (string)"
Specifies the geometry string of the desktop manager in standard X11
format (wxh+x+y).  The width and height, if specified, are ignored,
but the x and y can be used to specify the initial location of the
desktop manager.
X.I
Default value: 0x0+0+0
X.TP
X.BI VirtualIconGeometry " (string)"
Speficied the geometry string of the desktop manager icon in standard X11
format (wxh+x+y).  The width and height are ignored, but the x and y can
be used to specify the initial location of the desktop manager icon.
X.I
Default value: 0x0+0+0
X.P
X.TP
X.BI VirtualIconic " (Boolean)"
If true, the virtual desk manager will come up iconic.
X.I
Default value:  False
X.P
X.TP
X.BI AllowMoveIntoDesktop " (Boolean)"
If true, allows windows to be moved from the screen into the desktop
manager and vice versa.  Otherwise, moving a window on the screen will
only allow it to be placed in the visible desktop area; and moving a
window in the desktop manager will not let it be dragged onto the screen.
X.I
Default value:  True
X.P
X.TP
X.BI VirtualFont " (string)"
The font name used to display title of windows within the virtual desktop
manager.
X.I
Default value:  A string representing a medium-sized Lucida Font
X.P
X.TP
X.BI VirtualBackgroundColor " (color specification)"
The color of the background of the virtual desktop manager.
X.I
Default value:  Based on the frame color of your desktop.
X.P
X.TP
X.BI VirtualForegroundColor " (color specification)"
The color of the virtual windows in the virtual desktop manager.
X.I
Default value:  The frame color of your desktop.
X.P
X.TP
X.BI VirtualFontColor " (color specification)"
The color of the title within the virtual windows of the virtual desktop
manager.
X.I
Default value:  Black
X.P
X.TP
X.BI VirtualBackgroundMap " (Pixmap filename)"
The name of a file containing a pixmap to use as the background of the
virtual desktop manager.  This item, if present, takes precedence over
the VirtualBackgroundColor.
X.I
Default value:  unused
X.P
X.TP
X.BI AutoShowRootMenu " (Bool)"
If true, the root menu will come up pinned at start up.
X.I
Default value:  False
X.P
X.TP
X.BI AutoRootMenuX " (int)"
If AutoShowRootMenu is true, this is the X location where the menu will
come up.
X.I
Default value: 0
X.P
X.TP
X.BI AutoRootMenuY " (int)"
If AutoShowRootMenu is true, this is the Y location where the menu will
come up.
X.I
Default value: 0
X.P
X.TP
X.BI VirtualSticky " (list of strings)"
The list of windows which should be sticky by default.  Like the olwm
MinimalDecor, this should be the list of class of windows (typically
set via the WM_CLASS property) which should be sticky.
X.I
Default value:  Null
X.P
X.\" ========================================================================
X.SH COPYRIGHTS
X.LP
OPEN LOOK is a trademark of AT&T.
X.br
The X Window system is a trademark of the Massachusetts Institute of
Technology.
X.br
OpenWindows is a trademark of Sun Microsystems, Inc.
X.br
Portions (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
pending in the U.S. and foreign countries. OPEN LOOK is a
trademark of AT&T. Used by written permission of the owners.
X.br
Portions (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered
trademark of Bigelow & Holmes. Permission to use the Lucida
trademark is hereby granted only in association with the images
and fonts described in this file.
X.br
Portions may be (c) 1990 Solbourne Computers.
X.br
Please see the LEGAL_NOTICES file for full disclosure of copyright
information.
X
X.\" ========================================================================
X.SH BUGS
X.LP
It's highly recommended to set the
X.B olwm
resource RefreshRecursively to False in order to get refreshes on the
virtual desktop to work correctly.
X.LP
New frames should inherit the stickyness of their parent.
X.LP
The virtual desktop manager icon is, in the words of an office mate,
X``pretty lame.''  Better yet, though, it should show feedback so it's
possible to tell when on the desktop you are when it's closed.
X.LP
Need a way for base windows to be sticky on creation (but I don't
like tvtwm's method of having particular applications sticky).
X.LP
Probably scores more; this was a weekend-type hack after all :-).
END_OF_FILE
if test 10814 -ne `wc -c <'olvwm.man'`; then
    echo shar: \"'olvwm.man'\" unpacked with wrong size!
fi
# end of 'olvwm.man'
fi
if test -f 'win.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'win.c'\"
else
echo shar: Extracting \"'win.c'\" \(9251 characters\)
sed "s/^X//" >'win.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
X *      file for terms of the license.
X *
X *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char     sccsid[] = "@(#)win.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) win.c 25.6 90/05/20 Crucible";
X *
X */
X
X#include <stdio.h>
X#include <memory.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X
X#include "olwm.h"
X#include "win.h"
X#include "mem.h"
X#include "st.h"
X
X#include "globals.h"
X
X/***************************************************************************
X* local functions
X***************************************************************************/
X
static enum st_retval
doRedrawOneWindow(w,win,c)
Window w;
WinGeneric *win;
void *c;
X{
X    if ((WinFunc(win,core.drawfunc) != NULL) && (win->core.client != NULL))
X	(WinFunc(win,core.drawfunc))(win->core.client->dpy,win);
X    return ST_CONTINUE;
X}
X
static void
callSelectTree(dpy,win,sel)
Display *dpy;
WinGeneric *win;
Bool sel;
X{
X	List *l = win->core.children;
X
X	if (WinFunc(win,core.selectfunc) != NULL)
X		(*(WinFunc(win,core.selectfunc)))(dpy,win,sel);
X	for (win = ListEnum(&l); win != NULL; win = ListEnum(&l))
X		callSelectTree(dpy, win, sel);
X}
X
X/* Destroying a window tree:  walk the trees associated with a client, 
X * invoking the destroyfuncs on each.  The order that the windows are
X * destroyed is significant; it works from the root upwards.  The
X * client structure is not affected; it is assumed that this function
X * is only called from routines which take responsibility for removing
X * the client structure as well.
X */
static void
callDestroyTree(dpy,win)
Display *dpy;
WinGeneric *win;
X{
X	List *l;
X	WinGeneric *cwin;
X
X	if (win == NULL)
X		return;
X	l = win->core.children;
X	for (cwin = ListEnum(&l); cwin != NULL; cwin = ListEnum(&l))
X		callDestroyTree(dpy, cwin);
X	if (WinFunc(win,core.destroyfunc) != NULL)
X		(*(WinFunc(win,core.destroyfunc)))(dpy,win);
X}
X
static void
setTreeConfig(dpy,win)
Display *dpy;
WinGeneric *win;
X{
X	List *l = win->core.children;
X	WinGeneric *wc;
X
X	(*(WinFunc(win,core.setconfigfunc)))(dpy,win);
X	for (wc = ListEnum(&l); wc != NULL; wc = ListEnum(&l))
X	{
X		setTreeConfig(dpy,wc);
X	}
X}
X
static void
callFocusTree(win, focus)
WinGeneric *win;
Bool focus;
X{
X	List *l;
X	WinGeneric *cwin;
X
X	if (win == NULL)
X		return;
X	if (WinFunc(win,core.focusfunc) != NULL)
X		(WinFunc(win,core.focusfunc))(win->core.client->dpy,win,focus);
X	l = win->core.children;
X	for (cwin = ListEnum(&l); cwin != NULL; cwin = ListEnum(&l))
X		callFocusTree(cwin, focus);
X}
X
X
static void
callDrawTree(win)
X    WinGeneric *win;
X{
X    List *l;
X    WinGeneric *cwin;
X
X    if (WinFunc(win,core.drawfunc) != NULL)
X	(WinFunc(win,core.drawfunc))(win->core.client->dpy,win);
X
X    l = win->core.children;
X    for (cwin = ListEnum(&l); cwin != NULL; cwin = ListEnum(&l))
X	callDrawTree(cwin);
X}
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/* WinCallSelect - call a client's select functions for either the icon or
X *   frame trees, depending on which is visible.  Passes along sel,
X *   which is True iff the client is being selected.
X */
void
WinCallSelect(cli, sel)
Client *cli;
Bool sel;
X{
X	if (cli->wmState == NormalState)
X		callSelectTree(cli->dpy, cli->framewin, sel);
X	else if (cli->wmState == IconicState)
X		callSelectTree(cli->dpy, cli->iconwin, sel);
X}
X
X/* WinCallFocus - call a client's focus functions for the frame tree.
X *   Passes along focus, which is True iff the client is gaining focus
X */
void
WinCallFocus(win,focus)
WinGeneric *win;
Bool focus;
X{
X	if (win == NULL)
X		return;
X	win->core.client->isFocus = focus;
X	callFocusTree(win, focus);
X}
X	
X/* WinCallDestroy - call a client's destroy functions for both the icon and
X *   frame trees
X */
void
WinCallDestroy(cli)
Client *cli;
X{
X	Display *dpy = cli->dpy;
X	WinPaneFrame *framewin = cli->framewin;
X	WinIconFrame *iconwin = cli->iconwin;
X
X	callDestroyTree(dpy, framewin);
X	callDestroyTree(dpy, iconwin);
X}
X
X/* WinCallConfig - initiate a configuration change, starting at some
X *	particular window.
X *	Configuration change works as follows:  a window is the initiator
X *	of the change.  If the children of this window need to be sized,
X *	then they are called to do so; then the window sizes itself and
X *	sets the position of each of its children.  This process is
X *	repeated on the parent of the initiating window, and so on up
X *	to the top window in the hierarchy (presumably a frame).
X *	A second pass then occurs, doing a depth-first preorder 
X *	traversal of the window tree, performing the window's set
X *	configuration function to make the computed change.
X *	In the first pass, any window which changes its configuration 
X *	should return this fact to be propagated back to this routine;
X *	if no window has changed configuration then the second pass
X *	won't be performed.
X *	The initiator window is passed (in some cases) the configure
X *	request event which cause the action to begin.
X */
void
WinCallConfig(dpy,win,pxcre)
Display *dpy;
WinGeneric *win;
XXConfigureRequestEvent *pxcre;
X{
X	Bool fDirty = False;
X	WinGeneric *w;
X	
X	do
X	{
X		fDirty = (WinFunc(win,core.newconfigfunc))(win,pxcre) || fDirty;
X		pxcre = NULL;
X		w = win;
X	}
X	while ((win = win->core.parent) != NULL);
X	if (fDirty)
X	{
X		setTreeConfig(dpy,w);
X	}
X}
X
X/*
X * WinCallDraw
X * Call all child windows' draw functions.
X */
void
WinCallDraw(win)
X    WinGeneric *win;
X{
X    callDrawTree(win);
X}
X
X
X/* WinAddChild -- add a child to a parent's list of children
X */
void
WinAddChild(parent,child)
WinGeneric *parent;
WinGeneric *child;
X{
X	parent->core.children = ListCons(child,parent->core.children);
X	child->core.parent = parent;
X}
X
X/* WinRemoveChild -- remove a child from a parent's list of children
X */
void
WinRemoveChild(parent,child)
WinGeneric *parent;
WinGeneric *child;
X{
X	List **l;
X
X	for (l = &(parent->core.children); *l != NULL; l = &((*l)->next))
X	{
X	    if ((WinGeneric *)((*l)->value) == child)
X	    {
X		ListDestroyCell(l);
X		return;
X	    }
X	}
X#ifdef DEBUG
X	printf("Warning:  tried to remove child %x from parent %x, but it wasn't there\n",child,parent);
X#endif
X}
X
X/* WinRootPos -- figure the root coordinates of a window's position
X */
void
WinRootPos(win,px,py)
WinGeneric *win;
int *px, *py;
X{
X	*px = 0;
X	*py = 0;
X	for ( ; win != NULL; win = win->core.parent)
X	{
X		*px += win->core.x;
X		*py += win->core.y;
X	}
X}
X
X
X/* WinRedrawAllWindows -- call every window's draw function (if provided)
X */
void
WinRedrawAllWindows()
X{
X	WIApply(doRedrawOneWindow, NULL);
X}
X
X/***************************************************************************
X* general event/class functions
X***************************************************************************/
X
int
WinEventExpose(dpy, event, win)
Display *dpy;
XXEvent *event;
WinGeneric *win;
X{
X	if (event->xexpose.count == 0)
X	    (WinFunc(win,core.drawfunc))(dpy, win);
X	else if (GRV.PrintAll) {
X	    fprintf(stderr, "Expose event ignored\n");
X	    DebugWindow(win);
X	}
X}
X
X
int 
WinNewPosFunc(win,x,y)
WinGeneric *win;
int x,y;
X{
X    if (x != win->core.x)
X    {
X	win->core.x = x;
X	win->core.dirtyconfig |= CWX;
X    }
X
X    if (y != win->core.y)
X    {
X	win->core.y = y;
X	win->core.dirtyconfig |= CWY;
X    }
X
X    return win->core.dirtyconfig;
X}
X
X
int
WinNewConfigFunc(win, pxcre)
WinGeneric *win;
XXConfigureRequestEvent *pxcre;
X{
X	int neww = WinFunc(win,core.widthfunc)(win, pxcre);
X	int newh = WinFunc(win,core.heightfunc)(win, pxcre);
X
X	if (neww != win->core.width)
X	{
X	    win->core.width = neww;
X	    win->core.dirtyconfig |= CWWidth;
X	}
X	if (newh != win->core.height)
X	{
X	    win->core.height = newh;
X	    win->core.dirtyconfig |= CWHeight;
X	}
X	return win->core.dirtyconfig;
X}
X
X
int
WinSetConfigFunc(dpy, win)
Display *dpy;
WinGeneric *win;
X{
X	XWindowChanges xwc;
X
X	if (win->core.dirtyconfig)
X	{
X	    xwc.x = win->core.x;
X	    xwc.y = win->core.y;
X	    xwc.width = win->core.width;
X	    xwc.height = win->core.height;
X	    /* generic windows never change border or stacking */
X	    XConfigureWindow(dpy,win->core.self,win->core.dirtyconfig,&xwc);
X	}
X	win->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight);
X}
X
X
X/*
X * WinAddColorClient
X *
X * Add cli to this win's list of colormap clients.  Assumes that cli isn't 
X * already in the list.
X */
void
WinAddColorClient(win, cli)
X    WinGeneric *win;
X    Client *cli;
X{
X    win->core.colormapClients = ListCons(cli, win->core.colormapClients);
X}
X
X
X/*
X * WinRemoveColorClient
X *
X * Remove cli from this win's list of colormap clients.  If there are no more
X * clients, and this window is a WIN_COLORMAP, destroy the window.  Assumes
X * that cli appears in win's list zero or one times.
X */
void
WinRemoveColorClient(dpy, win, cli)
X    Display *dpy;
X    WinGeneric *win;
X    Client *cli;
X{
X    List **l;
X
X    l = &win->core.colormapClients;
X    while (*l != NULL) {
X	if ((*l)->value == cli) {
X	    ListDestroyCell(l);
X	    break;
X	}
X	l = &((*l)->next);
X    }
X    if (win->core.colormapClients == NULL_LIST
X	&& win->core.kind == WIN_COLORMAP)
X	(WinFunc(win, core.destroyfunc))(dpy, win);
X}
END_OF_FILE
if test 9251 -ne `wc -c <'win.c'`; then
    echo shar: \"'win.c'\" unpacked with wrong size!
fi
# end of 'win.c'
fi
if test -f 'winbutton.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winbutton.c'\"
else
echo shar: Extracting \"'winbutton.c'\" \(9099 characters\)
sed "s/^X//" >'winbutton.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
X *      file for terms of the license.
X *
X *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char     sccsid[] = "@(#)winbutton.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winbutton.c 25.5 90/05/21 Crucible";
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <olgx/olgx.h>
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "globals.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Graphics_info *olgx_gisnormal;
extern GC DrawSelectedGC;
extern GC DrawBackgroundGC;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X#define in_windowmark(x,y) \
X	( (x) >= 0 && (y) >= 0 && \
X	  (x) <= Abbrev_MenuButton_Width(olgx_gisnormal) && \
X	  (y) <= Abbrev_MenuButton_Height(olgx_gisnormal) \
X	)
static Bool buttonActive = False;
static ClassButton classButton;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/* 
X * eventButtonPress - handle button press events on the close button window.  
X */
static int
eventButtonPress(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinButton	*winInfo;
X{
X	Client *cli = winInfo->core.client;
X	WinPaneFrame *winFrame = cli->framewin;
X
X        olgx_draw_abbrev_button(olgx_gisnormal, winInfo->core.self, 
X		0, 0, OLGX_INVOKED);
X        switch (MouseButton(dpy, event))
X        {
X        case MB_ADJUST:
X                return;
X
X        case MB_MENU:
X                if (winFrame->fcore.menu)
X                        MenuShow(dpy, winFrame, winFrame->fcore.menu, event);
X                olgx_draw_abbrev_button(olgx_gisnormal, 
X			winInfo->core.self,
X                       	0, 0, OLGX_NORMAL | OLGX_ERASE);
X                return;
X
X        }
X        XGrabPointer(dpy, winInfo->core.self,
X             False,
X             (ButtonReleaseMask | ButtonPressMask | PointerMotionMask),
X             GrabModeAsync, GrabModeAsync,
X             None,
X             GRV.MovePointer,
X             CurrentTime);
X        buttonActive = True;
X}
X
X/* 
X * eventButtonRelease - handle button release events on the close button window.  
X */
static int
eventButtonRelease(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinButton	*winInfo;
X{
X	Client *cli = winInfo->core.client;
X	int x,y;
X
X        /* REMIND: why is this necessary?  The pointer should have
X         * been re-grabbed with GrabModeAsync, thus deactivating
X         * the grab upon the release of the button. */
X        XUngrabPointer(dpy,event->xbutton.time);
X
X        x = event->xbutton.x;
X        y = event->xbutton.y;
X
X        buttonActive = False;
X        olgx_draw_abbrev_button(olgx_gisnormal, winInfo->core.self, 
X			0, 0, OLGX_NORMAL | OLGX_ERASE);
X
X        if (!in_windowmark(x,y))
X        {
X                return;
X        }
X
X        /* we want to do the default action of the menu for this
X         * window.  This will either be Iconify if the window is
X         * a base window, or dismiss if not */
X        switch(cli->wmDecors->menu_type)
X        {
X                case MENU_FULL:
X                        StateNormIcon(cli);
X                        break;
X
X                case MENU_NONE:
X                case MENU_LIMITED:
X                        /*
X                         * Send a WM_DELETE_WINDOW event.
X			 * REMIND change to use event time
X                         */
X			ClientKill(cli,False);
X                        break;
X        }
X}
X
X/* 
X * eventMotionNotify - handle motion notify events on the close button window.  
X */
static int
eventMotionNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinButton	*winInfo;
X{
X	Client *cli = winInfo->core.client;
X	int x,y;
X
X	if (!event->xmotion.same_screen)
X		return;
X
X        x = event->xmotion.x;
X        y = event->xmotion.y;
X        if ( buttonActive && !in_windowmark(x,y) ) {
X            olgx_draw_abbrev_button(olgx_gisnormal, winInfo->core.self,
X		0, 0, OLGX_NORMAL | OLGX_ERASE);
X            buttonActive = False;
X        } else if ( !buttonActive && in_windowmark(x,y) ) {
X            olgx_draw_abbrev_button(olgx_gisnormal, winInfo->core.self,
X	    	0, 0, OLGX_INVOKED);
X            buttonActive = True;
X        }
X}
X
X/*
X * drawButton -- draw the pushpin window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawButton(dpy, winInfo)
Display	*dpy;
WinButton *winInfo;
X{
X    GC erasegc;
X
X    /*
X     * REMIND
X     * 
X     * Erase the background first.  Unfortunately, we can't depend on
X     * OLGX_ERASE to do the right thing, because it (a) erases only in BG1,
X     * and (b) erases only in 2D mode.  We need to erase a background color
X     * that depends on the state of the frame.  If we're in click-focus and we
X     * have the focus, draw in BG2; otherwise, draw in BG1.
X     */
X
X    if (!GRV.FocusFollowsMouse && winInfo->core.client->isFocus)
X	erasegc = DrawSelectedGC;
X    else
X	erasegc = DrawBackgroundGC;
X
X    XFillRectangle(dpy, winInfo->core.self, erasegc, 0, 0,
X		   Abbrev_MenuButton_Width(olgx_gisnormal),
X		   Abbrev_MenuButton_Height(olgx_gisnormal));
X
X    olgx_draw_abbrev_button(olgx_gisnormal, winInfo->core.self,
X			    0, 0, OLGX_NORMAL | OLGX_ERASE);
X}
X
X
X/*
X * DestroyButton -- destroy the close button window resources and free any allocated
X *	data.
X */
static int
destroyButton(dpy, winInfo)
Display	*dpy;
WinButton *winInfo;
X{
X	/* free our data and throw away window */
X	XDestroyWindow(dpy, winInfo->core.self);
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X
X/* 
X * focusButton - the focus or selection state has changed
X */
static int
focusButton(dpy, winInfo, selected)
Display *dpy;
WinButton *winInfo;
Bool selected;
X{
X        (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * heightfuncButton - recomputes the height of the close button window
X */
static int 
heightfuncButton(win, pxcre)
WinButton *win;
XXConfigureRequestEvent *pxcre;
X{
X	return Abbrev_MenuButton_Width(olgx_gisnormal);
X}
X
X/*
X * widthfuncButton - recomputes the width of the close button window
X */
static int 
widthfuncButton(win, pxcre)
WinButton *win;
XXConfigureRequestEvent *pxcre;
X{
X	return Abbrev_MenuButton_Height(olgx_gisnormal);
X}
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeButton  -- create the close button window. Return a WinGeneric structure.
X */
WinButton *
MakeButton(dpy, par, x, y)
Display	*dpy;
WinGeneric *par;
int x,y;
X{
X	WinButton *w;
X	Window win;
X        unsigned long valuemask;
X        XSetWindowAttributes attributes;
X
X        attributes.event_mask =
X	    ButtonReleaseMask | ButtonPressMask | ExposureMask;
X	attributes.cursor = GRV.IconPointer;
X        valuemask = CWEventMask | CWCursor;
X
X        win = XCreateWindow(dpy, par->core.self,
X                        x, y,
X			Abbrev_MenuButton_Width(olgx_gisnormal), 
X			Abbrev_MenuButton_Height(olgx_gisnormal),
X                        0,
X                        DefaultDepth(dpy, DefaultScreen(dpy)),
X                        CopyFromParent,
X                        DefaultVisual(dpy, DefaultScreen(dpy)),
X                        valuemask,
X                        &attributes);
X
X	/* create the associated structure */
X	w = MemNew(WinButton);
X	w->core.self = win;
X	w->class = &classButton;
X	w->core.kind = WIN_WINBUTTON;
X	WinAddChild(par,w);
X	w->core.children = NULL;
X	w->core.client = par->core.client;
X	w->core.x = x;	
X	w->core.y = y;
X	w->core.width = Abbrev_MenuButton_Width(olgx_gisnormal);
X	w->core.height = Abbrev_MenuButton_Height(olgx_gisnormal);
X	w->core.dirtyconfig = 0;
X	w->core.exposures = NULL;
X
X	/* register the window */
X	WIInstallInfo(w);
X
X        XMapWindow(dpy, win);
X
X	return w;
X}
X
void
ButtonInit(dpy)
Display *dpy;
X{
X        classButton.core.kind = WIN_WINBUTTON;
X        classButton.core.xevents[ButtonPress] = eventButtonPress;
X        classButton.core.xevents[ButtonRelease] = eventButtonRelease;
X        classButton.core.xevents[MotionNotify] = eventMotionNotify;
X        classButton.core.xevents[Expose] = WinEventExpose;
X        classButton.core.focusfunc = focusButton;
X        classButton.core.drawfunc = drawButton;
X        classButton.core.destroyfunc = destroyButton;
X        classButton.core.selectfunc = NULL;
X        classButton.core.newconfigfunc = WinNewConfigFunc;
X        classButton.core.newposfunc = WinNewPosFunc;
X        classButton.core.setconfigfunc = WinSetConfigFunc;
X        classButton.core.createcallback = NULL;
X        classButton.core.heightfunc = heightfuncButton;
X        classButton.core.widthfunc = widthfuncButton;
X}
X
END_OF_FILE
if test 9099 -ne `wc -c <'winbutton.c'`; then
    echo shar: \"'winbutton.c'\" unpacked with wrong size!
fi
# end of 'winbutton.c'
fi
if test -f 'winpush.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winpush.c'\"
else
echo shar: Extracting \"'winpush.c'\" \(10341 characters\)
sed "s/^X//" >'winpush.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
X *      file for terms of the license.
X *
X *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static	char	sccsid[] = "@(#) winpush.c 25.7 90/05/21 Crucible";
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <olgx/olgx.h>
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "globals.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Atom AtomDeleteWindow;
extern Atom AtomPushpinState;
extern Graphics_info *olgx_gisnormal;
extern Graphics_info *olgx_gisrevpin;
extern GC DrawBusyGC, DrawBackgroundGC;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
static ClassPushPin classPushPin;
static Bool     pushpinStateAfterPress;  /* State of the pushpin
X					  * after the user pressed
X				   	  * the mouse button. */
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/* locallyChangePushPinState -- temporarily change the pushpin state,
X * 	while tracking a button press over the pin.  The permanent change
X *	will be made later.
X */
static void
locallyChangePushPinState(dpy,winInfo,newState)
Display *dpy;
WinPushPin *winInfo;
Bool newState;
X{
X        if (winInfo->pushpinin != newState)
X        {
X                winInfo->pushpinin = newState;
X                (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X        }
X}
X
X/* changePushPinState -- permanently change the push pin state */
static void
changePushPinState(dpy, event, winInfo)
Display *dpy;
XXEvent  *event;
WinPushPin *winInfo;
X{
X	Client		*cli = winInfo->core.client;
X
X        (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X
X        /* Tell the client that the state of its push-pin
X         * has changed.
X         */
X        XChangeProperty(dpy, PANEWINOFCLIENT(cli),
X                        AtomPushpinState,
X                        XA_INTEGER, 32,
X                        PropModeReplace,
X                        (unsigned char *)&(winInfo->pushpinin), 1);
X
X        /* If the client has WM_DELETE_WINDOW in
X         * its WM_PROTOCOLS, then we should send
X         * a WM_DELETE_WINDOW client message.
X         */
X        if (!winInfo->pushpinin)
X        {
X		ClientKill(winInfo->core.client,False);
X        }  
X#ifdef NOTDEF
X        /* Else just unmap the window. */
X        /* REMIND what should we do here? (if client isn't in delete protocol)
X        else
X                XUnmapWindow(dpy, clientEvent.xclient.window);
X        */
X#endif
X}  
X
X/* 
X * eventButtonPress - handle button press events on the pushpin window 
X */
static int
eventButtonPress(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPushPin	*winInfo;
X{
X	if (MouseButton(dpy,event) == MB_SELECT)
X	{
X            locallyChangePushPinState(dpy, winInfo, !(winInfo->pushpinin));
X            pushpinStateAfterPress = winInfo->pushpinin;
X	}
X}
X
X/* 
X * eventButtonRelease - handle button release events on the pushpin window 
X */
static int
eventButtonRelease(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPushPin	*winInfo;
X{
X	/*
X	 * If the user pressed the SELECT button, and the pin state is the 
X	 * same as it was just after he pressed the button over the pin, that 
X	 * means that we really are changing the pin state.  Otherwise, the 
X	 * user has previewed a pin state change but has backed off, so we do 
X	 * nothing.
X	 */
X	if (MouseButton(dpy,event) == MB_SELECT &&
X	    pushpinStateAfterPress == winInfo->pushpinin)
X	{
X		changePushPinState(dpy,event,winInfo);
X	}
X}
X
X/* 
X * eventMotionNotify - handle pointer moves
X */
static int
eventMotionNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPushPin	*winInfo;
X{
X	Bool fInWindow;
X
X	if (!event->xmotion.same_screen)
X		return;
X
X        /* When the user moves the cursor off the pushpin
X         * while s/he has the button down we should pull
X         * the button out.  If the user moves back onto the
X         * pushpin put the pin back in.  So,
X         *
X         * if (cursor is off the pushpin) and (pin is in)
X         *                  OR
X         *    (cursor is on the pushpin) and (pin is out)
X         * then
X         *      change the state of the pushpin.
X         */
X        fInWindow = !((event->xmotion.x < 0) ||
X             (event->xmotion.y < 0) ||
X             (event->xmotion.x >= PushPinOut_Width(olgx_gisnormal)) ||
X             (event->xmotion.y >= PushPinOut_Height(olgx_gisnormal)));
X        locallyChangePushPinState(dpy, winInfo,
X                fInWindow?pushpinStateAfterPress:!pushpinStateAfterPress);
X
X        /* REMIND Maybe we should do this by getting LeaveNotify events
X         * and seeing if MB_SELECT is pressed.  If it is, then we
X         * know the user left the pushpin with the button pressed???
X         */
X}
X
X
X/*
X * drawPushPin -- draw the pushpin window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawPushPin(dpy, winInfo)
Display	*dpy;
WinPushPin *winInfo;
X{
X	Client *cli = winInfo->core.client;
X
X        /* If the titlebar is in reverse video we need to
X         * draw the pushpin in reverse video also.
X         */
X	if (GRV.F3dUsed) {
X		/*
X		 * REMIND
X		 * We need to erase the background here to BG2.  We can't use
X		 * OLGX_ERASE because olgx erases only in BG1.  So, we draw an 
X		 * filled, invoked box that is just larger than the pin 
X		 * window, so that the border doesn't show.
X		 */
X		olgx_draw_box(olgx_gisnormal, winInfo->core.self, -1, -1,
X			      winInfo->core.width+2,
X			      winInfo->core.height+2,
X                              ((cli->isFocus) && (!GRV.FocusFollowsMouse))?
X			          OLGX_INVOKED : OLGX_NORMAL, 
X			      True);
X        } else {
X		XFillRectangle(dpy, winInfo->core.self, DrawBackgroundGC, 
X			0, 0, winInfo->core.width, winInfo->core.height);
X        }
X	if (winInfo->core.client->isBusy)
X	{
X	    XFillRectangle(dpy, winInfo->core.self, DrawBusyGC,
X		0, 0, winInfo->core.width, winInfo->core.height);
X	}
X	olgx_draw_pushpin(olgx_gisnormal, winInfo->core.self, 0, 0,
X              	  ((winInfo->pushpinin) ? OLGX_PUSHPIN_IN : OLGX_PUSHPIN_OUT));
X}
X
X
X/*
X * DestroyPushPin -- destroy the pushpin window resources and free any allocated
X *	data.
X */
static int
destroyPushPin(dpy, winInfo)
Display	*dpy;
WinPushPin *winInfo;
X{
X	/* free our data and throw away window */
X	XDestroyWindow(dpy, winInfo->core.self);
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X
X/* 
X * focusselectPushPin - the focus or selection state has changed
X */
static int
focusselectPushPin(dpy, winInfo, selected)
Display *dpy;
WinPushPin *winInfo;
Bool selected;
X{
X        (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * heightfuncPushPin - recomputes the correct height of the window
X */
static int 
heightfuncPushPin(win, pxcre)
WinPushPin *win;
XXConfigureRequestEvent *pxcre;
X{
X	return PushPinOut_Width(olgx_gisnormal);
X}
X
X/*
X * widthfuncPushPin - recomputes the correct width of the window
X */
static int 
widthfuncPushPin(win, pxcre)
WinPushPin *win;
XXConfigureRequestEvent *pxcre;
X{
X	return PushPinOut_Height(olgx_gisnormal);
X}
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakePushPin  -- create the pushpin window. Return a WinGeneric structure.
X */
WinPushPin *
MakePushPin(dpy, par, pane, x, y)
Display	*dpy;
WinGeneric *par;
Window pane;
int x,y;
X{
X	WinPushPin *w;
X	Window win;
X        unsigned long valuemask;
X        XSetWindowAttributes attributes;
X
X        attributes.event_mask = Button1MotionMask | ButtonReleaseMask | 
X		ButtonPressMask | ExposureMask;
X        attributes.win_gravity = NorthWestGravity;
X        valuemask = CWEventMask | CWWinGravity;
X
X        win = XCreateWindow(dpy, par->core.self,
X                        x, y,
X			PushPinOut_Width(olgx_gisnormal), 
X			PushPinOut_Height(olgx_gisnormal),
X                        0,
X                        DefaultDepth(dpy, DefaultScreen(dpy)),
X                        CopyFromParent,
X                        DefaultVisual(dpy, DefaultScreen(dpy)),
X                        valuemask,
X                        &attributes);
X
X	/* create the associated structure */
X	w = MemNew(WinPushPin);
X	w->core.self = win;
X	w->class = &classPushPin;
X	w->core.kind = WIN_PUSHPIN;
X	WinAddChild(par,w);
X	w->core.children = NULL;
X	w->core.client = par->core.client;
X	w->core.x = x;	
X	w->core.y = y;
X	w->core.width = PushPinOut_Width(olgx_gisnormal);
X	w->core.height = PushPinOut_Height(olgx_gisnormal);
X	w->core.dirtyconfig = CWX | CWY | CWWidth | CWHeight;
X	w->core.exposures = NULL;
X
X        /* Determine initial state of push pin. */
X        w->pushpinin =  (par->core.client->wmDecors->pushpin_initial_state == PIN_IN);
X
X        /* Register the push-pin state. */
X        XChangeProperty(dpy, pane,
X                        AtomPushpinState,
X                        XA_INTEGER, 32,
X                        PropModeReplace,
X                        (unsigned char *)&(w->pushpinin), 1);
X
X	/* register the window */
X	WIInstallInfo(w);
X
X        XMapRaised(dpy, win);
X
X	return w;
X}
X
void
PushPinInit(dpy)
Display *dpy;
X{
X	classPushPin.core.kind = WIN_PUSHPIN;
X	classPushPin.core.xevents[Expose] = WinEventExpose;
X	classPushPin.core.xevents[ButtonPress] = eventButtonPress;
X	classPushPin.core.xevents[ButtonRelease] = eventButtonRelease;
X	classPushPin.core.xevents[MotionNotify] = eventMotionNotify;
X	classPushPin.core.focusfunc = focusselectPushPin;
X	classPushPin.core.drawfunc = drawPushPin;
X	classPushPin.core.destroyfunc = destroyPushPin;
X	classPushPin.core.selectfunc = focusselectPushPin;
X	classPushPin.core.newconfigfunc = WinNewConfigFunc;
X	classPushPin.core.newposfunc = WinNewPosFunc;
X	classPushPin.core.setconfigfunc = WinSetConfigFunc;
X	classPushPin.core.createcallback = NULL;
X	classPushPin.core.heightfunc = heightfuncPushPin;
X	classPushPin.core.widthfunc = widthfuncPushPin;
X}
END_OF_FILE
if test 10341 -ne `wc -c <'winpush.c'`; then
    echo shar: \"'winpush.c'\" unpacked with wrong size!
fi
# end of 'winpush.c'
fi
echo shar: End of archive 3 \(of 16\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 16 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

--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources.x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list