sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) (04/29/91)
Submitted-by: sdo@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@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@uunet.uu.net argv@ora.com argv@zipcode.com