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