v12i065: olvwm - Open Look Virtual Window Manager, Part09/16

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


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

#! /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 9 (of 16)."
# Contents:  olwm.c winicon.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:07 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'olwm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'olwm.c'\"
else
echo shar: Extracting \"'olwm.c'\" \(24540 characters\)
sed "s/^X//" >'olwm.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[] = "@(#)olwm.c	1.4 olvwm version 4/25/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) olwm.c 25.14 90/06/05 Crucible";
X *
X */
X
X#include "patchlevel.h"
X
X#include <errno.h>
X#include <memory.h>
X#include <signal.h>
X#include <stdio.h>
X#include <strings.h>
X
extern char *strtok();		/* not defined in strings.h */
X
X#include <sys/time.h>
X#include <sys/types.h>
X
X#include <sys/resource.h>
X#include <sys/stat.h>
X#include <sys/wait.h>
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <X11/Xresource.h>
X
X#include "events.h"
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "defaults.h"
X#include "resources.h"
X#include "globals.h"
X#include "group.h"
X#include "slots.h"
X
X/*
X * Externals
X */
extern void	EventLoop();
extern void	UpdateModifierMap();
X
extern Atom	AtomChangeState;
extern Atom	AtomClass;
extern Atom	AtomColorMapWindows;
extern Atom	AtomDecorAdd;
extern Atom	AtomDecorClose;
extern Atom	AtomDecorDelete;
extern Atom	AtomDecorFooter;
extern Atom	AtomDecorHeader;
extern Atom	AtomDecorPin;
extern Atom	AtomDecorResize;
extern Atom	AtomDeleteWindow;
extern Atom	AtomLeftFooter;
extern Atom	AtomLength;
extern Atom	AtomListLength;
extern Atom	AtomMenuFull;
extern Atom	AtomMenuLimited;
extern Atom	AtomMultiple;
extern Atom	AtomNone;
extern Atom	AtomOlwmTimestamp;
extern Atom	AtomPinIn;
extern Atom	AtomPinOut;
extern Atom	AtomProtocols;
extern Atom	AtomPushpinState;
extern Atom	AtomRightFooter;
extern Atom	AtomSaveYourself;
extern Atom	AtomShowProperties;
extern Atom	AtomTakeFocus;
extern Atom	AtomTargets;
extern Atom	AtomTimestamp;
extern Atom	AtomWMApplyProperties;
extern Atom	AtomWMResetProperties;
extern Atom	AtomWMState;
extern Atom	AtomWTBase;
extern Atom	AtomWTCmd;
extern Atom	AtomWTHelp;
extern Atom	AtomWTNotice;
extern Atom	AtomWTOther;
extern Atom	AtomWTProp;
extern Atom	AtomWinAttr;
extern Atom	AtomWindowBusy;
extern Atom	AtomDfltBtn;
X
X/*
X * Globals
X */
char	*ProgramName;
char	*AppName;		/* strictly last component of ProgramName */
int	FrameFullAction(), Exit(), FrameLimAction(), DismissAction();
int 	IconFullAction();
extern Window	NoFocusWin;
extern Menu	*RootMenu;
X
X/* The Properties button is currently disabled in all of these menus */
Button IconFullButtonsSticky[] = {
X        { "Open", False, Enabled, {IconFullAction, NULL} },
X        { "Full Size", False, Enabled, {IconFullAction, NULL} },
X        { "Properties", False, Disabled, {IconFullAction, NULL} },
X        { "Back", False, Enabled, {IconFullAction, NULL} },
X        { "Refresh", False, Enabled, {IconFullAction, NULL} },
X        { "UnStick", False, Enabled, {IconFullAction, NULL} },
X        { "Quit", False, Enabled, {IconFullAction, NULL} },
X        };
Menu IconFullMenuSticky = { "Window", IconFullButtonsSticky, 7, 0, False, (FuncPtr)MakeMenu};
X
Button IconFullButtonsUnsticky[] = {
X        { "Open", False, Enabled, {IconFullAction, NULL} },
X        { "Full Size", False, Enabled, {IconFullAction, NULL} },
X        { "Properties", False, Disabled, {IconFullAction, NULL} },
X        { "Back", False, Enabled, {IconFullAction, NULL} },
X        { "Refresh", False, Enabled, {IconFullAction, NULL} },
X        { "Stick", False, Enabled, {IconFullAction, NULL} },
X        { "Quit", False, Enabled, {IconFullAction, NULL} },
X        };
Menu IconFullMenuUnsticky = { "Window", IconFullButtonsUnsticky, 7, 0, False, (FuncPtr)MakeMenu};
X
Button FrameNormButtonsSticky[] = {
X        { "Close", False, Enabled, {FrameFullAction, NULL} },
X        { "Normal Size", False, Enabled, {FrameFullAction, NULL} },
X        { "Properties", False, Disabled, {FrameFullAction, NULL} },
X        { "Back", False, Enabled, {FrameFullAction, NULL} },
X        { "Refresh", False, Enabled, {FrameFullAction, NULL} },
X        { "UnStick", False, Enabled, {FrameFullAction, NULL} },
X        { "Quit", False, Enabled, {FrameFullAction, NULL} },
X        };
Menu FrameNormMenuSticky = { "Window", FrameNormButtonsSticky, 7, 0, False, (FuncPtr)MakeMenu};
X
Button FrameNormButtonsUnsticky[] = {
X        { "Close", False, Enabled, {FrameFullAction, NULL} },
X        { "Normal Size", False, Enabled, {FrameFullAction, NULL} },
X        { "Properties", False, Disabled, {FrameFullAction, NULL} },
X        { "Back", False, Enabled, {FrameFullAction, NULL} },
X        { "Refresh", False, Enabled, {FrameFullAction, NULL} },
X        { "Stick", False, Enabled, {FrameFullAction, NULL} },
X        { "Quit", False, Enabled, {FrameFullAction, NULL} },
X        };
Menu FrameNormMenuUnsticky = { "Window", FrameNormButtonsUnsticky, 7, 0, False, (FuncPtr)MakeMenu};
X
Button FrameFullButtonsSticky[] = {
X        { "Close", False, Enabled, {FrameFullAction, NULL} },
X        { "Full Size", False, Enabled, {FrameFullAction, NULL} },
X        { "Properties", False, Disabled, {FrameFullAction, NULL} },
X        { "Back", False, Enabled, {FrameFullAction, NULL} },
X        { "Refresh", False, Enabled, {FrameFullAction, NULL} },
X        { "UnStick", False, Enabled, {FrameFullAction, NULL} },
X        { "Quit", False, Enabled, {FrameFullAction, NULL} },
X        };
Menu FrameFullMenuSticky = { "Window", FrameFullButtonsSticky, 7, 0, False, (FuncPtr)MakeMenu};
X
Button FrameFullButtonsUnsticky[] = {
X        { "Close", False, Enabled, {FrameFullAction, NULL} },
X        { "Full Size", False, Enabled, {FrameFullAction, NULL} },
X        { "Properties", False, Disabled, {FrameFullAction, NULL} },
X        { "Back", False, Enabled, {FrameFullAction, NULL} },
X        { "Refresh", False, Enabled, {FrameFullAction, NULL} },
X        { "Stick", False, Enabled, {FrameFullAction, NULL} },
X        { "Quit", False, Enabled, {FrameFullAction, NULL} },
X        };
Menu FrameFullMenuUnsticky = { "Window", FrameFullButtonsUnsticky, 7, 0, False, (FuncPtr)MakeMenu};
X
Button DismissButtons[] = {
X        { "This Window", False, Enabled, {DismissAction, NULL} },
X        { "All Pop-ups", False, Enabled, {DismissAction, NULL} },
X	};
Menu DismissMenu = { NULL, DismissButtons, 2, 0, False, NULL};
X	
Button FrameLimButtons[] = {
X	{ "Dismiss", True, Enabled, {(FuncPtr) 0, (void *) &DismissMenu} },
X        { "Back", False, Enabled, {FrameLimAction, (void *)0} },
X        { "Refresh", False, Enabled, {FrameLimAction, (void *)0} },
X        { "Owner?", False, Enabled, {FrameLimAction, (void *)0} },
X	};
Menu FrameLimMenu = { "Window", FrameLimButtons, 4, 0, False, (FuncPtr)MakeMenu};
X
X/* Current Display/Screen */
Display	*DefDpy;
int	DefScreen;
X
static void	parseCommandline();
X/* Note that changes to RMTable instance names must also be made here !! */
static	XrmOptionDescRec	optionTable[] = {
X	{ "-display",		".display",	
X		XrmoptionSepArg, (caddr_t) NULL },
X	{ "-f",			".inputFocusStyle", 
X		XrmoptionNoArg, (caddr_t) "follow" },
X	{ "-follow",		".inputFocusStyle", 
X		XrmoptionNoArg, (caddr_t) "follow" },
X	{ "-c", 		".inputFocusStyle",	
X		XrmoptionNoArg, (caddr_t) "select" },
X	{ "-click", 		".inputFocusStyle",	
X		XrmoptionNoArg, (caddr_t) "select" },
X	{ "-2d", 		".use3D",	
X		XrmoptionNoArg, (caddr_t) "False" },
X	{ "-3d", 		".use3D",	
X		XrmoptionNoArg, (caddr_t) "True" },
X	{ "-parent", 		".reparentOK",	
X		XrmoptionNoArg, (caddr_t) "False" },
X	{ "-orphans", 		".debug.print.orphans", 
X		XrmoptionNoArg, (caddr_t) "True" },
X	{ "-all", 		".debug.print.all", 
X		XrmoptionNoArg, (caddr_t) "True" },
X	{ "-synchronize",	".debug.synchronize",
X		XrmoptionNoArg, (caddr_t) "True" },
X	{ "-debug",	"*Debug",	XrmoptionNoArg,	(caddr_t) "True" },
X	{ "-name",		".name",	
X		XrmoptionSepArg, (caddr_t) NULL },
X	{ "-bg",	"*Background",	XrmoptionSepArg, (caddr_t) NULL },
X	{ "-background", "*Background",	XrmoptionSepArg, (caddr_t) NULL },
X	{ "-fg",	"*Foreground",	XrmoptionSepArg, (caddr_t) NULL },
X	{ "-foreground","*Foreground",	XrmoptionSepArg, (caddr_t) NULL },
X	{ "-bd",	"*Background",	
X		XrmoptionSepArg, (caddr_t) NULL },
X	{ "-bordercolor",	"*Background",	
X		XrmoptionSepArg, (caddr_t) NULL },
X	{ "-fn",	"*TitleFont",	XrmoptionSepArg, (caddr_t) NULL },
X	{ "-font",	"*TitleFont",	XrmoptionSepArg, (caddr_t) NULL },
X	{ "-xrm",	NULL,		XrmoptionResArg, (caddr_t) NULL },
X};
X#define OPTION_TABLE_ENTRIES (sizeof(optionTable)/sizeof(XrmOptionDescRec))
X
static void	parseResourceDefaults();
static void	initWinClasses();
X
X/* Child Process Handling */
void HandleChildSignal();
void ReapChildren();
int DeadChildren = 0;
X
static char	**argVec;
char		**Envp;
X
IgnoreErrors()
X{}
X
X/*
X * main	-- parse arguments, perform initialization, call event-loop
X *
X * The OpenLook window manager was written before the OpenLook
X * spec. was completed.  Because of this, some of it works in
X * an awkward way.  Specifically, the way a window's focus and
X * select state is shown.
X *
X * For example, when a window is focused in click-to-focus mode
X * the header gets highlighted, (black background, white text).
X * As it was written, the titlebar window sits just inside of the 
X * resize corners.  Because the OpenLook spec. requires the header to 
X * be highlighted in line with the resize corners, blacking in the
X * the background of the titlebar window is one pixel short in each
X * direction of being a big enough highlighted area.  We can't make
X * the titlebar bigger because it would then overlap the resize corners.
X * Now that the spec. is complete, OLWM should be restructured.
X *
X * Overview:
X *
X *	Upon startup OLWM reparents all the client windows unless
X *	the user has told it otherwise (-p option).
X * 	OLWM creates a frame which will contain the client window (the pane)
X *  	and the decoration windows (resize corners, titlebar).  The
X *	titlebar window contains the pushpin, if any.
X *
X *	After creating the decorations for the windows OLWM sits
X * 	in a forever loop getting the next event and calling the
X * 	corresponding window's event handling routine.
X *
X *	Each window has associated with it an event handling 
X * 	routine (EventFrame, EventPushPin) which the main EventLoop
X *	will call when an event happens in that window.  The event
X *	handling routine will call the proper routines to move a 
X *	window, create a menu, etc.
X */
main( argc, argv, envp )
int	argc;
char	**argv;
char	**envp;
X{
X	int			ErrorHandler();
X	XSetWindowAttributes	attributes;
X	int			ExitOLWM();
X	char			**updateEnvp();
X	XrmDatabase		commandlineDB = NULL;
X	XrmValue		rmValue;
X	XrmRepresentation	rmType;
X	char			name[MAX_NAME];
X	char			class[MAX_NAME];
X	WinGeneric		*winroot;
X
X#ifdef MALLOCDEBUG
X	malloc_debug(MALLOCDEBUG);
X#endif /* MALLOCDEBUG */
X
X	ProgramName = argv[0];
X	argVec = argv;
X
X	/* Set up a signal handler so that if we are killed we put
X	 * the windows back into a usable state.  Specifically we
X	 * need to reset the focus so they will be able to get input.
X	 */
X	signal(SIGHUP, ExitOLWM);
X	signal(SIGINT, ExitOLWM);
X	signal(SIGTERM, ExitOLWM);
X	signal(SIGCHLD, HandleChildSignal);
X
X	/* initialize the resource manager */
X	XrmInitialize();
X
X	/* parse the command line arguments into local tmp DB */
X	parseCommandline( &argc, argv, &commandlineDB );
X
X	SetNameTag(NULL, RM_PREFIX, NULL, False);
X
X	/* check to see if display was specified on command line */
X	MakeRMName( name, RM_DISPLAY );
X	MakeRMClass( class, RM_DISPLAY );
X	
X	if ( XrmGetResource( commandlineDB, name, class, &rmType, &rmValue ) )
X	{
X		GRV.DisplayName = MemNewString( rmValue.addr );
X		/* need to change display in Envp for commands invoked */
X		Envp = updateEnvp( envp, "DISPLAY", GRV.DisplayName );
X	}
X	else
X	{
X		GRV.DisplayName = NULL;
X		Envp = envp;
X	}
X
X	/* Open the display connection. */
X	if ((DefDpy = XOpenDisplay(GRV.DisplayName)) == NULL)
X	{
X		fprintf( stderr, "%s: cannot connect to %s\n",
X			ProgramName, GRV.DisplayName );
X		exit( -1 );
X	}
X
X	DefScreen = DefaultScreen( DefDpy );
X
X	PreInitGraphics( DefDpy );
X
X	/* Get the modifier mapping from the server. */
X	UpdateModifierMap(DefDpy);
X
X	/* Set up the error handling function. */
X	XSetErrorHandler(ErrorHandler);
X
X	/* Tell server we need to get mapping requests.
X	 * ErrorSensitive is used to check for the possibility
X	 * of another window manager running, stuff in the DB routines
X	 * generates warnings.
X	 */
X	ErrorSensitive("Perhaps there is another window manager running?");
X
X	/* put all resources into global OlwmDB and set olwm variables */
X	GetDefaults(DefDpy, commandlineDB);
X
X
X	/* this can be useful for debuging strange client behaivior */
X	if (GRV.Synchronize)
X		XSynchronize(DefDpy, True);
X
X	XSelectInput( DefDpy, RootWindow(DefDpy, DefScreen),
X			KeyPressMask | SubstructureRedirectMask |
X			ButtonPressMask | ButtonReleaseMask |
X			Button1MotionMask | Button2MotionMask |
X			EnterWindowMask | PropertyChangeMask );
X	XSync(DefDpy, False);
X	ErrorInsensitive(DefDpy);
X
X	/* set workspace color (not an update - first time) */
X	UpdWorkspace( DefDpy, RM_WORKSPACECOLOR, False );
X
X	/* Init graphics stuff. */
X	InitGraphics( DefDpy );
X
X	/* Initialize the atoms we will need to communicate with
X	 * Open Look clients.
X	 */
X	InitAtoms(DefDpy);
X
X	/* Initialize the database. */
X	WIInit( DefDpy );
X
X	/* Initialise all types of window classes */
X	initWinClasses(DefDpy);
X
X	/* initialise the group module */
X	GroupInit();
X
X	/*
X	 * Force child processes to disinherit the TCP file descriptor.
X	 * This helps shell commands forked and exec'ed from menus
X	 * to work properly.
X	 */
X	if (fcntl(ConnectionNumber(DefDpy), F_SETFD, 1) == -1)
X	{
X		perror( "olvwm: child cannot disinherit TCP fd" );
X		exit( -1 );
X	}
X
X	/* Add the root window to the window database. */
X	winroot = MakeRoot(DefDpy, NULL);
X
X	/* initialize colormap focus stuff */
X	ColorFocusInit(DefDpy, winroot);
X
X	/*
X	 * Make an input only window that is invisible.
X	 * This window will have the focus when no client
X	 * window has the focus.  This is done so olwm
X	 * can beep at the user when they hit a key while
X	 * no window has the input focus.
X	 */
X	MakeNoFocus(DefDpy, winroot);
X
X	/* Set the focus to the NoFocusWin.
X	 * 	(RevertToNone is cast from long to 
X	 *	int - lint will warn) 
X	 */
X	XSetInputFocus(DefDpy, NoFocusWin, RevertToParent, CurrentTime);
X
X	/*
X	 * Initialize the virtual desktop
X	 */
X	MakeVirtualDesktop( DefDpy );
X	MakeVDM( DefDpy );
X
X	/* initialise the icon-slot module */
X	/* This must now follow virtual initialization */
X	SlotInit(DefDpy);
X
X	/*
X	 * NB:  This is an SDO hack. . .
X	 */
X	XSetErrorHandler(IgnoreErrors);
X	if (GRV.ReparentFlag)
X		ReparentTree(DefDpy);
X
X	/* Set up the error handling function. */
X	/* NB:  This used to be done before, but now that olwm has a child
X	 * window, reparenting it causes colormap errors ignore by non-child
X	 * windows
X	 */
X	XSetErrorHandler(ErrorHandler);
X
X
X	/*
X	 * The following code is temporary, being used to generate the
X	 * menus on the frame.
X	 */
X	InitMenus(DefDpy);
X	MenuCreate(DefDpy, &IconFullMenuSticky);
X	MenuCreate(DefDpy, &IconFullMenuUnsticky);
X	MenuCreate(DefDpy, &FrameNormMenuSticky);
X	MenuCreate(DefDpy, &FrameNormMenuUnsticky);
X	MenuCreate(DefDpy, &FrameFullMenuSticky);
X	MenuCreate(DefDpy, &FrameFullMenuUnsticky);
X	MenuCreate(DefDpy, &FrameLimMenu);
X	MenuCreate(DefDpy, &DismissMenu);
X	InitUserMenu(DefDpy);
X
X	if (GRV.Beep != BeepNever)
X	    XBell(DefDpy, 100);
X	
X	if (GRV.AutoShowRootMenu) {
X	    RootMenu->x = GRV.AutoRootMenuX;
X	    RootMenu->y = GRV.AutoRootMenuY;
X	    MakeMenu(DefDpy, NULL, RootMenu, -1);
X	}
X
X	EventLoop( DefDpy );
X
X	/*NOTREACHED*/
X}
X
X
X/* 
X * parseCommandline - parse the command line arguments into a resource
X *	database
X */
static void
parseCommandline( argc, argv, tmpDB )
int		*argc;
char		*argv[];
XXrmDatabase	*tmpDB;
X{
X	char	*p, *fullName, *saveName;
X
X	/* resource instance name (aka AppName) should be simply the name of 
X	 * the program, not the full pathname
X	 */
X	fullName = MemNewString( ProgramName );
X	saveName = strtok( fullName, "/" );
X	for( p = strtok(NULL, "/"); p != NULL; p = strtok(NULL, "/") )
X			saveName = p;
X	if ( !strcmp( saveName, ProgramName ) )
X		AppName = ProgramName;
X	else
X		AppName = MemNewString( saveName );
X	MemFree( fullName );
X
X	/* REMIND - if AppName is used when parsing command line options,
X	 * how will -name arg override it for other command line options given?
X	 */
X	XrmParseCommand( tmpDB, optionTable, OPTION_TABLE_ENTRIES,
X			 AppName, argc, argv );
X
X	/* check to see if there are any arguments left unparsed */
X	if ( *argc != 1 )
X	{
X		/* check to see if it's -help */
X		if ( argv[1][0] == '-' && argv[1][1] == 'h' )
X			usage("Command line arguments accepted", "are:");
X		else
X			usage("Unknown argument(s)", "encountered");
X	}
X}
X
X
X/*
X * InitAtoms -- initialize the atoms needed to communicate with Open
X *	Look clients
X */
static
InitAtoms(dpy)
Display	*dpy;
X{
X	/* ICCCM specific flags */
X	AtomColorMapWindows = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
X	AtomWMState = XInternAtom(dpy, "WM_STATE", False);
X	AtomChangeState = XInternAtom(dpy, "WM_CHANGE_STATE" , False);
X	AtomProtocols = XInternAtom(dpy, "WM_PROTOCOLS" , False);
X	AtomTakeFocus = XInternAtom(dpy, "WM_TAKE_FOCUS" , False);
X	AtomSaveYourself = XInternAtom(dpy, "WM_SAVE_YOURSELF" , False);
X	AtomDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW" , False);
X	AtomClass = XInternAtom(dpy, "WM_CLASS", False);
X
X	/* OpenLook specific flags */
X	AtomWinAttr = XInternAtom(dpy, "_OL_WIN_ATTR" , False);
X	AtomPushpinState = XInternAtom(dpy, "_OL_PIN_STATE" , False);
X	AtomWindowBusy = XInternAtom(dpy, "_OL_WIN_BUSY" , False);
X	AtomLeftFooter = XInternAtom(dpy, "_OL_WINMSG_ERROR" , False);
X	AtomRightFooter = XInternAtom(dpy, "_OL_WINMSG_STATE" , False);
X	AtomShowProperties = XInternAtom(dpy, "_OL_SHOW_PROPS" , False);
X	AtomWMApplyProperties = XInternAtom(dpy, "_OL_PROPS_APPLY" , False);
X	AtomWMResetProperties = XInternAtom(dpy, "_OL_PROPS_RESET" , False);
X	AtomPinOut = XInternAtom(dpy, "_OL_PIN_OUT" , False);
X	AtomDecorResize = XInternAtom(dpy, "_OL_DECOR_RESIZE" , False);
X	AtomWTBase = XInternAtom(dpy, "_OL_WT_BASE" , False);
X	AtomDecorFooter = XInternAtom(dpy, "_OL_DECOR_FOOTER" , False);
X	AtomDecorAdd = XInternAtom(dpy, "_OL_DECOR_ADD" , False);
X	AtomDecorDelete = XInternAtom(dpy, "_OL_DECOR_DEL" , False);
X	AtomDecorPin = XInternAtom(dpy, "_OL_DECOR_PIN" , False);
X	AtomWTProp = XInternAtom(dpy, "_OL_WT_PROP" , False);
X	AtomWTCmd = XInternAtom(dpy, "_OL_WT_CMD" , False);
X	AtomPinIn = XInternAtom(dpy, "_OL_PIN_IN" , False);
X	AtomNone = XInternAtom(dpy, "_OL_NONE" , False);
X	AtomWTNotice = XInternAtom(dpy, "_OL_WT_NOTICE" , False);
X	AtomMenuFull = XInternAtom(dpy, "_OL_MENU_FULL" , False);
X	AtomDecorHeader = XInternAtom(dpy, "_OL_DECOR_HEADER" , False);
X	AtomWTHelp = XInternAtom(dpy, "_OL_WT_HELP" , False);
X	AtomMenuLimited = XInternAtom(dpy, "_OL_MENU_LIMITED" , False);
X	AtomDecorClose = XInternAtom(dpy, "_OL_DECOR_CLOSE" , False);
X	AtomWTOther = XInternAtom(dpy, "_OL_WT_OTHER" , False);
X	AtomOlwmTimestamp = XInternAtom(dpy,"_OLWM_TIMESTAMP",False);
X	AtomDfltBtn = XInternAtom(dpy, "_OL_DFLT_BTN", False);
X
X	/* ICCCM selection atoms */
X	AtomTargets = XInternAtom(dpy,"TARGETS",False);
X	AtomMultiple = XInternAtom(dpy,"MULTIPLE",False);
X	AtomTimestamp = XInternAtom(dpy,"TIMESTAMP",False);
X	AtomListLength = XInternAtom(dpy,"LIST_LENGTH",False);
X	AtomLength = XInternAtom(dpy,"LENGTH",False);
X}
X
static void
initWinClasses(dpy)
Display *dpy;
X{
X#ifdef DEBUG
X	printf("initialising classes\n");
X#endif
X	FrameInit(dpy);
X	IconInit(dpy);
X	ResizeInit(dpy);
X	ColormapInit(dpy);
X	ButtonInit(dpy);
X	BusyInit(dpy);
X	MenuInit(dpy);
X	RootInit(dpy);
X	NoFocusInit(dpy);
X	PushPinInit(dpy);
X	PaneInit(dpy);
X	IconPaneInit(dpy);
X}
X
X
X/*
X * Exit -- exit routine called by menus.
X *	Kill all running applications.
X */
XExit(dpy)
Display	*dpy;
X{
X	extern void *ClientKill();
X	ListApply(ActiveClientList, ClientKill, True);
X	XSync(dpy, True);
X	exit(0);
X	/*NOTREACHED*/
X}
X
X
static void
cleanup()
X{
X	extern void *UnparentClient();
X
X	/*
X	 * Another SDO hack . . .
X	 */
X	XSetErrorHandler(IgnoreErrors);
X	VirtualCleanup(DefDpy);
X
X	/* Reset the input focus so it will be
X	 * RevertToRoot instead of RevertToNone.
X	 * If we don't do this, when OLWM exits
X	 * the user won't be able to get any client
X	 * window to get the focus.
X	 * 	(RevertToPointerRoot is cast from long to 
X	 *	int - lint will warn)
X	 */
X	XSetInputFocus(DefDpy, PointerRoot, RevertToPointerRoot,CurrentTime);
X
X	/*
X	 * Go through the list of windows.  Unmap all icons that are on the
X	 * screen.  Reparent all windows back to the root, suitably offset
X	 * according to their window-gravities.  Also remap all non-withdrawn
X	 * windows, and remove all Withdrawn windows from the save-set (so
X	 * they don't get remapped.  REMIND: We have to do this because
X	 * Withdrawn windows are still left reparented inside the frame; this
X	 * shouldn't be the case.
X	 */
X	ListApply(ActiveClientList,UnparentClient,NULL);
X
X	/* Re-install the default colormap. */
X	InstallColormap(DefDpy, WIGetInfo(DefaultRootWindow(DefDpy)));
X
X	/* If we set the root's background, restore it. */
X	if (GRV.WorkspaceColor == NULL || *(GRV.WorkspaceColor) != '\0') {
X	    XSetWindowBackgroundPixmap(DefDpy, DefaultRootWindow(DefDpy),
X				       None);
X	    XClearWindow(DefDpy, DefaultRootWindow(DefDpy));
X	}
X
X	XSync(DefDpy, True);
X}
X
X
X/* Clean up and then re-exec argv. */
int
RestartOLWM()
X{
X    cleanup();
X    execvp(argVec[0], argVec);
X    ErrorGeneral("cannot restart");
X    /*NOTREACHED*/
X}
X
X
X/* Clean up and then exit. */
int
XExitOLWM()
X{
X    cleanup();
X    exit(0);
X}
X
X
X/*
X * HandleChildSignal - keep track of children that have died
X */
static void
HandleChildSignal()
X{
X	++DeadChildren;
X}
X
X/*
X * ReapChildren - wait() for all dead child processes
X */
void
ReapChildren()
X{
X	int oldmask;
X	int pid;
X	union wait status;
X
X	oldmask = sigblock(sigmask(SIGCHLD));
X	while (DeadChildren>0)
X	{
X		pid = wait3(&status, WNOHANG, (struct rusage *)0);
X		if (pid == 0)
X		{
X			fputs("olvwm: got SIGCHLD but found no children\n", stderr);
X			DeadChildren = 0;
X			break;
X		}
X		if (WIFSTOPPED(status))
X		{
X			kill(pid, SIGKILL);
X		}
X		--DeadChildren;
X	}
X	(void) sigsetmask(oldmask);
X}
X
X/*
X * usage(s1, s2)	-- print informative message regarding usage
X */
static
usage(s1, s2)
char	*s1, *s2;
X{
X    fprintf(stderr, "%s %s\n", s1, s2);
X    fprintf(stderr,
X	"usage: %s [-2d] [-3d] [-click] [-follow] [-parent]\n", ProgramName);
X    fputs(
X	"\t[-display <display>] [-name <classname>] [-xrm <rsrcstring>]\n",
X	stderr);
X    fputs("\t[-all] [-debug] [-orphans] [-synchronize]\n", stderr);
X    exit(1);
X}
X
X/*
X * updateEnvp - modify environment vector
X *
X * Purpose - Duplicate environment vector and set the named environment 
X *	     variable to the value passed.  Notice that space is created 
X *	     inside this routine for the new environment vector, but not freed.
X *
X * Input:
X *	envp	 - current environment vector
X *	
X *	variable - environment variable to be changed
X *
X *	newValue - new value for the variable
X *
X * Returns:
X *	New environment vector.
X */
static char **
updateEnvp( envp, variable, newValue )
char	**envp;
char	*variable;
char	*newValue;
X{
X	int	count;		/* counter for number of env variables */
X	int	numVariables;
X	char	**newEnvp;
X	char	*newSetting;
X
X	/* create new string to be put into environment */
X	/* need space for null at end, and "=" in the middle */
X	newSetting = (char *)MemAlloc( (unsigned)(strlen( variable ) 
X					+ strlen( newValue ) + 2 )
X				      );
X	sprintf( newSetting, "%s=%s", variable, newValue );
X
X	/* count existing env vector entries and make pointers in newEnvp */
X	for ( count = 0 ; envp[count] != NULL ; count++ )
X		;
X
X	/* number of variables in env vector */
X	numVariables = count;
X
X	/* make space for numVariables + 2 pointers in newEnvp 
X	 * (+ 1 for the NULL at end and + 1 in case the variable being 
X	 * changed isn't already in the environment)
X	 */ 
X	newEnvp = (char **)MemAlloc( (unsigned)(
X					sizeof(char *) * (numVariables + 2)
X				      ));
X
X	/* copy existing env vector */
X	for ( count = 0 ; count < numVariables ; count++ )
X		newEnvp[count] = MemNewString( envp[count] ); 
X	
X	/* search through, checking for variable in question */
X	for ( count = 0 ; count < numVariables ; count++ )
X		if ( !strcmp( newEnvp[count], variable ) )
X			break;
X	
X	newEnvp[count] = newSetting;
X
X	if ( count == numVariables )	/* finished loop without match */
X		numVariables++;		/* added 1 more var to the env */
X	else
X		MemFree( newEnvp[numVariables+1] );	/* don't need */
X
X	/* make sure the last entry in the vector is NULL */
X	newEnvp[numVariables] = NULL;
X
X	return( newEnvp );
X}
END_OF_FILE
if test 24540 -ne `wc -c <'olwm.c'`; then
    echo shar: \"'olwm.c'\" unpacked with wrong size!
fi
# end of 'olwm.c'
fi
if test -f 'winicon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winicon.c'\"
else
echo shar: Extracting \"'winicon.c'\" \(22643 characters\)
sed "s/^X//" >'winicon.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[] = "@(#)winicon.c	1.3 olvwm version 4/17/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winicon.c 25.11 90/05/30 Crucible";
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <string.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 "menu.h"
X#include "globals.h"
X#include "slots.h"
X#include "group.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern GC IconNormalGC;
extern GC IconSelectedGC;
extern GC IconUnselectedGC;
extern GC IconBorderGC;
extern GC DrawBackgroundGC;
extern GC DrawSelectedGC;
extern GC RootGC;
X
extern Graphics_info	*olgx_gisnormal;
extern Menu 		IconFullMenuSticky, IconFullMenuUnsticky;
X
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* events in the icon window that are interesting */
X#define ICON_EVENT_MASK        (ButtonPressMask | ButtonReleaseMask | \
X				ExposureMask | Button1MotionMask)
X
X/* border sizes, in pixels */
X#define ICON_HORZBORDER 3
X#define ICON_VERTBORDER 3
X
X/* Class function vector */
static ClassIconFrame classIconFrame;
X
X/***************************************************************************
X* forward-declared functions
X***************************************************************************/
X
X/***************************************************************************
X* private event functions
X***************************************************************************/
X
static int
menuPressIcon(dpy,event,iconInfo)
Display *dpy;
XXEvent *event;
WinIconFrame *iconInfo;
X{
X        if (iconInfo->fcore.menu)
X            MenuShow(dpy,iconInfo,iconInfo->fcore.menu,event);
X}
X
static int
selectDoubleClickIcon(dpy,event,iconInfo)
Display *dpy;
XXEvent *event;
WinIconFrame *iconInfo;
X{
X	StateIconNorm(iconInfo->core.client);
X}
X
static int
adjustClickIcon(dpy,event,iconInfo)
Display *dpy;
XXEvent *event;
WinIconFrame *iconInfo;
X{
X        ToggleSelection(iconInfo->core.client, event->xbutton.time);
X}
X
static int
eventKeyPress(dpy, event, iconInfo)
X    Display	*dpy;
X    XEvent	*event;
X    WinIconFrame	*iconInfo;
X
X{
extern Window	VDM;
X/*
X * Since the vdm is the only icon which we get this event for, we don't
X * have to check to see which it is . . .
X */
X
X    event->xany.window = VDM;
X    CheckVDMMove(dpy, event);
X}
X
X/*
X * eventEnterNotify -- if in follow-mouse and pointer enters this tree of windows,
X *      set the focus
X */
static int
eventEnterNotify(dpy, event, iconInfo)
Display *dpy;
XXEvent  *event;
WinIconFrame *iconInfo;
X{
X    if (GRV.FocusFollowsMouse && (event->xcrossing.detail != NotifyInferior))
X	XSetInputFocus(dpy, iconInfo->core.self, RevertToNone, CurrentTime);
X}
X
X/*
X * eventLeaveNotify -- if in follow-mouse and pointer enters this tree of windows,
X *      set the focus
X */
static int
eventLeaveNotify(dpy, event, iconInfo)
Display *dpy;
XXEvent  *event;
WinIconFrame *iconInfo;
X{
X    extern Window	NoFocusWin;
X
X    if (GRV.FocusFollowsMouse && (event->xcrossing.detail != NotifyInferior))
X	XSetInputFocus(dpy, NoFocusWin, RevertToNone, CurrentTime);
X}
X 
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/* selectDragIcon -- the user has held the select button down long enough
X * to initiate a drag.  Unpin the icon slot and start a window-move.
X */
static int
selectDragIcon(dpy, ev, iframe, lastpress)
Display *dpy;
XXEvent *ev;
WinIconFrame *iframe;
XXButtonEvent *lastpress;
X{
X	SlotFree(iframe);
X	iframe->fManuallyPositioned = True;
X	UserMoveWindows(dpy, lastpress, iframe);
X}
X
X
X/*
X * newconfigIcon -- compute a new configuration of icon window
X */
static int
newconfigIcon(winInfo, pxcre)
WinIconFrame *winInfo;
XXConfigureRequestEvent *pxcre;
X{
X        Client *cli = winInfo->core.client;
X        WinPane *winPane = (WinPane *)winInfo->fcore.panewin;
X        int neww;
X        int newh;
X
X        neww = winInfo->fcore.panewin->core.width + 2*widthBothIcon(winInfo);
X        newh = winInfo->fcore.panewin->core.height + heightTopIcon(winInfo) +
X            heightBottomIcon(winInfo);
X
X        if (neww != winInfo->core.width)
X        {
X                winInfo->core.width = neww;
X                winInfo->core.dirtyconfig |= CWWidth;
X        }
X
X        if (newh != winInfo->core.height)
X        {
X                winInfo->core.height = newh;
X                winInfo->core.dirtyconfig |= CWHeight;
X        }
X
X        if (winInfo->core.dirtyconfig)
X        {
X                (WinFunc(winPane,core.newposfunc))(winPane, 
X			widthBothIcon(winInfo), heightTopIcon(winInfo));
X        }
X
X	if (winInfo->core.dirtyconfig & (CWWidth | CWHeight))
X	{
X                IconChangeName(winInfo,PANEWINOFCLIENT(cli));
X	}
X
X	return winInfo->core.dirtyconfig;
X}
X
X/*
X * newposIcon -- the icon is being moved to a new x,y location.  If the icon
X *	slot has not yet been allocated, do so; otherwise, blindly accept
X *	the x,y position.
X */
static int
newposIcon(winInfo,x,y)
WinIconFrame *winInfo;
int x,y;
X{
X	WinNewPosFunc(winInfo,x,y);
X	if ((winInfo->iconslot == NULL) && 
X	    (winInfo->core.client->groupmask != GROUP_DEPENDENT))
X	{
X		SlotAlloc(winInfo, winInfo->fManuallyPositioned, GRV.FSnapToGrid);
X	}
X	return winInfo->core.dirtyconfig;
X}
X
X
static void
drawDashedRect(dpy, win, x, y, w, h)
X    Display *dpy;
X    Window win;
X    int x, y, w, h;
X{
X    XPoint pts[5];
X
X    pts[0].x = x;	pts[0].y = y;
X    pts[1].x = x;	pts[1].y = y + h;
X    pts[2].x = x + w;	pts[2].y = y + h;
X    pts[3].x = x + w;	pts[3].y = y;
X    pts[4].x = x;	pts[4].y = y;
X
X    /*
X     * The following is necessary because IconBorderGC uses the LineOnOffDash
X     * line-style, which is faster than LineDoubleDash on some servers.
X     */
X    XDrawLines(dpy, win, IconUnselectedGC, pts, 5, CoordModeOrigin);
X    XDrawLines(dpy, win, IconBorderGC, pts, 5, CoordModeOrigin);
X}
X
X/*
X * drawIconBorder -- based on the value of select, draw the border for an icon
X */
static void
drawIconBorder(dpy, winInfo, select)
Display *dpy;
WinIconFrame *winInfo;
Bool    select;
X{
X	int x, y;           /* values for use with */
X	unsigned int width, height;  /* rectangle drawn for border */
X	Window w = winInfo->core.self;
X	
X	x = y = 0;
X	width = winInfo->core.width - 1;
X	height = winInfo->core.height - 1;
X
X	/*
X	 * If 3D is used, give "borderless" icons.  Otherwise, give black and 
X	 * white borders.
X	 */
X	if (select) {
X	    XDrawRectangle(dpy, w, IconSelectedGC,
X			   x, y, width, height );
X	    XDrawRectangle(dpy, w, IconSelectedGC,
X			   x+1, y+1, width-2, height-2 );
X	    XDrawRectangle(dpy, w, IconSelectedGC,
X			   x+2, y+2, width-4, height-4 );
X	} else {
X	    XDrawRectangle(dpy, w, IconUnselectedGC,
X			   x, y, width, height);
X	    if (GRV.F3dUsed) {
X		XDrawRectangle(dpy, w, IconUnselectedGC, 
X			       x+1, y+1, width-2, height-2);
X	    } else {
X#ifdef notdef
X		XDrawRectangle(dpy, w, IconBorderGC, 
X			       x+1, y+1, width-2, height-2);
X#endif /* notdef */
X		drawDashedRect(dpy, w, x+1, y+1, width-2, height-2);
X	    }
X
X	    XDrawRectangle(dpy, w, IconUnselectedGC,
X			   x+2, y+2, width-4, height-4);
X	}
X
X#ifdef notdef
X/*
X * This stuff was used for the attempt at 3D-look icons.
X * It has been abandoned in favor of the "borderless" icon look.
X */
X
X        /* initial values for first rectangle */
X        x = 0;
X        y = 0;
X        /* need to subtract one, based on how XDrawRectangle works */
X        width = winInfo->core.width - 1;
X        height = winInfo->core.height - 1;
X
X        /* draw three rectangles for border */
X	for ( rectangle = 0 ; rectangle < 3 ; rectangle++ )
X	{
X              switch( rectangle )
X              {
X              case 0:         /* outermost rectangle */
X                      if ( GRV.F3dUsed )
X                      {
X                              if ( select )
X                                      olgxState = OLGX_INVOKED;
X                              else
X                                      olgxState = OLGX_NORMAL;
X
X                              olgx_draw_box( olgx_gisnormal,
X                                             winInfo->core.self,
X                                             x, y, width+1, height+1,
X                                             olgxState, 0 );
X                              drawRectangle = False;
X                      }
X                      else
X                      {
X                              highlightGC = select
X                                              ? DrawSelectedGC
X                                              : DrawBackgroundGC;
X                              drawRectangle = True;
X                      }
X                      break;
X              case 1:         /* middle rectangle */
X                      if ( select )
X                                      highlightGC = DrawSelectedGC;
X                      else if ( GRV.F3dUsed )
X                              highlightGC = DrawBackgroundGC;
X                      else    /* REMIND eventually need to handle
X                               * IconBorder resource when 2d & ColorDisplay
X                               */
X                              highlightGC = IconBorderGC;
X                      drawRectangle = True;
X                      break;
X              case 2:         /* innermost rectangle */
X              default:
X                      highlightGC = select ? DrawSelectedGC
X                                           : DrawBackgroundGC;
X                      drawRectangle = True;
X                      break;
X              }
X
X              if ( drawRectangle )
X                      XDrawRectangle( dpy, winInfo->core.self, highlightGC,
X                                      x, y, width, height );
X              x++;
X              y++;
X              width -= 2;
X              height -= 2;
X      }
X#endif /* notdef */
X}
X
X/*
X * drawIcon -- draw the icon window
X */
X/*ARGSUSED*/  /* dpy arg will be used when multiple Displays supported */
static int
drawIcon(dpy, winInfo)
Display       *dpy;
WinIconFrame *winInfo;
X{
X	extern GC	IconSelectedGC, IconNormalGC;
X	Window		frameWin = winInfo->core.self;
X
X	XFillRectangle(dpy, frameWin, IconUnselectedGC, 0, 0,
X		       winInfo->core.width, winInfo->core.height);
X
X	/* draw icon name */
X	XDrawString(dpy, frameWin, IconNormalGC, winInfo->nameX,
X		    winInfo->nameY, winInfo->fcore.name, winInfo->nameLength);
X
X	/* draw border */
X	drawIconBorder(dpy, winInfo, winInfo->core.client->isSelected);
X}
X
X
X/*
X * DestroyIcon -- destroy the icon window resources and free any allocated
X *    data.
X */
static int
destroyIcon(dpy, winInfo)
Display       *dpy;
WinIconFrame *winInfo;
X{
X      /* free our data and throw away window */
X      SlotFree(winInfo);
X      ListDestroy(winInfo->core.children);
X      XFree(winInfo->fcore.name);
X      XUndefineCursor(dpy, winInfo->core.self);
X      XDestroyWindow(dpy,winInfo->core.self);
X      WIUninstallInfo(winInfo->core.self);
X      MemFree(winInfo);
X}
X
X
static int
heightTopIcon(win)
WinIconFrame	*win;
X{
X	WinIconPane *winPane = (WinIconPane *)(win->fcore.panewin);
X	int basicbottom;
X
X	if (winPane->iconClientWindow)
X	{
X	    return ICON_VERTBORDER;
X	}
X	else
X	{
X	    basicbottom = ICON_VERTBORDER+GRV.IconFontInfo->max_bounds.ascent+
X		GRV.IconFontInfo->max_bounds.descent;
X	    if (winPane->core.height > ICON_WIN_HEIGHT - ICON_VERTBORDER - basicbottom)
X		return ICON_VERTBORDER;
X	    else
X		return (ICON_WIN_HEIGHT-ICON_VERTBORDER-basicbottom-winPane->core.height)/2+ICON_VERTBORDER;
X	}
X}
X
static int
heightBottomIcon(win)
WinIconFrame	*win;
X{
X	WinIconPane *winPane = (WinIconPane *)(win->fcore.panewin);
X	int basicbottom;
X
X	if (winPane->iconClientWindow)
X	{
X	    return ICON_VERTBORDER;
X	}
X	else
X	{
X#ifdef OBSOLETE
X	    basicbottom = ICON_VERTBORDER+GRV.IconFontInfo->max_bounds.ascent+
X		GRV.IconFontInfo->max_bounds.descent;
X#endif
X	    basicbottom = winPane->core.height/2;
X	    if (winPane->core.height > ICON_WIN_HEIGHT - ICON_VERTBORDER - basicbottom)
X		return basicbottom;
X	    else
X		return (ICON_WIN_HEIGHT-ICON_VERTBORDER-basicbottom-winPane->core.height)/2+basicbottom;
X	}
X}
X
X/* The icon pane has the same border width on either side, so this function
X * is used to calculate both border widths.
X */
static int
widthBothIcon(win)
WinIconFrame	*win;
X{
X	WinIconPane *winPane = (WinIconPane *)(win->fcore.panewin);
X
X	if (winPane->iconClientWindow)
X	{
X	    return ICON_HORZBORDER;
X	}
X	else
X	{
X	    if (winPane->core.width < ICON_WIN_WIDTH - 2*ICON_HORZBORDER)
X	    {
X		return (ICON_WIN_WIDTH-winPane->core.width)/2;
X	    }
X	    else
X		return ICON_HORZBORDER;
X	}
X}
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeIcon  -- create the icon window. Return a WinIconFrame structure.
X *	Note that unlike most Make functions, icons are not mapped right
X *	away.
X */
WinIconFrame *
MakeIcon(cli,panewin,paneattrs)
Client *cli;
Window panewin;		
XXWindowAttributes *paneattrs;
X{
X	Display		*dpy = cli->dpy;
X	int		screen = cli->screen;
X	WinIconFrame	*w;
X        XSetWindowAttributes attributes;
X        unsigned long   valuemask;
X	XWMHints	*wmHints = cli->wmHints;
X
X	/* create the window structure */
X	w = MemNew(WinIconFrame);
X	w->core.kind = WIN_ICON;
X	w->class = &classIconFrame;
X	w->core.parent = NULL;
X	w->core.children = NULL;
X	w->core.client = cli;
X	w->core.width = ICON_WIN_WIDTH;
X	w->core.height = ICON_WIN_HEIGHT;
X
X	/* fill out  the associated structure */
X	w->core.dirtyconfig = CWX|CWY|CWWidth|CWHeight;
X	w->core.colormap = None;
X	w->core.exposures = NULL;
X
X	/* create the icon frame */
X	valuemask = CWEventMask;
X	attributes.event_mask = ICON_EVENT_MASK;
X	if (panewin == VDM)
X	    attributes.event_mask |= (KeyPressMask | EnterWindowMask);
X	w->core.self = XCreateWindow(dpy, RootWindow(dpy, screen), 
X			 w->core.x, w->core.y, 1, 1, 0,
X			 DefaultDepth(dpy, screen), InputOutput,
X			 DefaultVisual(dpy, screen), valuemask, &attributes);
X
X	/* install icon frame in client */
X	cli->iconwin = w;	/* REMIND: should be called cli->iconframe */
X	
X	/* set the position - either from position or icon slot */
X	if (wmHints && (wmHints->flags & IconPositionHint)) 
X	{
X		w->core.x = wmHints->icon_x;
X		w->core.y = wmHints->icon_y;
X		w->fManuallyPositioned = True;
X	}
X	else
X	{
X		/* to be fixed up at config time */
X		w->core.x = w->core.y = 0;
X		w->fManuallyPositioned = False;
X	}
X
X	/* register the window */
X	WIInstallInfo(w);
X
X	/* set cursor for frame */
X	XDefineCursor( dpy, w->core.self, GRV.IconPointer );
X
X	IconChangeName(w,panewin);
X
X	if (cli->sticky)
X            w->fcore.menu = &IconFullMenuSticky;
X        else w->fcore.menu = &IconFullMenuUnsticky;
X
X	return w;
X}
X
void
IconInit(dpy)
Display *dpy;
X{
X	classIconFrame.core.kind = WIN_ICON;
X	classIconFrame.core.xevents[Expose] = WinEventExpose;
X	classIconFrame.core.xevents[ButtonRelease] = GFrameEventButtonRelease;
X	classIconFrame.core.xevents[MotionNotify] = GFrameEventMotionNotify;
X	classIconFrame.core.xevents[ButtonPress] = GFrameEventButtonPress;
X	classIconFrame.core.xevents[EnterNotify] = eventEnterNotify;
X	classIconFrame.core.xevents[LeaveNotify] = eventLeaveNotify;
X	classIconFrame.core.xevents[KeyPress] = eventKeyPress;
X	classIconFrame.core.focusfunc = NULL;
X	classIconFrame.core.drawfunc = drawIcon;
X	classIconFrame.core.destroyfunc = destroyIcon;
X	classIconFrame.core.selectfunc = GFrameSelect;
X	classIconFrame.core.newconfigfunc = newconfigIcon;
X	classIconFrame.core.newposfunc = newposIcon;
X	classIconFrame.core.setconfigfunc = GFrameSetConfigFunc;
X	classIconFrame.core.createcallback = NULL;
X	classIconFrame.core.heightfunc = NULL;
X	classIconFrame.core.widthfunc =  NULL;
X	classIconFrame.fcore.heighttop = heightTopIcon;
X	classIconFrame.fcore.heightbottom = heightBottomIcon;
X	classIconFrame.fcore.widthleft = widthBothIcon;
X	classIconFrame.fcore.widthright = widthBothIcon;
X	classIconFrame.fcore.menuPress = menuPressIcon;
X	classIconFrame.fcore.adjustPress = NULL;
X	classIconFrame.fcore.adjustClick = adjustClickIcon;
X	classIconFrame.fcore.selectPress = NULL;
X	classIconFrame.fcore.selectClick = NULL;
X	classIconFrame.fcore.selectDoubleClick = selectDoubleClickIcon;
X	classIconFrame.fcore.selectDrag = selectDragIcon;
X}
X
X/*
X * DrawIconToWindowLines -- draw the open (close) lines when a window is
X *      becoming an icon or vice-versa
X */
void
DrawIconToWindowLines(dpy, iconInfo, winInfo)
Display *dpy;
WinPaneFrame *winInfo;
WinIconFrame *iconInfo;
X{
X        int     ii;
X
X        XGrabServer(dpy);
X
X        for(ii=0; ii < 3 ; ii++)
X        {
X                /* draw the close lines */
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X      	                        iconInfo->core.x,
X                                iconInfo->core.y,
X                                winInfo->core.x,
X                                winInfo->core.y);
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                iconInfo->core.x,
X                                (int)(iconInfo->core.y + iconInfo->core.height),
X                                winInfo->core.x,
X                                (int)(winInfo->core.y + winInfo->core.height));
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                (int)(iconInfo->core.x + iconInfo->core.width),
X                                iconInfo->core.y,
X                                (int)(winInfo->core.x + winInfo->core.width),
X                                winInfo->core.y);
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                (int)(iconInfo->core.x + iconInfo->core.width),
X                                (int)(iconInfo->core.y + iconInfo->core.height),
X                                (int)(winInfo->core.x + winInfo->core.width),
X                                (int)(winInfo->core.y + winInfo->core.height));
X
X                XFlush(dpy);
X                /* erase the close lines */
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                iconInfo->core.x,
X                                iconInfo->core.y,
X                                winInfo->core.x,
X                                winInfo->core.y);
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                iconInfo->core.x,
X                                (int)(iconInfo->core.y + iconInfo->core.height),
X                                winInfo->core.x,
X                                (int)(winInfo->core.y + winInfo->core.height));
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                (int)(iconInfo->core.x + iconInfo->core.width),
X                                iconInfo->core.y,
X                                (int)(winInfo->core.x + winInfo->core.width),
X                                winInfo->core.y);
X                XDrawLine(dpy, RootWindow(dpy, DefaultScreen(dpy)), RootGC,
X                                (int)(iconInfo->core.x + iconInfo->core.width),
X                                (int)(iconInfo->core.y + iconInfo->core.height),
X                                (int)(winInfo->core.x + winInfo->core.width),
X                                (int)(winInfo->core.y + winInfo->core.height));
X                XFlush(dpy);
X        }
X
X        XUngrabServer(dpy);
X}
X
X/* IconChangeName -- the client has decided to change the name of its
X * 	icon.  Handle this.
X */
void
IconChangeName(winIcon,pane)
WinIconFrame *winIcon;
Window pane;
X{
X	Client *cli = winIcon->core.client;
X	Display *dpy = cli->dpy;
X
X	if (!XGetIconName(dpy, pane, &(winIcon->fcore.name)))
X		if (!XFetchName(dpy, pane, &(winIcon->fcore.name)))
X			winIcon->fcore.name = MemNewString(GRV.DefaultWinName);
X
X	winIcon->nameLength = strlen(winIcon->fcore.name);
X	winIcon->nameWidth = XTextWidth(GRV.IconFontInfo, winIcon->fcore.name, 
X		winIcon->nameLength);
X	winIcon->nameX = (winIcon->core.width - winIcon->nameWidth)/2;
X	/* put the title no lower than just above the selection hightlight area 
X	 * (the selection box is three pixels wide: 3+1=4).  optimally, put
X	 * it centered in the lower third of the icon window.  recall that
X	 * descent goes below the Y value used for drawing.
X	 */
X	winIcon->nameY = MIN( (winIcon->core.height - 4
X				- GRV.IconFontInfo->max_bounds.descent),
X			      5*winIcon->core.height/6 );
X
X	if (!winIcon->core.dirtyconfig)
X		(WinFunc(winIcon,core.drawfunc))(dpy,winIcon);
X}
X
X
X/*
X * Set the icon's (x,y) location explicitly.  This information is typically
X * taken from the WM_HINTS structure.  Since the coordinates specify the 
X * absolute position of the icon pane, we must subtract the icon border to get 
X * the position if the icon frame.
X */
void
IconSetPos(win,x,y)
WinIconFrame *win;
int x,y;
X{
X    (WinFunc(win,core.newposfunc))(win,x-ICON_HORZBORDER,y-ICON_VERTBORDER);
X}
X
X/*
X * IconShow -- map an icon onto the screen, handling reparenting and
X * save-sets for icon panes.
X */
void
IconShow(cli, winIcon)
X    Client *cli;
X    WinIconFrame *winIcon;
X{
X    WinIconPane *pane = (WinIconPane *)winIcon->fcore.panewin;
X
X    XReparentWindow(cli->dpy, pane->core.self, winIcon->core.self,
X			pane->core.x, pane->core.y);
X    XMapWindow(cli->dpy, pane->core.self);
X    if (pane->iconClientWindow)
X        XChangeSaveSet(cli->dpy, pane->core.self, SetModeInsert);
X    XMapWindow(cli->dpy, winIcon->core.self);
X    XMapWindow(cli->dpy, cli->virtualInactive);
X}
X
X
X/*
X * IconHide -- remove an icon from the screen, handling reparenting and
X * save-sets for icon panes.
X */
void
IconHide(cli, winIcon)
X    Client *cli;
X    WinIconFrame *winIcon;
X{
X    WinIconPane *pane = (WinIconPane *)winIcon->fcore.panewin;
X
X    XUnmapWindow(cli->dpy, winIcon->core.self);
X    XUnmapWindow(cli->dpy, pane->core.self);
X    XUnmapWindow(cli->dpy, cli->virtualInactive);
X    XReparentWindow(cli->dpy, pane->core.self, DefaultRootWindow(cli->dpy),
X			winIcon->core.x + pane->core.x,
X			winIcon->core.y + pane->core.y);
X    if (pane->iconClientWindow)
X        XChangeSaveSet(cli->dpy, pane->core.self, SetModeDelete);
X}
END_OF_FILE
if test 22643 -ne `wc -c <'winicon.c'`; then
    echo shar: \"'winicon.c'\" unpacked with wrong size!
fi
# end of 'winicon.c'
fi
echo shar: End of archive 9 \(of 16\).
cp /dev/null ark9isdone
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