home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume15 / olvwm-3.0 / part10 < prev    next >
Text File  |  1992-02-03  |  56KB  |  2,107 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!elroy.jpl.nasa.gov!ames!pasteur!nntp
  3. From: scott.oaks@East.Sun.COM (Scott Oaks)
  4. Subject: v15i156: OpenLook Virtual Window Mgr (3.0), Part10/21
  5. Message-ID: <1992Feb4.135728.7486@pasteur.Berkeley.EDU>
  6. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  7. Nntp-Posting-Host: postgres.berkeley.edu
  8. Organization: University of California, at Berkeley
  9. References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
  10. Date: Tue, 4 Feb 1992 13:57:28 GMT
  11. Approved: dcmartin@msi.com
  12.  
  13. Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
  14. Posting-number: Volume 15, Issue 156
  15. Archive-name: olvwm-3.0/part10
  16.  
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  21. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  22. # If this archive is complete, you will see the following message at the end:
  23. #        "End of archive 10 (of 21)."
  24. # Contents:  olwm.c states.c
  25. # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:44 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'olwm.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'olwm.c'\"
  29. else
  30. echo shar: Extracting \"'olwm.c'\" \(18395 characters\)
  31. sed "s/^X//" >'olwm.c' <<'END_OF_FILE'
  32. X/*
  33. X *      (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
  34. X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
  35. X *      file for terms of the license.
  36. X */
  37. X
  38. X#ident    "@(#)olwm.c    1.1 olvwm version 1/3/92"
  39. X
  40. X/*
  41. X * Based on
  42. X#ident    "@(#)olwm.c    26.42    91/09/14 SMI"
  43. X *
  44. X */
  45. X
  46. X#include <errno.h>
  47. X#include <memory.h>
  48. X#include <signal.h>
  49. X#include <stdio.h>
  50. X#include <string.h>
  51. X
  52. X#include <sys/time.h>
  53. X#include <sys/types.h>
  54. X
  55. X#include <sys/param.h>
  56. X#include <sys/resource.h>
  57. X#include <sys/stat.h>
  58. X#include <sys/wait.h>
  59. X
  60. X#include <X11/Xos.h>
  61. X#include <X11/Xlib.h>
  62. X#include <X11/Xutil.h>
  63. X#include <X11/Xatom.h>
  64. X#include <X11/Xresource.h>
  65. X
  66. X#include "i18n.h"
  67. X#include "ollocale.h"
  68. X#include "events.h"
  69. X#include "mem.h"
  70. X#include "olwm.h"
  71. X#include "win.h"
  72. X#include "menu.h"
  73. X#include "defaults.h"
  74. X#include "resources.h"
  75. X#include "globals.h"
  76. X#include "group.h"
  77. X#include "slots.h"
  78. X
  79. X#include "patchlevel.h"
  80. X
  81. Xtypedef    void    (*VoidFunc)();
  82. X
  83. X/*
  84. X * Globals
  85. X */
  86. Xchar    *ProgramName;
  87. Xchar    *AppName;        /* strictly last component of ProgramName */
  88. XGlobalResourceVariables GRV;
  89. XXrmDatabase OlwmDB;
  90. X
  91. X
  92. X/*
  93. X * Global Quarks.  "Top" refers to the root of the resource name/instance 
  94. X * hierarchy.
  95. X */
  96. XXrmQuark TopClassQ;
  97. XXrmQuark TopInstanceQ;
  98. XXrmQuark OpenWinQ;
  99. X/*
  100. X * Quark for olwm instance -- we read resources with an instance name of
  101. X * olwm for backwards compatibility
  102. X */
  103. XXrmQuark OlwmQ;
  104. X
  105. X/* Current Display */
  106. XDisplay    *DefDpy;
  107. X
  108. X
  109. Xstatic Display *openDisplay();
  110. Xstatic void    parseCommandline();
  111. Xstatic void    sendSyncSignal();
  112. X
  113. X
  114. X/* Note that changes to RMTable instance names must also be made here !! */
  115. Xstatic    XrmOptionDescRec    optionTable[] = {
  116. X    { "-display",        ".display",    
  117. X        XrmoptionSepArg, (caddr_t) NULL },
  118. X    { "-f",            ".setInput",
  119. X        XrmoptionNoArg, (caddr_t) "follow" },
  120. X    { "-follow",        ".setInput", 
  121. X        XrmoptionNoArg, (caddr_t) "follow" },
  122. X    { "-c",         ".setInput",    
  123. X        XrmoptionNoArg, (caddr_t) "select" },
  124. X    { "-click",         ".setInput",    
  125. X        XrmoptionNoArg, (caddr_t) "select" },
  126. X    { "-2d",         ".use3D",    
  127. X        XrmoptionNoArg, (caddr_t) "False" },
  128. X    { "-3d",         ".use3D",    
  129. X        XrmoptionNoArg, (caddr_t) "True" },
  130. X    { "-parent",         ".reparentOK",    
  131. X        XrmoptionNoArg, (caddr_t) "False" },
  132. X    { "-orphans",         ".printOrphans", 
  133. X        XrmoptionNoArg, (caddr_t) "True" },
  134. X    { "-all",         ".printAll", 
  135. X        XrmoptionNoArg, (caddr_t) "True" },
  136. X    { "-synchronize",    ".synchronize",
  137. X        XrmoptionNoArg, (caddr_t) "True" },
  138. X    { "-debug",    ".printOrphans", XrmoptionNoArg, (caddr_t) "True" },
  139. X    { "-name",        ".name",    
  140. X        XrmoptionSepArg, (caddr_t) NULL },
  141. X    { "-bg",    "*Background",    XrmoptionSepArg, (caddr_t) NULL },
  142. X    { "-background", "*Background",    XrmoptionSepArg, (caddr_t) NULL },
  143. X    { "-fg",    "*Foreground",    XrmoptionSepArg, (caddr_t) NULL },
  144. X    { "-foreground","*Foreground",    XrmoptionSepArg, (caddr_t) NULL },
  145. X    { "-bd",    "*Background",    
  146. X        XrmoptionSepArg, (caddr_t) NULL },
  147. X    { "-bordercolor",    "*Background",    
  148. X        XrmoptionSepArg, (caddr_t) NULL },
  149. X    { "-fn",    "*TitleFont",    XrmoptionSepArg, (caddr_t) NULL },
  150. X    { "-font",    "*TitleFont",    XrmoptionSepArg, (caddr_t) NULL },
  151. X    { "-xrm",    NULL,        XrmoptionResArg, (caddr_t) NULL },
  152. X    { "-single",    ".singleScreen",XrmoptionNoArg, (caddr_t) "True" },
  153. X    { "-multi",    ".singleScreen",XrmoptionNoArg, (caddr_t) "False" },
  154. X    { "-syncpid",   ".syncPid",     XrmoptionSepArg, (caddr_t) NULL },
  155. X    { "-syncsignal",".syncSignal",  XrmoptionSepArg, (caddr_t) NULL },
  156. X    { "-depth",    "*depth",    XrmoptionSepArg, (caddr_t) NULL },
  157. X    { "-visual",    "*visual",    XrmoptionSepArg, (caddr_t) NULL },
  158. X#ifdef OW_I18N_L3
  159. X        { "-basiclocale", "*basicLocaleCL", XrmoptionSepArg, (caddr_t) NULL },
  160. X           { "-displaylang", "*displayLangCL", XrmoptionSepArg, (caddr_t) NULL },
  161. X           { "-inputlang",   "*inputLangCL", XrmoptionSepArg, (caddr_t) NULL },
  162. X           { "-numeric",     "*numericCL", XrmoptionSepArg, (caddr_t) NULL },
  163. X           { "-dateFormat",  "*dateFormatCL", XrmoptionSepArg, (caddr_t) NULL },
  164. X#endif /* OW_I18N_L3 */
  165. X};
  166. X#define OPTION_TABLE_ENTRIES (sizeof(optionTable)/sizeof(XrmOptionDescRec))
  167. X
  168. Xstatic void    initWinClasses();
  169. X
  170. X/* Child Process Handling */
  171. Xvoid HandleChildSignal();
  172. Xvoid ReapChildren();
  173. Xint DeadChildren = 0;
  174. Xint SlavePid;
  175. X
  176. X#ifdef ALLPLANES
  177. Xint allplanes;            /* server supports the ALLPLANES extension */
  178. X#endif
  179. X
  180. X#ifdef SHAPE
  181. XBool ShapeSupported;        /* server supports the SHAPE extension */
  182. Xint  ShapeEventBase;
  183. Xint  ShapeErrorBase;
  184. X#endif
  185. X
  186. X
  187. Xstatic char    **argVec;
  188. X
  189. X/*
  190. X * main    -- parse arguments, perform initialization, call event-loop
  191. X *
  192. X * The OpenLook window manager was written before the OpenLook
  193. X * spec. was completed.  Because of this, some of it works in
  194. X * an awkward way.  Specifically, the way a window's focus and
  195. X * select state is shown.
  196. X *
  197. X * For example, when a window is focused in click-to-focus mode
  198. X * the header gets highlighted, (black background, white text).
  199. X * As it was written, the titlebar window sits just inside of the 
  200. X * resize corners.  Because the OpenLook spec. requires the header to 
  201. X * be highlighted in line with the resize corners, blacking in the
  202. X * the background of the titlebar window is one pixel short in each
  203. X * direction of being a big enough highlighted area.  We can't make
  204. X * the titlebar bigger because it would then overlap the resize corners.
  205. X * Now that the spec. is complete, OLWM should be restructured.
  206. X *
  207. X * Overview:
  208. X *
  209. X *    Upon startup OLWM reparents all the client windows unless
  210. X *    the user has told it otherwise (-p option).
  211. X *     OLWM creates a frame which will contain the client window (the pane)
  212. X *      and the decoration windows (resize corners, titlebar).  The
  213. X *    titlebar window contains the pushpin, if any.
  214. X *
  215. X *    After creating the decorations for the windows OLWM sits
  216. X *     in a forever loop getting the next event and calling the
  217. X *     corresponding window's event handling routine.
  218. X *
  219. X *    Each window has associated with it an event handling 
  220. X *     routine (EventFrame, EventPushPin) which the main EventLoop
  221. X *    will call when an event happens in that window.  The event
  222. X *    handling routine will call the proper routines to move a 
  223. X *    window, create a menu, etc.
  224. X */
  225. Xmain(argc, argv)
  226. X    int argc;
  227. X    char **argv;
  228. X{
  229. X    int            ErrorHandler();
  230. X    int            ExitOLWM();
  231. X    XrmDatabase        commandlineDB = NULL;
  232. X    char            *dpystr;
  233. X
  234. X#ifdef OW_I18N_L3
  235. X#ifndef MAXPATHLEN
  236. X#define MAXPATHLEN 256
  237. X#endif
  238. X    char            *OpenWinHome;
  239. X    char            locale_dir[MAXPATHLEN+1];
  240. X    extern char        *getenv();
  241. X#endif /* OW_I18N_L3 */
  242. X
  243. X#ifdef MALLOCDEBUG
  244. X    malloc_debug(MALLOCDEBUG);
  245. X#endif /* MALLOCDEBUG */
  246. X#ifdef GPROF_HOOKS
  247. X    moncontrol(0);
  248. X#endif /* GPROF_HOOKS */
  249. X
  250. X#ifdef OW_I18N_L3
  251. X           /*
  252. X            * Even in the SUNDAE1.0 (first release) we might need the
  253. X            * dynamic locale change for window manager, since window
  254. X            * manager is usually never re-start again in one sesstion.
  255. X            * But leave static for now.
  256. X            */
  257. X           /*
  258. X            * We are setting the locale (issuing the setlocale) by
  259. X            * EffectOLLC() function, but we need to call setlocale here
  260. X            * to handle command line argument with certain locale.
  261. X            * FIX_ME! But may not work well, because we did not touch the
  262. X            * Xlib function XrmParseCommand().
  263. X            */
  264. X           if (setlocale(LC_ALL, "") == NULL) {
  265. X        /*
  266. X         * FIX_ME: Following message may be misleading,
  267. X         * because setlocale will retrieve more than just a
  268. X         * $LANG environment variable (such as $LC_CTYPE).
  269. X         * Also, later if the resource DB has a locale
  270. X         * infomation, we will use it. Hence, this setting is
  271. X         * may be only for the command line processing.
  272. X         */
  273. X        fprintf(stderr, gettext("\
  274. X        olwm: Warning: '%s' is invalid locale, using 'C' locale.\n"),
  275. X                getenv("LANG"));
  276. X        (void)setlocale(LC_ALL,"C");
  277. X    }
  278. X    if ((OpenWinHome = getenv("OPENWINHOME")) != 0)
  279. X        (void)strcpy(locale_dir,OpenWinHome);
  280. X    else
  281. X        (void)strcpy(locale_dir,"/usr");
  282. X    (void)strcat(locale_dir,"/lib/locale");
  283. X    bindtextdomain("olwm_messages",locale_dir);
  284. X           textdomain("olwm_messages");
  285. X#endif /* OW_I18N_L3 */
  286. X
  287. X    ProgramName = argv[0];
  288. X    argVec = argv;
  289. X
  290. X    /* Set up a signal handler so that if we are killed we put
  291. X     * the windows back into a usable state.  Specifically we
  292. X     * need to reset the focus so they will be able to get input.
  293. X     */
  294. X    signal(SIGHUP, (VoidFunc)ExitOLWM);
  295. X    signal(SIGINT, (VoidFunc)ExitOLWM);
  296. X    signal(SIGTERM, (VoidFunc)ExitOLWM);
  297. X    signal(SIGCHLD, HandleChildSignal);
  298. X
  299. X    /* initialize the resource manager */
  300. X    XrmInitialize();
  301. X
  302. X    /* parse the command line arguments into local tmp DB */
  303. X    parseCommandline( &argc, argv, &commandlineDB );
  304. X
  305. X    DefDpy = openDisplay(commandlineDB);
  306. X
  307. X#ifdef ALLPLANES
  308. X    {
  309. X        int tmp;
  310. X        allplanes = XAllPlanesQueryExtension(DefDpy, &tmp, &tmp);
  311. X    }
  312. X#endif /* ALLPLANES */
  313. X
  314. X
  315. X#ifdef SHAPE
  316. X    ShapeSupported = XShapeQueryExtension(DefDpy, &ShapeEventBase,
  317. X                          &ShapeErrorBase);
  318. X#endif /* SHAPE */
  319. X
  320. X    /* put all resources into global OlwmDB and set olwm variables */
  321. X    GetDefaults(DefDpy, commandlineDB);
  322. X
  323. X    /* Initialize the event handling system. */
  324. X    InitEvents(DefDpy);
  325. X    InitBindings(DefDpy);
  326. X
  327. X    /* Set up the error handling function. */
  328. X    XSetErrorHandler(ErrorHandler);
  329. X
  330. X    /* this can be useful for debuging strange client behaivior */
  331. X    if (GRV.Synchronize)
  332. X        XSynchronize(DefDpy, True);
  333. X
  334. X    /* Initialize the atoms we will need to communicate with
  335. X     * Open Look clients.
  336. X     */
  337. X    InitAtoms(DefDpy);
  338. X
  339. X    /* Initialize the database. */
  340. X    WIInit( DefDpy );
  341. X
  342. X    /* Initialise all types of window classes */
  343. X    initWinClasses(DefDpy);
  344. X
  345. X    /* Initialize client led state */
  346. X    InitClientState(DefDpy);
  347. X
  348. X    /* initialise the group module */
  349. X    GroupInit();
  350. X
  351. X    /*
  352. X     * Force child processes to disinherit the TCP file descriptor.
  353. X     * This helps shell commands forked and exec'ed from menus
  354. X     * to work properly.
  355. X     */
  356. X    if (fcntl(ConnectionNumber(DefDpy), F_SETFD, 1) == -1)
  357. X    {
  358. X        perror( gettext("olvwm: child cannot disinherit TCP fd") );
  359. X        exit( -1 );
  360. X    }
  361. X
  362. X#ifdef OW_I18N_L3
  363. X    EffectOLLC(DefDpy);
  364. X#endif /* OW_I18N_L3 */
  365. X    /* Init the global menus -- No more global menus; done in InitScreens
  366. X    InitMenus(DefDpy);
  367. X    */
  368. X
  369. X    /* init region handling code */
  370. X    InitRegions();
  371. X
  372. X    /* Init screen */
  373. X    InitScreens(DefDpy);
  374. X    InitOlvwmRC(DefDpy);
  375. X    GrabKeys(DefDpy, True);
  376. X    GrabButtons(DefDpy, True);
  377. X    ReparentScreens(DefDpy);
  378. X    if (!GRV.FocusFollowsMouse)
  379. X        ClientFocusTopmost(DefDpy, GetFirstScrInfo(), CurrentTime);
  380. X    CreateAutoRootMenu(DefDpy);
  381. X    
  382. X    /*
  383. X      * Start olwmslave - using the same args we got.
  384. X     */
  385. X    if (GRV.RunSlaveProcess)
  386. X        SlavePid = SlaveStart(argVec);
  387. X
  388. X    if (GRV.Beep != BeepNever)
  389. X        XBell(DefDpy, 100);
  390. X
  391. X    sendSyncSignal();
  392. X
  393. X    EventLoop( DefDpy );
  394. X
  395. X    /*NOTREACHED*/
  396. X}
  397. X
  398. X
  399. X/* 
  400. X * parseCommandline - parse the command line arguments into a resource
  401. X *    database
  402. X */
  403. Xstatic void
  404. XparseCommandline( argc, argv, tmpDB )
  405. Xint        *argc;
  406. Xchar        *argv[];
  407. XXrmDatabase    *tmpDB;
  408. X{
  409. X    char    instName[MAX_NAME];
  410. X    char    namestr[MAX_NAME];
  411. X    char    *type, *p;
  412. X    XrmValue val;
  413. X
  414. X    /* Extract trailing pathname component of argv[0] into AppName. */
  415. X
  416. X    AppName = strrchr(argv[0], '/');
  417. X    if (AppName == NULL)
  418. X        AppName = argv[0];
  419. X    else
  420. X        ++AppName;
  421. X
  422. X    XrmParseCommand(tmpDB, optionTable, OPTION_TABLE_ENTRIES,
  423. X            AppName, argc, argv );
  424. X
  425. X    /*
  426. X     * Initialize root instance and class quarks.  Create the instance
  427. X     * name by first looking up the "name" resource in the command line
  428. X     * database (for the -name option).  If it's not present, use AppName
  429. X     * (the trailing pathname component of argv[0]).  Then, scan it and
  430. X     * replace all illegal characters with underscores.  Note: we don't
  431. X     * use the ctype functions here, because they are internationalized.
  432. X     * In some locales, isalpha() will return true for characters that are
  433. X     * not valid in resource component names.  Thus, we must fall back to
  434. X     * standard character comparisions.
  435. X     *
  436. X     * REMIND: specifying the -name option changes the name with which 
  437. X     * resources are looked up.  But the command line options were put 
  438. X     * into the database using AppName, which is based on argv[0].  Thus, 
  439. X     * specifying -name causes all command-line args to be ignored, which 
  440. X     * is wrong.
  441. X     */
  442. X
  443. X    (void) strcpy(namestr, AppName);
  444. X    (void) strcat(namestr, ".name");
  445. X    if (XrmGetResource(*tmpDB, namestr, namestr, &type, &val)) {
  446. X        (void) strncpy(instName, (char *)val.addr, MAX_NAME);
  447. X    } else {
  448. X        (void) strncpy(instName, AppName, MAX_NAME);
  449. X    }
  450. X
  451. X    instName[MAX_NAME-1] = '\0';
  452. X    for (p=instName; *p != '\0'; ++p) {
  453. X        if (!(*p >= 'a' && *p <= 'z' ||
  454. X          *p >= 'A' && *p <= 'Z' ||
  455. X          *p >= '0' && *p <= '9' ||
  456. X          *p == '_' || *p == '-')) {
  457. X        *p = '_';
  458. X        }
  459. X    }
  460. X    TopInstanceQ = XrmStringToQuark(instName);
  461. X    TopClassQ = XrmStringToQuark("Olwm");
  462. X    OpenWinQ = XrmStringToQuark("OpenWindows");
  463. X    OlwmQ = XrmStringToQuark("olwm");
  464. X
  465. X    /* check to see if there are any arguments left unparsed */
  466. X    if ( *argc != 1 )
  467. X    {
  468. X        /* check to see if it's -help */
  469. X        if ( argv[1][0] == '-' && argv[1][1] == 'h' )
  470. X            usage(gettext("Command line arguments accepted"),gettext("are:"));
  471. X        else
  472. X            usage(gettext("Unknown argument(s)"), gettext("encountered"));
  473. X    }
  474. X}
  475. X
  476. X
  477. X/*
  478. X * openDisplay
  479. X */
  480. Xstatic Display *
  481. XopenDisplay(rdb)
  482. X    XrmDatabase rdb;
  483. X{
  484. X    char namebuf[MAX_NAME];
  485. X    char *type;
  486. X    XrmValue value;
  487. X    char *dpystr = NULL;
  488. X    char *envstr;
  489. X    Display *dpy;
  490. X
  491. X    (void) strcpy(namebuf, AppName);
  492. X    (void) strcat(namebuf, ".display");
  493. X
  494. X    if (XrmGetResource(rdb, namebuf, namebuf, &type, &value)) {
  495. X    dpystr = (char *)value.addr;
  496. X    envstr = (char *)MemAlloc(8+strlen(dpystr)+1);
  497. X    sprintf(envstr, "DISPLAY=%s", dpystr);
  498. X    putenv(envstr);
  499. X    }
  500. X
  501. X    dpy = XOpenDisplay(dpystr);
  502. X    if (dpy == NULL) {
  503. X    fprintf(stderr, gettext("%s: cannot connect to %s\n"),
  504. X        ProgramName, dpystr);
  505. X    exit(1);
  506. X    }
  507. X    return dpy;
  508. X}
  509. X
  510. X
  511. X/*
  512. X * sendSyncSignal
  513. X *
  514. X * Send a signal to the process named on the command line (if any).  Values
  515. X * for the process id and signal to send are looked up in the resource 
  516. X * database; they are settable with command-line options.  The resources are 
  517. X * looked up with the names
  518. X * 
  519. X *    <appname>.syncPid        process id
  520. X *    <appname>.syncSignal        signal to send (integer)
  521. X *
  522. X * where <appname> is the trailing pathname component of argv[0].
  523. X */
  524. Xstatic void
  525. XsendSyncSignal()
  526. X{
  527. X    char *type;
  528. X    XrmValue value;
  529. X    int pid;
  530. X    int sig = SIGALRM;
  531. X    int tmp;
  532. X    char namebuf[100];
  533. X
  534. X    (void) strcpy(namebuf, AppName);
  535. X    (void) strcat(namebuf, ".syncPid");
  536. X    if (!XrmGetResource(OlwmDB, namebuf, namebuf, &type, &value))
  537. X    return;
  538. X    pid = atoi((char *)value.addr);
  539. X    if (pid <= 0 || pid > MAXPID)
  540. X    return;
  541. X
  542. X    (void) strcpy(namebuf, AppName);
  543. X    (void) strcat(namebuf, ".syncSignal");
  544. X    if (XrmGetResource(OlwmDB, namebuf, namebuf, &type, &value)) {
  545. X    tmp = atoi((char *)value.addr);
  546. X    if (tmp > 0 && tmp <= SIGUSR2)
  547. X        sig = tmp;
  548. X    }
  549. X    (void) kill(pid, sig);
  550. X}
  551. X
  552. Xstatic void
  553. XinitWinClasses(dpy)
  554. XDisplay *dpy;
  555. X{
  556. X    FrameInit(dpy);
  557. X    IconInit(dpy);
  558. X    ResizeInit(dpy);
  559. X    ColormapInit(dpy);
  560. X    ButtonInit(dpy);
  561. X    BusyInit(dpy);
  562. X    MenuInit(dpy);
  563. X    PinMenuInit(dpy);
  564. X    RootInit(dpy);
  565. X    NoFocusInit(dpy);
  566. X    PushPinInit(dpy);
  567. X    PaneInit(dpy);
  568. X    IconPaneInit(dpy);
  569. X    VirtualInit(dpy);
  570. X}
  571. X
  572. X
  573. X/*
  574. X * Exit -- exit routine called by menus.
  575. X *    Kill all running applications.
  576. X */
  577. XExit(dpy)
  578. XDisplay    *dpy;
  579. X{
  580. X    extern void *ClientShutdown();
  581. X    
  582. X    SlaveStop();
  583. X    ListApply(ActiveClientList, ClientShutdown, (void *)0);
  584. X    XSync(dpy, True);
  585. X    exit(0);
  586. X    /*NOTREACHED*/
  587. X}
  588. X
  589. X
  590. Xstatic void
  591. Xcleanup()
  592. X{
  593. X    extern void *UnparentClient();
  594. X
  595. X    /*
  596. X      * If DefDpy is NULL then we didn't get to the XOpenDisplay()
  597. X     * so basically there is nothing to clean up so return.
  598. X     */
  599. X    if (DefDpy == NULL)
  600. X        return;
  601. X
  602. X    /*
  603. X     * Stop olwmslave
  604. X      */
  605. X    SlaveStop();
  606. X
  607. X    /*
  608. X     * destroy all pinned menus
  609. X     */
  610. X    DestroyPinnedMenuClients();
  611. X
  612. X    /*
  613. X     * Clean up the virtual desktop -- if we aren't left in the upper
  614. X     * left corner, nothing will start in the right place
  615. X     */
  616. X    VirtualCleanup(DefDpy);
  617. X
  618. X    /*
  619. X     * Go through the list of windows.  Unmap all icons that are on the
  620. X     * screen.  Reparent all windows back to the root, suitably offset
  621. X     * according to their window-gravities.  Also remap all non-withdrawn
  622. X     * windows, and remove all Withdrawn windows from the save-set (so
  623. X     * they don't get remapped.  REMIND: We have to do this because
  624. X     * Withdrawn windows are still left reparented inside the frame; this
  625. X     * shouldn't be the case.
  626. X     */
  627. X    ListApply(ActiveClientList,UnparentClient,NULL);
  628. X
  629. X    /* Destroy the screens - which will restore input focus, colormap,
  630. X     * and background, etc.
  631. X     */
  632. X    DestroyScreens(DefDpy);
  633. X
  634. X    XSync(DefDpy, True);
  635. X}
  636. X
  637. X
  638. X/* Clean up and then re-exec argv. */
  639. Xint
  640. XRestartOLWM()
  641. X{
  642. X    cleanup();
  643. X    execvp(argVec[0], argVec);
  644. X    ErrorGeneral("cannot restart");
  645. X    /*NOTREACHED*/
  646. X}
  647. X
  648. X
  649. X/* Clean up and then exit. */
  650. Xint
  651. XExitOLWM()
  652. X{
  653. X    cleanup();
  654. X    exit(0);
  655. X}
  656. X
  657. X
  658. X/*
  659. X * HandleChildSignal - keep track of children that have died
  660. X */
  661. Xstatic void
  662. XHandleChildSignal()
  663. X{
  664. X    /*
  665. X     * Following is only neede for SYSV but it doesn't hurt in BSD
  666. X     */
  667. X    signal(SIGCHLD, HandleChildSignal);
  668. X    ++DeadChildren;
  669. X}
  670. X
  671. X/*
  672. X * ReapChildren - wait() for all dead child processes
  673. X */
  674. Xvoid
  675. XReapChildren()
  676. X{
  677. X#ifdef SYSV
  678. X        sigset_t newmask, oldmask;
  679. X        int status;
  680. X        pid_t pid;
  681. X#else
  682. X    int oldmask;
  683. X    int pid;
  684. X    union wait status;
  685. X#endif
  686. X
  687. X#ifdef SYSV
  688. X        sigemptyset(&newmask);
  689. X        sigemptyset(&oldmask);
  690. X        sigaddset(&newmask, SIGCHLD);
  691. X        sigprocmask(SIG_BLOCK, &newmask, &oldmask);
  692. X#else
  693. X    oldmask = sigblock(sigmask(SIGCHLD));
  694. X#endif
  695. X    while (DeadChildren>0)
  696. X    {
  697. X#ifdef SYSV
  698. X                pid = waitpid(-1, &status, WNOHANG);
  699. X#else
  700. X                pid = wait3(&status, WNOHANG, (struct rusage *)0);
  701. X#endif
  702. X        /* if it's the slave process then stop its use */
  703. X        if (pid == SlavePid) 
  704. X            SlaveStopped();
  705. X
  706. X        if (pid == 0)
  707. X        {
  708. X            /* Removed error message - deemed not useful */
  709. X            DeadChildren = 0;
  710. X            break;
  711. X        }
  712. X        if (WIFSTOPPED(status))
  713. X        {
  714. X            kill(pid, SIGKILL);
  715. X        }
  716. X        --DeadChildren;
  717. X    }
  718. X#ifdef SYSV
  719. X        sigprocmask(SIG_SETMASK, &oldmask, &oldmask);
  720. X#else
  721. X        (void) sigsetmask(oldmask);
  722. X#endif
  723. X}
  724. X
  725. X/*
  726. X * usage(s1, s2)    -- print informative message regarding usage
  727. X */
  728. Xstatic
  729. Xusage(s1, s2)
  730. Xchar    *s1, *s2;
  731. X{
  732. X    fprintf(stderr, "%s %s\n", s1, s2);
  733. X    fprintf(stderr,
  734. X    "usage: %s [-2d] [-3d] [-click] [-follow] [-parent]\n", ProgramName);
  735. X    fputs(
  736. X       /* STRING_EXTRACTION - do not translate "-display" ,"-name"
  737. X        * and "-xrm", becuase those are namne of command line option.
  738. X        */
  739. X    gettext("\t[-display <display>] [-name <classname>] [-xrm <rsrcstring>]\n"),
  740. X    stderr);
  741. X    fputs("\t[-all] [-debug] [-orphans] [-synchronize] [-single]\n", stderr);
  742. X    fputs("\t[-syncpid pid] [-syncsignal signal]\n", stderr);
  743. X    exit(1);
  744. X}
  745. X
  746. END_OF_FILE
  747. if test 18395 -ne `wc -c <'olwm.c'`; then
  748.     echo shar: \"'olwm.c'\" unpacked with wrong size!
  749. fi
  750. # end of 'olwm.c'
  751. fi
  752. if test -f 'states.c' -a "${1}" != "-c" ; then 
  753.   echo shar: Will not clobber existing file \"'states.c'\"
  754. else
  755. echo shar: Extracting \"'states.c'\" \(33415 characters\)
  756. sed "s/^X//" >'states.c' <<'END_OF_FILE'
  757. X/*      (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
  758. X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
  759. X *      file for terms of the license.
  760. X */
  761. X
  762. X/* states.c - functions relating to changes in client state 
  763. X *    (Normal, Iconic, Withdrawn)
  764. X */
  765. X
  766. X#ident    "@(#)states.c    1.1 olvwm version 1/3/92"
  767. X
  768. X/*
  769. X * Based on
  770. X#ident    "@(#)states.c    26.50    91/09/14 SMI"
  771. X *
  772. X */
  773. X
  774. X#include <errno.h>
  775. X#include <stdio.h>
  776. X#include <X11/Xos.h>
  777. X#include <X11/Xlib.h>
  778. X#include <X11/Xutil.h>
  779. X#include <X11/Xatom.h>
  780. X
  781. X#include "i18n.h"
  782. X#include "ollocale.h"
  783. X#include "mem.h"
  784. X#include "olwm.h"
  785. X#include "win.h"
  786. X#include "group.h"
  787. X#include "globals.h"
  788. X#include "properties.h"
  789. X#include "virtual.h"
  790. X
  791. X/***************************************************************************
  792. X* global data
  793. X***************************************************************************/
  794. X
  795. Xextern Atom AtomWMClass;
  796. Xextern Atom AtomDecorAdd;
  797. Xextern Atom AtomDecorClose;
  798. Xextern Atom AtomDecorDel;
  799. Xextern Atom AtomDecorFooter;
  800. Xextern Atom AtomDecorHeader;
  801. Xextern Atom AtomDecorIconName;
  802. Xextern Atom AtomDecorPin;
  803. Xextern Atom AtomDecorResize;
  804. Xextern Atom AtomDeleteWindow;
  805. Xextern Atom AtomMenuFull;
  806. Xextern Atom AtomMenuLimited;
  807. Xextern Atom AtomNone;
  808. Xextern Atom AtomOlwmTimestamp;
  809. Xextern Atom AtomPinIn;
  810. Xextern Atom AtomPinOut;
  811. Xextern Atom AtomProtocols;
  812. Xextern Atom AtomSaveYourself;
  813. Xextern Atom AtomTakeFocus;
  814. Xextern Atom AtomWinAttr;
  815. Xextern Atom AtomWTBase;
  816. Xextern Atom AtomWTCmd;
  817. Xextern Atom AtomWTHelp;
  818. Xextern Atom AtomWTNotice;
  819. Xextern Atom AtomWTOther;
  820. X
  821. Xextern Client *CurrentClient;
  822. X
  823. Xextern    int    WinDrawFunc();
  824. Xextern    void    IconPaneSetPixmap();
  825. Xextern    void    IconPaneSetMask();
  826. X
  827. X/***************************************************************************
  828. X* private data
  829. X***************************************************************************/
  830. X
  831. X/* sanity checks for getting stuff out of hints */
  832. X#define IsCard16(x)    ((x) == ((unsigned short)(x)) && (x) > 0 )
  833. X#define IsInt16(x)    ((x) == ((short) (x)))
  834. X
  835. Xstatic WMDecorations BaseWindow = {
  836. X    WMDecorationCloseButton | WMDecorationResizeable | WMDecorationHeader 
  837. X    | WMDecorationIconName,
  838. X    MENU_FULL,
  839. X    0,
  840. X    PIN_IN,
  841. X    0
  842. X};
  843. X
  844. Xstatic WMDecorations CmdWindow = {
  845. X    WMDecorationPushPin | WMDecorationResizeable | WMDecorationHeader
  846. X    | WMDecorationIconName,
  847. X    MENU_LIMITED,
  848. X    0,
  849. X    PIN_IN,
  850. X    0
  851. X};
  852. X
  853. Xstatic WMDecorations NoticeWindow = {
  854. X    WMDecorationIconName,
  855. X    MENU_NONE,
  856. X    0,
  857. X    PIN_IN,
  858. X    0
  859. X};
  860. X
  861. Xstatic WMDecorations HelpWindow = {
  862. X    WMDecorationPushPin | WMDecorationHeader | WMDecorationIconName
  863. X    | WMDecorationWarpToPin,
  864. X    MENU_LIMITED,
  865. X    0,
  866. X    PIN_IN,
  867. X    0
  868. X};
  869. X
  870. Xstatic WMDecorations OtherWindow = {
  871. X    WMDecorationIconName,
  872. X    MENU_NONE,
  873. X    0, 
  874. X    PIN_IN,
  875. X    0
  876. X};
  877. X
  878. Xstatic WMDecorations TransientWindow = {
  879. X    WMDecorationResizeable | WMDecorationIconName,
  880. X    MENU_LIMITED,
  881. X    0,
  882. X    PIN_IN,
  883. X    0
  884. X};
  885. X
  886. Xstatic WMDecorations MinimalWindow = {
  887. X    WMDecorationResizeable | WMDecorationIconName,
  888. X    MENU_FULL,
  889. X    0,
  890. X    PIN_IN,
  891. X    0
  892. X};
  893. X
  894. Xstatic WMDecorations NoDecors = {
  895. X    WMNoDecor,
  896. X    MENU_NONE,
  897. X    0,
  898. X    PIN_OUT,
  899. X    0
  900. X};
  901. X
  902. Xtypedef struct {
  903. X    char *class, *instance, *name;
  904. X} minimalclosure;
  905. X
  906. X
  907. X/***************************************************************************
  908. X* private functions
  909. X***************************************************************************/
  910. X
  911. X/*
  912. X * Determine FocusMode from wmHints and protocols
  913. X */
  914. Xstatic FocusMode
  915. XfocusModeFromHintsProtocols(wmHints,protocols)
  916. X    XWMHints    *wmHints;
  917. X    int        protocols;
  918. X{
  919. X    FocusMode    focusMode;
  920. X
  921. X    if (wmHints && wmHints->input) {
  922. X        if (protocols & TAKE_FOCUS)
  923. X            focusMode = LocallyActive;    
  924. X        else
  925. X            focusMode = Passive;    
  926. X    } else { /* wmHints->input == False */
  927. X        if (protocols & TAKE_FOCUS)
  928. X            focusMode = GloballyActive;    
  929. X        else
  930. X            focusMode = NoInput;    
  931. X    }
  932. X    return focusMode;
  933. X}
  934. X
  935. X/* matchInstClass -- run through the list of names to be minimally
  936. X * decorated, and see if this window's class or instance match
  937. X * any.
  938. X *
  939. X * In olvwm, we check the name as well as class/instance
  940. X */
  941. Xstatic Bool
  942. XmatchInstClass(str,mc)
  943. Xchar *str;
  944. Xminimalclosure *mc;
  945. X{
  946. X    if ((mc->class != NULL) && (!strcmp(str, mc->class)))
  947. X    return True;
  948. X    if ((mc->instance != NULL) && (!strcmp(str, mc->instance)))
  949. X    return True;
  950. X    if ((mc->name != NULL) && (!strncmp(str, mc->name, strlen(str))))
  951. X    return True;
  952. X    return False;
  953. X}
  954. X
  955. X
  956. X/*
  957. X * getOlWinDecors - given the window attributes and decoration add/delete
  958. X *    requests, determine what kind of window (according to the OpenLook
  959. X *    kinds of windows) the client represents, and determine what sort of
  960. X *    decorations are appropriate.
  961. X */
  962. XWMDecorations *
  963. XgetOLWinDecors(dpy, win, transient, cli)
  964. XDisplay *dpy;
  965. XWindow  win;
  966. XBool    transient;
  967. XClient    *cli;
  968. X{
  969. X        WMDecorations           *decors;
  970. X    minimalclosure        mc;
  971. X    XWMHints            *wmHints = cli->wmHints;
  972. X    OLWinAttr        *winAttrs;
  973. X    Bool            oldVersion;
  974. X    int            decorFlags;
  975. X
  976. X        decors = MemNew(WMDecorations);
  977. X
  978. X    /*
  979. X     * REMIND: there is no way for a program to 
  980. X     * specify the default item, even if it should
  981. X     * specify the menu
  982. X     * so this get's initialized here
  983. X     * (one per window)
  984. X     */
  985. X    decors->def_item = 0;
  986. X
  987. X    /* if the instance or class strings match any of the names
  988. X     * listed for minimal decoration, only provide resize corners
  989. X     * and a menu.
  990. X     */
  991. X    mc.class = cli->wmClass;
  992. X    mc.instance = cli->wmInstance;
  993. X    if (!XFetchName(dpy, win, &mc.name))
  994. X        mc.name = NULL;
  995. X    if (ListApply(GRV.Minimals,matchInstClass,&mc) != NULL)
  996. X    {
  997. X            *decors = MinimalWindow;
  998. X        return decors;
  999. X    }
  1000. X    if (ListApply(GRV.NoDecors, matchInstClass, &mc) != NULL) {
  1001. X        *decors = NoDecors;
  1002. X        if (mc.name)
  1003. X        XFree(mc.name);
  1004. X        return decors;
  1005. X    }
  1006. X    if (mc.name)
  1007. X        XFree(mc.name);
  1008. X
  1009. X#ifdef SHAPE
  1010. X    if (cli->isShaped) {
  1011. X        *decors = MinimalWindow;
  1012. X        return decors;
  1013. X    }
  1014. X#endif
  1015. X
  1016. X    oldVersion = False;
  1017. X    winAttrs = MemNew(OLWinAttr);
  1018. X
  1019. X    /*
  1020. X     * If the _OL_WIN_ATTR property is not present then make the
  1021. X     * window into a base window unless is a transient window.
  1022. X     */
  1023. X    if (!PropGetOLWinAttr(dpy,win,winAttrs,&oldVersion)) {
  1024. X        if (transient) {
  1025. X            *decors = TransientWindow;
  1026. X            if (GRV.TransientsTitled)
  1027. X                decors->flags |= WMDecorationHeader;
  1028. X        } else {
  1029. X            *decors = BaseWindow;
  1030. X        }
  1031. X    /*
  1032. X      * Else we do have that property; so interpret it
  1033. X      */
  1034. X    } else {
  1035. X        /*
  1036. X         * Choose the decor from win_type
  1037. X         */
  1038. X        if ((winAttrs->flags & WA_WINTYPE) == 0) {
  1039. X                *decors = BaseWindow;
  1040. X        } else if (winAttrs->win_type == AtomWTBase) {
  1041. X                *decors = BaseWindow;
  1042. X        } else if (winAttrs->win_type == AtomWTCmd) {
  1043. X                *decors = CmdWindow;
  1044. X        } else if (winAttrs->win_type == AtomWTHelp) {
  1045. X                *decors = HelpWindow;
  1046. X        } else if (winAttrs->win_type == AtomWTNotice) {
  1047. X                *decors = NoticeWindow;
  1048. X        } else if (winAttrs->win_type == AtomWTOther) {
  1049. X                *decors = OtherWindow;
  1050. X
  1051. X                /* 
  1052. X             * This is the only case where we look at menu type
  1053. X             */
  1054. X                if (winAttrs->flags & WA_MENUTYPE) {
  1055. X                if (winAttrs->menu_type == AtomMenuFull)
  1056. X                    decors->menu_type = MENU_FULL;
  1057. X                else if (winAttrs->menu_type == AtomMenuLimited)
  1058. X                    decors->menu_type = MENU_LIMITED;
  1059. X                else if (winAttrs->menu_type == AtomNone)
  1060. X                    decors->menu_type = MENU_NONE;
  1061. X                }
  1062. X        }
  1063. X
  1064. X        /*
  1065. X          * Backward compatibility.  If we had a old/short attribute 
  1066. X         * property, and the client specified an icon window, we're 
  1067. X         * probably dealing with an old XView client.  These clients 
  1068. X         * assume the window manager doesn't put the icon name in 
  1069. X         * the icon, so they paint it into the icon window itself.
  1070. X         * Turn off the painting of the icon name for icons of 
  1071. X         * these windows.
  1072. X         */
  1073. X        if (oldVersion && wmHints && (wmHints->flags & IconWindowHint))
  1074. X            decors->flags &= ~WMDecorationIconName;
  1075. X
  1076. X        /*
  1077. X         * Set cancel if something specified
  1078. X         */
  1079. X        if (winAttrs->flags & WA_CANCEL)
  1080. X            decors->cancel = (winAttrs->cancel != 0);
  1081. X
  1082. X        /*
  1083. X         * Set the pin state
  1084. X         */
  1085. X        if (winAttrs->flags & WA_PINSTATE) {
  1086. X            decors->pushpin_initial_state = 
  1087. X                        winAttrs->pin_initial_state;
  1088. X        } else {
  1089. X            decors->pushpin_initial_state = PIN_OUT;
  1090. X        }
  1091. X    }
  1092. X
  1093. X    /*
  1094. X      * Apply DecorAdd flags
  1095. X     */
  1096. X    if (PropGetOLDecorAdd(dpy,win,&decorFlags)) {
  1097. X        decors->flags |= decorFlags;
  1098. X    }
  1099. X
  1100. X    /*
  1101. X      * Apply DecorDel flags
  1102. X     */
  1103. X    if (PropGetOLDecorDel(dpy,win,&decorFlags)) {
  1104. X        decors->flags &= ~decorFlags;
  1105. X    }
  1106. X
  1107. X    /*
  1108. X     * If the window has no header it can't have any header
  1109. X     * decorations; ie. pushpin or a close button.
  1110. X     */
  1111. X    if (!(decors->flags & WMDecorationHeader)) {
  1112. X        decors->flags &= ~(WMDecorationHeaderDeco);
  1113. X    }
  1114. X
  1115. X        /* 
  1116. X     * If the window wants both a pushpin and a close button it
  1117. X         * only can have a pushpin.
  1118. X         */
  1119. X        if ((decors->flags & WMDecorationCloseButton) &&
  1120. X            (decors->flags & WMDecorationPushPin))
  1121. X                decors->flags &= ~(WMDecorationCloseButton);
  1122. X
  1123. X    /*
  1124. X     * Don't warp to the pin if there's no pin.
  1125. X     */
  1126. X    if (!(decors->flags & WMDecorationPushPin))
  1127. X        decors->flags &= ~WMDecorationWarpToPin;
  1128. X
  1129. X        return  decors;
  1130. X}
  1131. X
  1132. X
  1133. X/*
  1134. X * calcPosition
  1135. X *
  1136. X * Calculate the next position to place a new window.  This function places
  1137. X * all new windows on the diagonal and makes sure that there is enough room on
  1138. X * the screen for the new window's size passed in w and h.
  1139. X */
  1140. Xstatic void
  1141. XcalcPosition(dpy, screen, attrs, frame)
  1142. X    Display        *dpy;
  1143. X    int            screen;
  1144. X    XWindowAttributes    *attrs;
  1145. X    WinPaneFrame    *frame;
  1146. X{
  1147. X    int        stepValue;
  1148. X    ScreenInfo    *scrInfo;
  1149. X
  1150. X    if ((scrInfo = GetScrInfoOfScreen(screen)) == NULL) {
  1151. X        attrs->x = attrs->y = 0;
  1152. X        return;
  1153. X    }
  1154. X
  1155. X    /* if the height of the current window is too large ... */
  1156. X    if ((scrInfo->framepos + frame->core.height
  1157. X        > DisplayHeight(dpy, screen)) ||
  1158. X        (scrInfo->framepos + frame->core.width
  1159. X        > DisplayWidth(dpy, screen)))
  1160. X    {
  1161. X        scrInfo->framepos = 0;
  1162. X    }
  1163. X
  1164. X    /* REMIND this should really be based on the header height */
  1165. X    stepValue = 30;
  1166. X
  1167. X    /* we will return the current position */
  1168. X    attrs->x = attrs->y = scrInfo->framepos;
  1169. X
  1170. X    /* calculate the next return value */
  1171. X    scrInfo->framepos = scrInfo->framepos + stepValue;
  1172. X    if ((scrInfo->framepos > DisplayWidth(dpy, screen)) ||
  1173. X        (scrInfo->framepos > DisplayHeight(dpy, screen)))
  1174. X    {
  1175. X        scrInfo->framepos = 0;
  1176. X    }
  1177. X}
  1178. X
  1179. X
  1180. X/*
  1181. X * iconifyOne -- iconify one client
  1182. X */
  1183. Xstatic void *
  1184. XiconifyOne(cli, winIcon)
  1185. XClient *cli;
  1186. XWinGeneric *winIcon;
  1187. X{
  1188. X    if (cli->groupmask == GROUP_DEPENDENT)
  1189. X            RemoveSelection(cli);    /* warp if necessary */
  1190. X    else
  1191. X        DrawIconToWindowLines(cli->dpy, winIcon, cli->framewin);
  1192. X
  1193. X    UnmapWindow(cli->framewin);
  1194. X    XUnmapWindow(cli->dpy, PANEWINOFCLIENT(cli));
  1195. X    cli->framewin->fcore.panewin->pcore.pendingUnmaps++;
  1196. X    cli->wmState = IconicState;
  1197. X    ClientSetWMState(cli);
  1198. X    return NULL;
  1199. X}
  1200. X
  1201. X/* deiconifyOne -- deiconify one client
  1202. X */
  1203. Xstatic void *
  1204. XdeiconifyOne(cli, winIcon, raise)
  1205. XClient *cli;
  1206. XWinGeneric *winIcon;
  1207. XBool raise;
  1208. X{
  1209. X    if (cli->groupmask != GROUP_DEPENDENT)
  1210. X        DrawIconToWindowLines(cli->dpy, winIcon, cli->framewin);
  1211. X
  1212. X    if (raise)
  1213. X        RaiseWindow(cli->framewin);
  1214. X
  1215. X    MapWindow(cli->framewin);
  1216. X    XMapRaised(cli->dpy, PANEWINOFCLIENT(cli));
  1217. X    cli->wmState = NormalState;
  1218. X    ClientSetWMState(cli);
  1219. X    return NULL;
  1220. X}
  1221. X
  1222. X
  1223. X/*
  1224. X * markFrame
  1225. X *
  1226. X * Marks a client's frame window with a given value.  Suitable for calling by
  1227. X * ListApply or GroupApply.
  1228. X */
  1229. Xstatic void *
  1230. XmarkFrame(cli, value)
  1231. X    Client *cli;
  1232. X    int value;
  1233. X{
  1234. X    if (cli->framewin != NULL)
  1235. X    cli->framewin->core.tag = value;
  1236. X    return NULL;
  1237. X}
  1238. X
  1239. X
  1240. X/*
  1241. X * deiconifyGroup
  1242. X *
  1243. X * Deiconify a window group, preserving stacking order.  Mark all the frames
  1244. X * that are to be deiconified, then query the server for all children-of-root.
  1245. X * Walk backward through this array (i.e. from top to bottom).  For each group
  1246. X * member found, stack it just below the previous one (raise the first one to
  1247. X * the top) and deiconify it.  Finally, unmark all the frames in the group.
  1248. X * Note: this algorithm depends on having the stacking order of windows
  1249. X * preserved when the group is iconified.
  1250. X */
  1251. Xstatic void
  1252. XdeiconifyGroup(cli, winIcon)
  1253. X    Client *cli;
  1254. X    WinIconFrame* winIcon;
  1255. X{
  1256. X    Window root, parent;
  1257. X    Window *children;
  1258. X    Window prev = None;
  1259. X    unsigned int nchildren;
  1260. X    int i;
  1261. X    WinGeneric *wi;
  1262. X    XWindowChanges xwc;
  1263. X
  1264. X    GroupApply(cli->groupid, markFrame, 1, GROUP_LEADER|GROUP_DEPENDENT);
  1265. X
  1266. X    (void) XQueryTree(cli->dpy, cli->scrInfo->rootid, &root, &parent,
  1267. X              &children, &nchildren);
  1268. X
  1269. X    xwc.stack_mode = Below;
  1270. X    for (i=nchildren-1; i>=0; --i) {
  1271. X    wi = WIGetInfo(children[i]);
  1272. X    if (wi != NULL && wi->core.tag == 1) {
  1273. X        if (prev == None) {
  1274. X        RaiseWindow(wi);
  1275. X        } else {
  1276. X        xwc.sibling = prev;
  1277. X        ConfigureWindow(cli->dpy, wi,
  1278. X                 CWSibling|CWStackMode, &xwc);
  1279. X        }
  1280. X        prev = children[i];
  1281. X        deiconifyOne(wi->core.client, winIcon, False);
  1282. X    }
  1283. X    }
  1284. X
  1285. X    if (children != NULL)
  1286. X    XFree((char *)children);
  1287. X
  1288. X    GroupApply(cli->groupid, markFrame, 0, GROUP_LEADER|GROUP_DEPENDENT);
  1289. X}
  1290. X
  1291. X
  1292. X/***************************************************************************
  1293. X* global functions
  1294. X***************************************************************************/
  1295. X
  1296. X
  1297. X/*
  1298. X * StateNew -- A client is mapping a top-level window (either a new window
  1299. X *    or a Withdrawn window).  The window may become Iconic or Normal 
  1300. X *    depending on the hints.  Check to see if this window needs to be mapped
  1301. X *    and if so add the required adornments.
  1302. X *        dpy         -- display pointer
  1303. X *        rootWin        -- root window
  1304. X *                    if None will determine the root window
  1305. X *                    for the client window
  1306. X *        window         -- client's window
  1307. X *        fexisting    -- the window already exists and we
  1308. X *                   are starting olwm, so positioning should
  1309. X *                   be special-cased
  1310. X *        ourWinInfo    -- if is this one of our menu windows, this
  1311. X *            will be its WinMenu structure; this window must
  1312. X *            be a subclass of Pane
  1313. X *            If this is a VDM,  this will be a subclass of
  1314. X *            VPane
  1315. X */
  1316. XClient *
  1317. XStateNew(dpy, rootWin, window, fexisting, ourWinInfo)
  1318. XDisplay *dpy;
  1319. XWindow rootWin;
  1320. XWindow window;
  1321. XBool fexisting;
  1322. XWinPane *ourWinInfo;
  1323. X{
  1324. X    Client         *cli;
  1325. X    WinGeneric    *winGeneric;
  1326. X    WinPane        *winPane;
  1327. X    WinIconFrame    *winIcon;
  1328. X    WinPaneFrame    *winFrame;
  1329. X    WinIconPane    *winIconPane;
  1330. X    XSizeHints    *normHints;
  1331. X    Bool        preICCCM;
  1332. X    Bool        transient = False;
  1333. X    int        status;
  1334. X    int        initstate;
  1335. X    XWindowAttributes paneAttr;
  1336. X    int         screen;
  1337. X    int        tmpx, tmpy;
  1338. X    ScreenInfo     *scrInfo;
  1339. X    int        winState;
  1340. X    Window        iconWin;
  1341. X    minimalclosure    mc;
  1342. X    int        icon_x, icon_y;
  1343. X
  1344. X    /*
  1345. X     * If the window is thought to be new (i.e. if ourWinInfo is null, as
  1346. X     * it is always except for the case of pinned menus and the VDM) and
  1347. X     * the window * has already been registered in the WinInfo database
  1348. X     * and it's anything other than colormap window, then return.
  1349. X     *
  1350. X     * This is to head off (a) clients that might be mapping the olwm
  1351. X     * frame, (b) clients that map their top-level window (pane) more than
  1352. X     * once before olwm can reparent it to a frame, and (c) olwm's own 
  1353. X     * popup menus.
  1354. X     */
  1355. X    if (!ourWinInfo &&
  1356. X       (winGeneric = WIGetInfo(window)) != NULL &&
  1357. X        winGeneric->core.kind != WIN_COLORMAP) {
  1358. X        return NULL;
  1359. X    }
  1360. X
  1361. X    /* Find the screen the client window is on.
  1362. X     * If ourWinInfo is valid, use it's screen
  1363. X     * Else if know the root then use it's screen
  1364. X     * Lastly QueryTree to find out from the server
  1365. X     */
  1366. X    if (ourWinInfo) {
  1367. X        screen = ourWinInfo->core.client->scrInfo->screen;
  1368. X    } else if (rootWin != None) {
  1369. X        if ((scrInfo = GetScrInfoOfRoot(rootWin)) == NULL) 
  1370. X            return NULL;
  1371. X        screen = scrInfo->screen;
  1372. X    } else {
  1373. X        Window    root, parent, *children;
  1374. X        unsigned int    nChild;
  1375. X        Status    result;
  1376. X        
  1377. X        result  = XQueryTree(dpy, window, &root, &parent, 
  1378. X                &children, &nChild);
  1379. X
  1380. X        if (result == 0 || parent != root)
  1381. X            return NULL;
  1382. X        if ((scrInfo = GetScrInfoOfRoot(root)) == NULL) 
  1383. X            return NULL;
  1384. X        screen = scrInfo->screen;
  1385. X    }
  1386. X
  1387. X    /*
  1388. X     * Select for events on the pane right now (including StructureNotify)
  1389. X     * so that we are guaranteed to get a DestroyNotify if the window goes
  1390. X     * away.  If the window has already gone away, the call to
  1391. X     * XGetWindowAttributes below will tell us without race conditions.
  1392. X     */
  1393. X    if (!ourWinInfo)
  1394. X        XSelectInput(dpy, window,
  1395. X             PropertyChangeMask | StructureNotifyMask |
  1396. X             ColormapChangeMask | EnterWindowMask);
  1397. X
  1398. X        /* get all the info about the new pane */
  1399. X        status = XGetWindowAttributes(dpy, window, &paneAttr);
  1400. X        if ( status == 0 ) {
  1401. X            return NULL;
  1402. X        }
  1403. X
  1404. X    /*
  1405. X     * If it's an override-redirect window, or if already exists but is 
  1406. X     * unmapped, ignore it after first removing our StructureNotify 
  1407. X     * interest.
  1408. X     */
  1409. X    if (paneAttr.override_redirect ||
  1410. X        (fexisting && paneAttr.map_state != IsViewable)) {
  1411. X        if (!ourWinInfo)
  1412. X        XSelectInput(dpy, window, NoEventMask);
  1413. X        return NULL;
  1414. X    }
  1415. X
  1416. X    /* Create the client structure so we can start hooking things to it */
  1417. X    if ((cli = ClientCreate(dpy,screen)) == NULL)
  1418. X    {
  1419. X        return NULL;
  1420. X    }
  1421. X
  1422. X#ifdef SHAPE
  1423. X    {
  1424. X        Bool bshaped, cshaped;
  1425. X        int bx, by, cx, cy;
  1426. X        unsigned int bw, bh, cw, ch;
  1427. X
  1428. X        if (ShapeSupported &&
  1429. X        0 != XShapeQueryExtents(dpy, window, &bshaped, &bx, &by,
  1430. X                    &bw, &bh, &cshaped, &cx, &cy,
  1431. X                    &cw, &ch))
  1432. X        {
  1433. X        XShapeSelectInput(dpy, window, ShapeNotifyMask);
  1434. X        cli->isShaped = bshaped;
  1435. X        } else {
  1436. X        cli->isShaped = False;
  1437. X        }
  1438. X    }
  1439. X#endif /* SHAPE */
  1440. X
  1441. X    /*
  1442. X      * Turn on prop read filtering with set of available properties
  1443. X      */
  1444. X    PropSetAvailable(dpy,window);
  1445. X
  1446. X    /*
  1447. X     * Get the WM_TRANSIENT_FOR hint.  If the property exists but has a
  1448. X     * contents of zero, or the window itself, substitute the root's
  1449. X     * window ID.  This is because some (buggy) clients actually write
  1450. X     * zero in the WM_TRANSIENT_FOR property, and we want to give them
  1451. X     * transient window behavior.
  1452. X     */
  1453. X    if (!PropGetWMTransientFor(dpy,window,cli->scrInfo->rootid,
  1454. X                    &(cli->transientFor))) {
  1455. X        cli->transientFor = 0;
  1456. X        transient = False;
  1457. X    } else {
  1458. X        transient = True;
  1459. X    }
  1460. X
  1461. X    /*
  1462. X     * Get the WM_NORMAL_HINTS property.  If it's short, then we have a
  1463. X     * pre-ICCCM client on our hands, so we interpret some values 
  1464. X     * specially.
  1465. X     */
  1466. X    normHints = MemNew(XSizeHints);
  1467. X
  1468. X    if (!PropGetWMNormalHints(dpy,window,normHints,&preICCCM)) {
  1469. X        normHints->win_gravity = NorthWestGravity;
  1470. X        normHints->flags = PWinGravity;
  1471. X    }
  1472. X
  1473. X    /*
  1474. X     * We got a short property.  Assume that this is a pre-X11R4
  1475. X     * client who's using the short version of the property.  Copy
  1476. X     * the data into a correctly-sized structure.  Then, depending
  1477. X     * on the flags set, ignore the window's real geometry and use
  1478. X     * the data in the hint (but only if it passes some sanity 
  1479. X     * checking).  The sanity checking is necessary because early 
  1480. X     * versions of XView write a short property, but rely on the 
  1481. X     * window manager to look at the window's geometry instead of 
  1482. X     * at the values in the hint.
  1483. X     */
  1484. X    if (preICCCM) {
  1485. X        int     maxDpyWidth = 2*DisplayWidth(dpy,screen);
  1486. X        int     maxDpyHeight = 2*DisplayHeight(dpy,screen);
  1487. X
  1488. X        if (!fexisting
  1489. X            && (normHints->flags & (USPosition|PPosition))
  1490. X            && IsInt16(normHints->x) 
  1491. X            && IsInt16(normHints->y)
  1492. X            && normHints->x > -maxDpyWidth
  1493. X            && normHints->y > -maxDpyHeight
  1494. X            && normHints->x < maxDpyWidth
  1495. X            && normHints->y < maxDpyHeight) {
  1496. X            paneAttr.x = normHints->x;
  1497. X            paneAttr.y = normHints->y;
  1498. X        }
  1499. X        if ((normHints->flags & (USSize|PSize)) 
  1500. X            && IsCard16(normHints->width) 
  1501. X            && IsCard16(normHints->height)
  1502. X            && normHints->width >= MINSIZE
  1503. X            && normHints->height >= MINSIZE
  1504. X            && normHints->width < maxDpyWidth
  1505. X            && normHints->height < maxDpyHeight) {
  1506. X            paneAttr.width = normHints->width;
  1507. X            paneAttr.height = normHints->height;
  1508. X        }
  1509. X    }
  1510. X
  1511. X    cli->normHints = normHints;
  1512. X
  1513. X    /*
  1514. X     * Get the WM_HINTS
  1515. X     */
  1516. X    cli->wmHints = MemNew(XWMHints);
  1517. X
  1518. X    if (!PropGetWMHints(dpy,window,cli->wmHints)) {
  1519. X        cli->wmHints->flags = 0L;
  1520. X    }
  1521. X
  1522. X    /* 
  1523. X     * Get the protocols in which the client will participate
  1524. X     */
  1525. X    if (!PropGetWMProtocols(dpy,window,&(cli->protocols))) {
  1526. X        cli->protocols = 0;
  1527. X    }
  1528. X
  1529. X        /* 
  1530. X     * Figure out what focus mode this window intends
  1531. X     */
  1532. X    cli->focusMode = focusModeFromHintsProtocols(cli->wmHints,
  1533. X                             cli->protocols);
  1534. X
  1535. X    /* 
  1536. X     * Get the window class and instance strings
  1537. X     */
  1538. X    if (!PropGetWMClass(dpy,window,&(cli->wmClass),&(cli->wmInstance))) {
  1539. X        cli->wmClass = cli->wmInstance = NULL;
  1540. X    }
  1541. X
  1542. X    /* 
  1543. X     * Get the OpenLook window type and associated decorations
  1544. X     */
  1545. X    cli->wmDecors = getOLWinDecors(dpy, window, transient, cli);
  1546. X
  1547. X    /*
  1548. X     * Establish window groups.  Policy: if the window is transient, this 
  1549. X     * takes priority over any window group specified in WM_HINTS.  If
  1550. X     * it's transient, make it be part of the window group of the window 
  1551. X     * it is transient for.  Otherwise, use the group specified in
  1552. X     * WM_HINTS.  If no group is specified in WM_HINTS, consider the 
  1553. X     * window to be the leader of its own group.
  1554. X     */
  1555. X    if (transient) {
  1556. X        winGeneric = WIGetInfo(cli->transientFor);
  1557. X        if (winGeneric != NULL)
  1558. X        cli->groupid = winGeneric->core.client->groupid;
  1559. X        else
  1560. X        cli->groupid = cli->transientFor;
  1561. X    } else if ((cli->wmHints) && (cli->wmHints->flags & WindowGroupHint)) {
  1562. X        cli->groupid = cli->wmHints->window_group;
  1563. X    } else {
  1564. X        cli->groupid = window;
  1565. X    }
  1566. X
  1567. X    if (cli->groupid == window)
  1568. X        cli->groupmask = GROUP_LEADER;
  1569. X    else
  1570. X    {
  1571. X        if (((cli->wmDecors->flags & WMDecorationPushPin) &&
  1572. X         (cli->wmDecors->menu_type == MENU_LIMITED))
  1573. X        || transient)
  1574. X        {
  1575. X        cli->groupmask = GROUP_DEPENDENT;
  1576. X        }
  1577. X        else
  1578. X        {
  1579. X        cli->groupmask = GROUP_INDEPENDENT;
  1580. X        }
  1581. X    }
  1582. X    GroupAdd(cli->groupid,cli,cli->groupmask);
  1583. X
  1584. X    /* 
  1585. X     * Officially set up the frame
  1586. X     */
  1587. X    winFrame = MakeFrame(cli,window,&paneAttr);
  1588. X
  1589. X    /*
  1590. X     * If the hints don't specify a location, we choose a suitable one, 
  1591. X     * taking into account the window size and decoration sizes.
  1592. X     */
  1593. X    if ( !fexisting &&
  1594. X         !(normHints->flags & USPosition) &&
  1595. X        (!(normHints->flags & PPosition) ||
  1596. X         (GRV.PPositionCompat && paneAttr.x <= 1 && paneAttr.y <= 1)))
  1597. X    {
  1598. X        calcPosition(dpy, screen, &paneAttr, winFrame);
  1599. X    }
  1600. X    else if (!fexisting && (normHints->flags & USPosition) &&
  1601. X         !GRV.UseRelativePosition) {
  1602. X        paneAttr.x += cli->scrInfo->vdm->offsetX;
  1603. X        paneAttr.y += cli->scrInfo->vdm->offsetY;
  1604. X    }
  1605. X
  1606. X    /*
  1607. X     * See if the position needs to be constrained to a logical
  1608. X     * screen due to entries in .olvwmrc
  1609. X     */
  1610. X    if (!XFetchName(dpy, window, &mc.name))
  1611. X        mc.name = NULL;
  1612. X    icon_x = icon_y = 0;
  1613. X    if (cli->groupmask != GROUP_DEPENDENT)
  1614. X        if (cli->wmHints)
  1615. X            if (cli->wmHints->flags & IconPositionHint)
  1616. X                SearchProgString(dpy, cli->scrInfo, mc.name,
  1617. X                cli->wmInstance, cli->wmClass,
  1618. X                &paneAttr.x, &paneAttr.y,
  1619. X                    &cli->wmHints->icon_x, &cli->wmHints->icon_y);
  1620. X            else SearchProgString(dpy, cli->scrInfo, mc.name,
  1621. X                cli->wmInstance, cli->wmClass,
  1622. X                &paneAttr.x, &paneAttr.y,
  1623. X                    &icon_x, &icon_y);
  1624. X        else SearchProgString(dpy, cli->scrInfo, mc.name, NULL, NULL,
  1625. X                     &paneAttr.x, &paneAttr.y, &icon_x, &icon_y);
  1626. X    else {
  1627. X        /*
  1628. X         * Map the popup on the same screen as the group leader
  1629. X         */
  1630. X        Client *leader = GroupLeader(cli->groupid);
  1631. X        int    curScreen;
  1632. X        int    dw = DisplayWidth(dpy, screen);
  1633. X        int    dh = DisplayHeight(dpy, screen);
  1634. X
  1635. X        if (leader != NULL) {
  1636. X        curScreen = leader->framewin->core.x / dw;
  1637. X        if (leader->framewin->core.x < 0)
  1638. X            curScreen--;
  1639. X        if (paneAttr.x < 0)
  1640. X            paneAttr.x = dw + (paneAttr.x % dw) + (curScreen * dw);
  1641. X        else paneAttr.x = (paneAttr.x % dw) + (curScreen * dw);
  1642. X        curScreen = leader->framewin->core.y / dh;
  1643. X        if (leader->framewin->core.y < 0)
  1644. X            curScreen--;
  1645. X        if (paneAttr.y < 0)
  1646. X            paneAttr.y = dh + (paneAttr.y % dh) + (curScreen * dh);
  1647. X        else paneAttr.y = (paneAttr.y % dh) + (curScreen * dh);
  1648. X        }
  1649. X    }
  1650. X        
  1651. X
  1652. X    /*
  1653. X     * If a non-olwm created window then create the pane for it
  1654. X     * Else if it is a pinned menu then call the creation callback
  1655. X     * so that it can fix up its pane
  1656. X     */
  1657. X    if (ourWinInfo == NULL) {
  1658. X        winPane = MakePane(cli,winFrame,window,&paneAttr);
  1659. X    } else {
  1660. X        winPane = ourWinInfo;
  1661. X        (WinClass(winPane)->core.createcallback)(ourWinInfo,cli,
  1662. X                                winFrame);
  1663. X    }
  1664. X
  1665. X    /* 
  1666. X     * Officially set up the icon
  1667. X     */
  1668. X    winIcon = MakeIcon(cli,window,&paneAttr);
  1669. X    winIconPane = MakeIconPane(cli,winIcon,cli->wmHints,fexisting);
  1670. X
  1671. X    /* 
  1672. X     * Keep track of any subwindows that need colormap installation
  1673. X     */
  1674. X    TrackSubwindows(cli);
  1675. X
  1676. X    /* 
  1677. X     * Size and generally configure the frame window tree
  1678. X     */
  1679. X    FrameSetPosFromPane(winFrame,paneAttr.x,paneAttr.y);
  1680. X    WinCallConfig(dpy, winPane, NULL);
  1681. X
  1682. X    /* 
  1683. X     * Size and generally configure the icon window tree
  1684. X     */
  1685. X    WinCallConfig(dpy, winIconPane, NULL);
  1686. X    if (cli->wmHints != NULL && (cli->wmHints->flags & IconPositionHint))
  1687. X        IconSetPos(winIcon,cli->wmHints->icon_x,cli->wmHints->icon_y);
  1688. X    else
  1689. X        IconSetPos(winIcon,icon_x,icon_y);
  1690. X    WinCallConfig(dpy, winIcon, NULL);
  1691. X
  1692. X        /*
  1693. X     * We manually move the icon pane window, since all the configuration
  1694. X     * has been done with the icon pane parented to root.
  1695. X     */
  1696. X        WinRootPos(winIconPane, &tmpx, &tmpy);
  1697. X        XMoveWindow(dpy, winIconPane->core.self, tmpx, tmpy);
  1698. X
  1699. X    /*
  1700. X     * Set the sticky bit according to the sticky list.  We check the
  1701. X     * window's group below (stickyness is inherited by group).
  1702. X     * sticky was set when the client was created; if this is a VDM
  1703. X     * then sticky will be set to true in the callback
  1704. X     */
  1705. X    mc.class = cli->wmClass;
  1706. X    mc.instance = cli->wmInstance;
  1707. X    if (ListApply(GRV.StickyList, matchInstClass, &mc) != NULL)
  1708. X        cli->sticky = True;
  1709. X    if (mc.name)
  1710. X        XFree(mc.name);
  1711. X
  1712. X    /* 
  1713. X     * Determine the proper initial state of the window. 
  1714. X     * If the window already exists and there is a WM_STATE property 
  1715. X     * then use the state that the last window manager left there, 
  1716. X     * otherwise use WM_HINTS.
  1717. X     */
  1718. X    if (fexisting &&
  1719. X        PropGetWMState(dpy,winPane->core.self,&winState,&iconWin)) {
  1720. X        if (winState == IconicState)
  1721. X        initstate = IconicState;
  1722. X        else
  1723. X        initstate = NormalState;
  1724. X    } else {
  1725. X        /* For new windows, check the initial_state field of WM_HINTS. */
  1726. X        if (cli->wmHints && (cli->wmHints->flags & StateHint)
  1727. X        && (cli->wmHints->initial_state == IconicState))
  1728. X            initstate = IconicState;
  1729. X        else
  1730. X            initstate = NormalState;
  1731. X    }
  1732. X
  1733. X    /*
  1734. X     * Don't allow the popup into iconic state if its leader is in normal 
  1735. X     * state.
  1736. X     *
  1737. X     * Also set the sticky field of the client based on the leader
  1738. X     */
  1739. X    if (cli->groupmask == GROUP_DEPENDENT) {
  1740. X        Client *leader = GroupLeader(cli->groupid);
  1741. X        if (leader != NULL) {
  1742. X        if (leader->wmState == NormalState && initstate == IconicState)
  1743. X            initstate = NormalState;
  1744. X        cli->sticky = leader->sticky;
  1745. X        }
  1746. X    }
  1747. X
  1748. X    if (cli->sticky)
  1749. X        MakeSticky(cli, True);
  1750. X    MakeVirtual(cli);
  1751. X    ClientProcessDragDropInterest(cli, PropertyNewValue);
  1752. X
  1753. X    /*
  1754. X     * Put the window into the correct initial state
  1755. X     */
  1756. X    switch ( initstate ) {
  1757. X    case NormalState:
  1758. X        cli->wmState = NormalState;
  1759. X        MapRaised(winFrame);
  1760. X        XMapRaised(dpy, winPane->core.self);
  1761. X        if (!fexisting) {
  1762. X        FrameWarpPointer(cli);
  1763. X        if (GRV.AutoInputFocus)
  1764. X            ClientSetFocus(cli, True, CurrentTime);
  1765. X        if (GRV.AutoColorFocus)
  1766. X            LockColormap(dpy, cli, winPane);
  1767. X        }
  1768. X        break;
  1769. X    case IconicState:
  1770. X        cli->wmState = IconicState;
  1771. X        /* unmap the window in case it was mapped originally */
  1772. X        XUnmapWindow(dpy, winPane->core.self);
  1773. X        winPane->pcore.pendingUnmaps++;
  1774. X        /* dependent group followers don't get their own icons */
  1775. X        if (cli->groupmask != GROUP_DEPENDENT)
  1776. X        IconShow(cli, winIcon);
  1777. X        break;
  1778. X    }
  1779. X    ClientSetWMState(cli);
  1780. X
  1781. X    /* 
  1782. X     * Get the window state
  1783. X     */
  1784. X    ClientGetWindowState(cli);
  1785. X
  1786. X    /*
  1787. X      * Turn off prop read filtering
  1788. X      */
  1789. X    PropClearAvailable();
  1790. X
  1791. X    return cli;
  1792. X}
  1793. X
  1794. X/*
  1795. X * ReparentTree -- called at start up, this routine queries the window
  1796. X *    tree and reparents all the windows 
  1797. X */
  1798. Xvoid
  1799. XReparentTree(dpy,treeroot)
  1800. XDisplay    *dpy;
  1801. XWindow     treeroot;
  1802. X{
  1803. X    unsigned int numChildren;
  1804. X    Window *children, root, parent, w;
  1805. X    int ii;
  1806. X    Client *cli;
  1807. X
  1808. X    children = NULL;
  1809. X
  1810. X    if (XQueryTree(dpy, treeroot, &root, &parent,
  1811. X                      &children, &numChildren)) 
  1812. X    {
  1813. X        for (ii=0; ii<numChildren; ii++)
  1814. X        {
  1815. X        w = children[ii];
  1816. X        if (WIGetInfo(w) == NULL)
  1817. X        {
  1818. X                cli = StateNew(dpy, treeroot, w, True, NULL);
  1819. X            if (cli != NULL)
  1820. X            {
  1821. X            cli->framewin->fcore.panewin->pcore.pendingUnmaps++;    
  1822. X                    /* unmap because of reparent */
  1823. X            }
  1824. X        }
  1825. X        }
  1826. X    }
  1827. X
  1828. X    if (children != NULL)
  1829. X        XFree((char *)children);
  1830. X}
  1831. X
  1832. X
  1833. X/* 
  1834. X * StateNormIcon - transition a window to IconicState from NormalState
  1835. X */
  1836. Xvoid
  1837. XStateNormIcon(cli)
  1838. XClient *cli;
  1839. X{
  1840. X    WinIconFrame *winIcon = cli->iconwin;
  1841. X
  1842. X    if (winIcon == NULL)
  1843. X        return;
  1844. X
  1845. X    /* don't do some other transition */
  1846. X    if (cli->wmState != NormalState)
  1847. X        return;
  1848. X
  1849. X    /* we can't iconify if we are a dependent */
  1850. X    if (cli->groupmask == GROUP_DEPENDENT)
  1851. X        return;
  1852. X
  1853. X    /* Map the icon window */
  1854. X    IconShow(cli, winIcon);
  1855. X
  1856. X    /* iconify self and dependents */
  1857. X    if (cli->groupmask == GROUP_LEADER)
  1858. X        GroupApply(cli->groupid, iconifyOne, winIcon,
  1859. X               GROUP_LEADER|GROUP_DEPENDENT);
  1860. X    else
  1861. X        iconifyOne(cli,winIcon);
  1862. X
  1863. X    if (cli == CurrentClient && !GRV.FocusFollowsMouse)
  1864. X        ClientSetFocus(cli, False, TimeFresh(cli->iconwin));
  1865. X}
  1866. X
  1867. X/* 
  1868. X * StateIconNorm - transition a window to NormalState from IconicState 
  1869. X */
  1870. Xvoid
  1871. XStateIconNorm(cli)
  1872. XClient *cli;
  1873. X{
  1874. X    WinIconFrame *winIcon = cli->iconwin;
  1875. X
  1876. X    if (winIcon == NULL)
  1877. X        return;
  1878. X
  1879. X    /* don't do some other transition */
  1880. X    if (cli->wmState != IconicState)
  1881. X        return;
  1882. X
  1883. X    if (cli->groupmask == GROUP_LEADER)
  1884. X        deiconifyGroup(cli, winIcon);
  1885. X    else
  1886. X        deiconifyOne(cli,winIcon,True);
  1887. X
  1888. X    /* Unmap icons */
  1889. X    IconHide(cli, winIcon);
  1890. X
  1891. X    if (cli == CurrentClient && !GRV.FocusFollowsMouse)
  1892. X        ClientSetFocus(cli, True, TimeFresh(cli->framewin));
  1893. X}
  1894. X
  1895. X/*
  1896. X * StateWithdrawn - a window is being withdrawn; tear down all related
  1897. X *    structures; clear the client out of all lists it may be
  1898. X *     on; reparent the pane window
  1899. X */
  1900. Xvoid
  1901. XStateWithdrawn(cli)
  1902. XClient *cli;
  1903. X{
  1904. X    WinIconFrame *iconInfo = cli->iconwin;
  1905. X    WinPaneFrame *frameInfo = cli->framewin;
  1906. X    WinPane *paneInfo;
  1907. X    Window pane;
  1908. X    Display *dpy = cli->dpy;
  1909. X
  1910. X    if (iconInfo == NULL || frameInfo == NULL)
  1911. X        return;
  1912. X
  1913. X    paneInfo = (WinPane*)(frameInfo->fcore.panewin);
  1914. X    pane = paneInfo->core.self;
  1915. X    iconInfo = cli->iconwin;
  1916. X
  1917. X        /* Return the pointer if necessary */
  1918. X    FrameUnwarpPointer(cli);
  1919. X
  1920. X        /* Unmap the frame and pane. */
  1921. X        UnmapWindow(frameInfo);
  1922. X        XUnmapWindow(dpy, pane);
  1923. X
  1924. X    /* Unmap the icon */
  1925. X    if (iconInfo != NULL)
  1926. X        IconHide(cli, iconInfo);
  1927. X
  1928. X    /* move the pane and unparent it */
  1929. X    FrameUnparentPane(cli, frameInfo, paneInfo);
  1930. X
  1931. X    DestroyClient(cli);
  1932. X}
  1933. X
  1934. X/************************************************************************
  1935. X *        Top-Level Window Property Update Functions
  1936. X ************************************************************************/
  1937. X
  1938. X/*
  1939. X * Refresh SizeHints from WM_NORMAL_HINTS property.  The new values
  1940. X * can simply be copied into the client's normHints.
  1941. X */
  1942. Xvoid
  1943. XStateUpdateWMNormalHints(cli,event)
  1944. X    Client        *cli;
  1945. X    XPropertyEvent    *event;
  1946. X{
  1947. X    Window        pane;
  1948. X    XSizeHints    sizeHints;
  1949. X    Bool        preICCCM;
  1950. X
  1951. X    if (event->state != PropertyNewValue)
  1952. X        return;
  1953. X
  1954. X    pane = PANEWINOFCLIENT(cli);
  1955. X
  1956. X    if (!PropGetWMNormalHints(cli->dpy,pane,&sizeHints,&preICCCM))
  1957. X        return;
  1958. X
  1959. X    *(cli->normHints) = sizeHints;
  1960. X}
  1961. X
  1962. X/*
  1963. X * Reapply WMHints from the WM_HINTS property.  Ignore everything but
  1964. X * InputHint and Icon{Pixmap/Mask}Hint.
  1965. X */
  1966. Xvoid
  1967. XStateUpdateWMHints(cli,event)
  1968. X    Client        *cli;
  1969. X    XPropertyEvent    *event;
  1970. X{
  1971. X    Window        pane;
  1972. X    XWMHints    wmHints;
  1973. X    WinIconPane    *iconPane;
  1974. X    Pixmap        iconMask;
  1975. X
  1976. X    if (cli->framewin == NULL || cli->iconwin == NULL ||
  1977. X        event->state != PropertyNewValue)
  1978. X        return;
  1979. X
  1980. X    pane = PANEWINOFCLIENT(cli);
  1981. X    iconPane = (WinIconPane *)cli->iconwin->fcore.panewin;
  1982. X
  1983. X    if (!PropGetWMHints(cli->dpy,pane,&wmHints))
  1984. X        return;
  1985. X
  1986. X    if (wmHints.flags & InputHint) {
  1987. X        cli->focusMode = 
  1988. X            focusModeFromHintsProtocols(&wmHints,cli->protocols);
  1989. X    }
  1990. X
  1991. X    if (wmHints.flags & IconPixmapHint)
  1992. X        IconPaneSetPixmap(cli->dpy,iconPane,wmHints.icon_pixmap);
  1993. X    if (wmHints.flags & IconMaskHint) 
  1994. X        IconPaneSetMask(cli->dpy,iconPane,wmHints.icon_mask);
  1995. X    if (wmHints.flags & IconPixmapHint || wmHints.flags & IconMaskHint) 
  1996. X        WinDrawFunc(iconPane);
  1997. X
  1998. X    if (cli->wmHints == NULL)
  1999. X        cli->wmHints = MemNew(XWMHints);
  2000. X
  2001. X    *(cli->wmHints) = wmHints;
  2002. X}
  2003. X
  2004. X/*
  2005. X * Reset client protocols and focusMode from WM_PROTOCOLS
  2006. X */
  2007. Xvoid
  2008. XStateUpdateWMProtocols(cli,event)
  2009. X    Client        *cli;
  2010. X    XPropertyEvent    *event;
  2011. X{
  2012. X    Window        pane;
  2013. X    int        protocols;
  2014. X
  2015. X    if (cli->framewin == NULL || event->state != PropertyNewValue)
  2016. X        return;
  2017. X
  2018. X    pane = PANEWINOFCLIENT(cli);
  2019. X
  2020. X    if (!PropGetWMProtocols(cli->dpy,pane,&protocols))
  2021. X        return;
  2022. X
  2023. X    if (cli->protocols == protocols)
  2024. X        return;
  2025. X
  2026. X    cli->focusMode = focusModeFromHintsProtocols(cli->wmHints,protocols);
  2027. X    cli->protocols = protocols;
  2028. X}
  2029. X
  2030. X/*
  2031. X * StateUpdateWinAttr - reread the _OL_WIN_ATTR property. 
  2032. X *    For now just apply WA_PINSTATE.
  2033. X */
  2034. Xvoid
  2035. XStateUpdateWinAttr(cli,event)
  2036. X    Client        *cli;
  2037. X    XPropertyEvent    *event;
  2038. X{
  2039. X    OLWinAttr    winAttr;
  2040. X    Bool        old;
  2041. X    Window        pane;
  2042. X
  2043. X    if (cli->framewin == NULL || event->state != PropertyNewValue)
  2044. X        return;
  2045. X
  2046. X    pane = PANEWINOFCLIENT(cli);
  2047. X
  2048. X    if (!PropGetOLWinAttr(cli->dpy,pane,&winAttr,&old))
  2049. X        return;
  2050. X        
  2051. X    if ((winAttr.flags & WA_PINSTATE) && ClientIsPinnable(cli)) {
  2052. X        WinPushPin *pushPin = (WinPushPin *)cli->framewin->winDeco;
  2053. X        PushPinSetPinState(cli->dpy,pushPin,
  2054. X                    winAttr.pin_initial_state,False);
  2055. X    }
  2056. X}
  2057. X
  2058. X/*
  2059. X * StateUpdateDecorAdd - read the DecorAdd property and reapply it
  2060. X */
  2061. Xvoid
  2062. XStateUpdateDecorAdd(cli,event)
  2063. X    Client        *cli;
  2064. X    XPropertyEvent    *event;
  2065. X{
  2066. X    /* REMIND - this needs to be implemented */
  2067. X}
  2068. X
  2069. X/*
  2070. X * StateUpdateDecorDel - read the DecorDel property and reapply it
  2071. X */
  2072. Xvoid
  2073. XStateUpdateDecorDel(cli,event)
  2074. X    Client        *cli;
  2075. X    XPropertyEvent    *event;
  2076. X{
  2077. X    /* REMIND - this needs to be implemented */
  2078. X}
  2079. END_OF_FILE
  2080. if test 33415 -ne `wc -c <'states.c'`; then
  2081.     echo shar: \"'states.c'\" unpacked with wrong size!
  2082. fi
  2083. # end of 'states.c'
  2084. fi
  2085. echo shar: End of archive 10 \(of 21\).
  2086. cp /dev/null ark10isdone
  2087. MISSING=""
  2088. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  2089.     if test ! -f ark${I}isdone ; then
  2090.     MISSING="${MISSING} ${I}"
  2091.     fi
  2092. done
  2093. if test "${MISSING}" = "" ; then
  2094.     echo You have unpacked all 21 archives.
  2095.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2096. else
  2097.     echo You still need to unpack the following archives:
  2098.     echo "        " ${MISSING}
  2099. fi
  2100. ##  End of shell archive.
  2101. exit 0
  2102. --
  2103. Molecular Simulations, Inc.             mail: dcmartin@postgres.berkeley.edu
  2104. 796 N. Pastoria Avenue                  uucp: uwvax!ucbvax!dcmartin
  2105. Sunnyvale, California 94086             at&t: 408/522-9236
  2106.