home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume15 / olvwm-3.0 / part16 < prev    next >
Internet Message Format  |  1992-02-03  |  57KB

  1. Path: uunet!sun-barr!ames!pasteur!nntp
  2. From: scott.oaks@East.Sun.COM (Scott Oaks)
  3. Newsgroups: comp.sources.x
  4. Subject: v15i162: OpenLook Virtual Window Mgr (3.0), Part16/21
  5. Message-ID: <1992Feb4.135937.8021@pasteur.Berkeley.EDU>
  6. Date: 4 Feb 92 13:59:37 GMT
  7. References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
  8. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  9. Organization: University of California, at Berkeley
  10. Lines: 1990
  11. Approved: dcmartin@msi.com
  12. Nntp-Posting-Host: postgres.berkeley.edu
  13.  
  14. Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
  15. Posting-number: Volume 15, Issue 162
  16. Archive-name: olvwm-3.0/part16
  17.  
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  22. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  23. # If this archive is complete, you will see the following message at the end:
  24. #        "End of archive 16 (of 21)."
  25. # Contents:  LEGAL_NOTICE events.c slots.c wingframe.c
  26. # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:47 1992
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'LEGAL_NOTICE' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'LEGAL_NOTICE'\"
  30. else
  31. echo shar: Extracting \"'LEGAL_NOTICE'\" \(2808 characters\)
  32. sed "s/^X//" >'LEGAL_NOTICE' <<'END_OF_FILE'
  33. X    NOTICE TO USER: The source code, including the glyphs or icons 
  34. X    forming a par of the OPEN LOOK TM Graphic User Interface, on this 
  35. X    tape and in these files is copyrighted under U.S. and international
  36. X    laws. Sun Microsystems, Inc. of Mountain View, California owns
  37. X    the copyright and has design patents pending on many of the icons. 
  38. X    AT&T is the owner of the OPEN LOOK trademark associated with the
  39. X    materials on this tape. Users and possessors of this source code 
  40. X    are hereby granted a nonexclusive, royalty-free copyright and 
  41. X    design patent license to use this code in individual and 
  42. X    commercial software. A royalty-free, nonexclusive trademark
  43. X    license to refer to the code and output as "OPEN LOOK" compatible 
  44. X    is available from AT&T if, and only if, the appearance of the 
  45. X    icons or glyphs is not changed in any manner except as absolutely
  46. X    necessary to accommodate the standard resolution of the screen or
  47. X    other output device, the code and output is not changed except as 
  48. X    authorized herein, and the code and output is validated by AT&T. 
  49. X    Bigelow & Holmes is the owner of the Lucida (R) trademark for the
  50. X    fonts and bit-mapped images associated with the materials on this 
  51. X    tape. Users are granted a royalty-free, nonexclusive license to use
  52. X    the trademark only to identify the fonts and bit-mapped images if, 
  53. X    and only if, the fonts and bit-mapped images are not modified in any
  54. X    way by the user. 
  55. X
  56. X
  57. X    Any use of this source code must include, in the user documentation 
  58. X    and internal comments to the code, notices to the end user as  
  59. X    follows:
  60. X
  61. X
  62. X    (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
  63. X    pending in the U.S. and foreign countries. OPEN LOOK is a 
  64. X    trademark of AT&T. Used by written permission of the owners.
  65. X
  66. X
  67. X     (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered 
  68. X    trademark of Bigelow & Holmes. Permission to use the Lucida 
  69. X    trademark is hereby granted only in association with the images 
  70. X    and fonts described in this file.
  71. X
  72. X
  73. X
  74. X    SUN MICROSYSTEMS, INC., AT&T, AND BIGELOW & HOLMES 
  75. X    MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF
  76. X     THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" 
  77. X    WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. 
  78. X    SUN  MICROSYSTEMS, INC., AT&T AND BIGELOW  & HOLMES, 
  79. X    SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES 
  80. X    WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED
  81. X    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  82. X    PARTICULAR PURPOSE. IN NO EVENT SHALL SUN MICROSYSTEMS,
  83. X    INC., AT&T OR BIGELOW & HOLMES BE LIABLE FOR ANY
  84. X    SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
  85. X    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA     
  86. X    OR PROFITS, WHETHER IN AN ACTION OF  CONTRACT, NEGLIGENCE
  87. X    OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  88. X    WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
  89. END_OF_FILE
  90. if test 2808 -ne `wc -c <'LEGAL_NOTICE'`; then
  91.     echo shar: \"'LEGAL_NOTICE'\" unpacked with wrong size!
  92. fi
  93. # end of 'LEGAL_NOTICE'
  94. fi
  95. if test -f 'events.c' -a "${1}" != "-c" ; then 
  96.   echo shar: Will not clobber existing file \"'events.c'\"
  97. else
  98. echo shar: Extracting \"'events.c'\" \(16710 characters\)
  99. sed "s/^X//" >'events.c' <<'END_OF_FILE'
  100. X/*
  101. X *      (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
  102. X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
  103. X *      file for terms of the license.
  104. X */
  105. X
  106. X#ident "@(#)events.c    1.1 olvwm version 1/3/92"
  107. X
  108. X/*
  109. X * Based on
  110. X#ident    "@(#)events.c    26.40    91/09/14 SMI"
  111. X *
  112. X */
  113. X
  114. X#include <errno.h>
  115. X#include <stdio.h>
  116. X#include <string.h>
  117. X#include <sys/types.h>
  118. X#include <sys/time.h>
  119. X
  120. X#include <X11/Xlib.h>
  121. X#include <X11/Xresource.h>
  122. X#include <X11/Xutil.h>
  123. X#include <X11/keysym.h>
  124. X
  125. X#include "i18n.h"
  126. X#include "ollocale.h"
  127. X#include "olwm.h"
  128. X#include "win.h"
  129. X#include "globals.h"
  130. X#include "events.h"
  131. X#include "list.h"
  132. X#include "mem.h"
  133. X
  134. X/* ===== externs ========================================================== */
  135. X
  136. Xextern int    DeadChildren;
  137. Xextern void    ReapChildren();
  138. X
  139. X/* ===== globals ========================================================== */
  140. X
  141. XTime LastEventTime = (Time) 0;
  142. XKeySym *KbdMap = NULL;        /* pointer to current key table; 2d array */
  143. Xint MinKeyCode = 0;
  144. Xint MaxKeyCode = 0;
  145. Xint KeySymsPerKeyCode = 0;
  146. X
  147. X/* ===== private data ===================================================== */
  148. X
  149. Xstatic int (*interposer)() = NULL;
  150. Xstatic void *closure;
  151. Xstatic List *deferredEventListHead = NULL_LIST;
  152. Xstatic List *deferredEventListTail = NULL_LIST;
  153. X
  154. Xstatic struct timeval timeoutNext = {0, 0};
  155. Xstatic TimeoutFunc timeoutFunc = NULL;
  156. Xstatic void *timeoutClosure = NULL;
  157. X
  158. Xstatic XModifierKeymap *ModMap = NULL;
  159. X
  160. Xstatic explicitPointerGrab = False;
  161. X
  162. X/* ===== private functions ================================================ */
  163. X
  164. X/*
  165. X * lookupWindow
  166. X * 
  167. X * Given an event, look up the WinInfo corresponding to the window field of 
  168. X * the event.  For events that have no window field, return NULL.
  169. X */
  170. XWinGeneric *
  171. XlookupWindow( event )
  172. X    XEvent *event;
  173. X{
  174. X    switch ( event->xany.type ) {
  175. X    case KeymapNotify:
  176. X    case MappingNotify:
  177. X    /* these events have no window field */
  178. X    return NULL;
  179. X    default:
  180. X    return WIGetInfo( event->xany.window );
  181. X    }
  182. X}
  183. X
  184. X
  185. X/*
  186. X * saveTimestamp
  187. X *
  188. X * Given an event, update LastEventTime with its timestamp.  For events that 
  189. X * have no timestamp, do nothing.
  190. X */
  191. Xvoid
  192. XsaveTimestamp( event )
  193. X    XEvent *event;
  194. X{
  195. X    switch ( event->xany.type ) {
  196. X    case KeyPress:
  197. X    case KeyRelease:
  198. X    LastEventTime = event->xkey.time;
  199. X    break;
  200. X    case ButtonPress:
  201. X    case ButtonRelease:
  202. X    LastEventTime = event->xbutton.time;
  203. X    break;
  204. X    case MotionNotify:
  205. X    LastEventTime = event->xmotion.time;
  206. X    break;
  207. X    case EnterNotify:
  208. X    case LeaveNotify:
  209. X    LastEventTime = event->xcrossing.time;
  210. X    break;
  211. X    case PropertyNotify:
  212. X    LastEventTime = event->xproperty.time;
  213. X    break;
  214. X    case SelectionClear:
  215. X    LastEventTime = event->xselectionclear.time;
  216. X    break;
  217. X    case SelectionRequest:
  218. X    /*
  219. X     * The timestamp in SelectionRequest events comes from other clients; 
  220. X     * it's not generated by the server.  It's thus not clear whether we 
  221. X     * should believe any timestamp in one of these events.
  222. X     */
  223. X    /* LastEventTime = event->xselectionrequest.time; */
  224. X    break;
  225. X    case SelectionNotify:
  226. X    /*
  227. X     * Ignore SelectionNotify events generated by other clients.
  228. X     * Save only the timestamps from server-generated events.
  229. X     */
  230. X    if (!event->xany.send_event)
  231. X        LastEventTime = event->xselection.time;
  232. X    break;
  233. X    default:
  234. X    break;
  235. X    }
  236. X}
  237. X
  238. X
  239. X/*
  240. X * Dispatches an event normally (i.e. not through an interposer).  Looks up
  241. X * the window structure from the event's window ID and calls the appropriate
  242. X * event function for that window's class.  All extension events are handled
  243. X * through a single extension event handler in the class.  If explicitGrab is
  244. X * set, then someone has explicitly grabbed the pointer and redispatched the
  245. X * event to a handler that is expecting an implicit grab, and so which won't
  246. X * ungrab the pointer.  We must therefore do an explicit ungrab of the
  247. X * pointer.
  248. X */
  249. Xstatic void
  250. XdispatchEvent(dpy, event, winInfo)
  251. XDisplay *dpy;
  252. XXEvent *event;
  253. XWinGeneric *winInfo;
  254. X{
  255. X    EvFunc evFunc;
  256. X
  257. X    if (GRV.PrintAll)
  258. X        DebugEvent(event, "Dispatch - debug");
  259. X
  260. X    saveTimestamp( event );
  261. X
  262. X    if (winInfo == NULL)
  263. X    {
  264. X        if (DispatchVirtual(dpy, event))
  265. X            return;
  266. X        else {
  267. X            /* REMIND should we do anything with these events? */
  268. X                if (GRV.PrintOrphans)
  269. X                    DebugEvent(event, "Orphaned (null window)");
  270. X
  271. X            /* If a client unmaps and then remaps its window, the
  272. X             * MapRequest comes in on the frame window, but we just
  273. X             * destroyed that window (on the unmap) so it appears as
  274. X             * an orphan window.  Hence we'll just create a new
  275. X             * frame/etc via StateNew()
  276. X             */
  277. X            if (event->xany.type == MapRequest) {
  278. X                StateNew(dpy, None,
  279. X                     event->xmaprequest.window, False, NULL);
  280. X            }
  281. X        }
  282. X
  283. X        return;
  284. X    }
  285. X
  286. X    if (GRV.PrintAll)
  287. X        DebugWindow(winInfo);
  288. X
  289. X#ifdef DEBUG
  290. X        if (winInfo->class == NULL)
  291. X    {
  292. X        ErrorGeneral("Window instance with NULL class pointer");
  293. X    }
  294. X
  295. X    if (winInfo->core.kind != winInfo->class->core.kind)
  296. X        ErrorWarning("Warning:  window with kind different than class kind");
  297. X#endif 
  298. X
  299. X    if (event->xany.type >= LASTEvent)
  300. X        evFunc = WinClass(winInfo)->core.extEventHdlr;
  301. X    else
  302. X        evFunc = WinClass(winInfo)->core.xevents[event->xany.type];
  303. X
  304. X    if (evFunc != NULL)
  305. X    {
  306. X        (*evFunc)(dpy, event, winInfo);
  307. X    }
  308. X    else if (!DispatchVirtual(dpy, event))
  309. X        if (GRV.PrintOrphans)
  310. X        DebugEvent(event, "Orphaned");
  311. X
  312. X    if (explicitPointerGrab && event->type == ButtonRelease &&
  313. X        AllButtonsUp(event))
  314. X    {
  315. X        XUngrabPointer(dpy, event->xbutton.time);
  316. X    }
  317. X}
  318. X
  319. Xstatic int
  320. XdispatchInterposer(dpy, event)
  321. XDisplay *dpy;
  322. XXEvent *event;
  323. X{
  324. X    int disposition;
  325. X    WinGeneric *winInfo;
  326. X    XEvent *temp;
  327. X
  328. X    if (GRV.PrintAll)
  329. X        DebugEvent(event, "Dispatch - interposer");
  330. X
  331. X    saveTimestamp( event );
  332. X    winInfo = lookupWindow(event);
  333. X    disposition = (*interposer)(dpy, event, winInfo, closure);
  334. X
  335. X    switch (disposition) {
  336. X    case DISPOSE_DISPATCH:
  337. X        dispatchEvent(dpy, event, winInfo);
  338. X        break;
  339. X    case DISPOSE_DEFER:
  340. X        temp = MemNew(XEvent);
  341. X        *temp = *event;
  342. X        if (deferredEventListHead == NULL_LIST) {
  343. X        deferredEventListHead = ListCons(temp, NULL_LIST);
  344. X        deferredEventListTail = deferredEventListHead;
  345. X        } else {
  346. X        deferredEventListTail->next = ListCons(temp, NULL_LIST);
  347. X        deferredEventListTail = deferredEventListTail->next;
  348. X        }
  349. X        break;
  350. X    case DISPOSE_USED:
  351. X        /* do nothing */
  352. X        break;
  353. X    }
  354. X}
  355. X
  356. Xstatic void
  357. XdoTimeout()
  358. X{
  359. X    TimeoutFunc f;
  360. X    void *closure;
  361. X
  362. X    f = timeoutFunc;
  363. X    closure = timeoutClosure;
  364. X    TimeoutCancel();
  365. X    (*f)(closure);
  366. X}
  367. X
  368. Xstatic void
  369. XnextEventOrTimeout(dpy, event)
  370. XDisplay *dpy;
  371. XXEvent *event;
  372. X{
  373. X    int fd = ConnectionNumber(dpy);
  374. X    struct timeval polltime;
  375. X    fd_set rdset, wrset, xset;
  376. X    int ready = -1;
  377. X
  378. X    while (XPending(dpy) == 0 && ready <= 0 && timeoutFunc != NULL) {
  379. X        gettimeofday(&polltime,NULL);
  380. X        if ((timeoutFunc != NULL) &&
  381. X        ((polltime.tv_sec > timeoutNext.tv_sec) ||
  382. X         ((polltime.tv_sec == timeoutNext.tv_sec) && 
  383. X          (polltime.tv_usec >= timeoutNext.tv_usec))))
  384. X        {
  385. X        doTimeout();
  386. X        continue;
  387. X        }
  388. X
  389. X        polltime.tv_sec = timeoutNext.tv_sec - polltime.tv_sec;
  390. X        polltime.tv_usec = 0;
  391. X
  392. X        FD_ZERO(&rdset);
  393. X        FD_SET(fd,&rdset);
  394. X        FD_ZERO(&wrset);
  395. X        FD_ZERO(&xset);
  396. X        FD_SET(fd,&xset);
  397. X
  398. X        ready = select(fd+1,&rdset,&wrset,&xset,&polltime);
  399. X
  400. X        gettimeofday(&polltime,NULL);
  401. X        if ((timeoutFunc != NULL) &&
  402. X        ((polltime.tv_sec > timeoutNext.tv_sec) ||
  403. X         ((polltime.tv_sec == timeoutNext.tv_sec) && 
  404. X          (polltime.tv_usec >= timeoutNext.tv_usec))))
  405. X        {
  406. X        doTimeout();
  407. X        }
  408. X    }
  409. X
  410. X    XNextEvent(dpy, event);
  411. X}
  412. X
  413. X
  414. X/*
  415. X * Update our own modifier map.  This is unfortunate, as we know Xlib already 
  416. X * keeps this information around.
  417. X */
  418. Xstatic void
  419. XupdateModifierMap(dpy)
  420. X    Display *dpy;
  421. X{
  422. X    if (ModMap != NULL)
  423. X    XFreeModifiermap(ModMap);
  424. X    ModMap = XGetModifierMapping(dpy);
  425. X}
  426. X
  427. X
  428. X/*
  429. X * Update our own keyboard table.  This is unfortunate, as we know Xlib 
  430. X * already keeps this information around.
  431. X */
  432. Xstatic void
  433. XupdateKeyboardMap(dpy)
  434. X    Display *dpy;
  435. X{
  436. X    if (KbdMap != NULL )
  437. X    XFree((char *)KbdMap);
  438. X    XDisplayKeycodes(dpy, &MinKeyCode, &MaxKeyCode);
  439. X    KbdMap = XGetKeyboardMapping(dpy, MinKeyCode, MaxKeyCode-MinKeyCode+1,
  440. X                 &KeySymsPerKeyCode);
  441. X}
  442. X
  443. X
  444. X/*
  445. X * Handle MappingNotify events.  Refresh cached information about the keyboard 
  446. X * and the pointer.
  447. X */
  448. Xvoid
  449. XhandleMappingNotify(dpy, e)
  450. X    Display *dpy;
  451. X    XEvent *e;
  452. X{
  453. X    XMappingEvent    *mapEvent = (XMappingEvent *)e;
  454. X
  455. X    switch (mapEvent->request) {
  456. X    case MappingModifier:
  457. X    XRefreshKeyboardMapping(mapEvent);
  458. X    updateModifierMap(dpy);
  459. X    RefreshKeyGrabs(dpy);
  460. X    RefreshButtonGrabs(dpy);
  461. X    break;
  462. X    case MappingKeyboard:
  463. X    XRefreshKeyboardMapping(mapEvent);
  464. X    updateKeyboardMap(dpy);
  465. X    RefreshKeyGrabs(dpy);
  466. X    break;
  467. X    case MappingPointer:
  468. X    /* no need to handle pointer mapping changes */
  469. X    break;
  470. X    }
  471. X}
  472. X
  473. X
  474. X/*ARGSUSED*/
  475. Xstatic void *
  476. XredispatchEvent(e,c)
  477. X    XEvent *e;
  478. X    void   *c;
  479. X{
  480. X    dispatchEvent(e->xany.display, e, lookupWindow(e));
  481. X    MemFree(e);
  482. X    return (void *)NULL;
  483. X}
  484. X
  485. X
  486. X/*
  487. X * Compute t2 - t1 and return the time value in diff.  The tv_usec field is 
  488. X * always in the range 0..999999.  This means that negative time values always 
  489. X * have tv_sec less than zero.  For instance, negative one-half seconds is 
  490. X * represented with tv_sec == -1 and tv_usec == 500000.
  491. X */
  492. Xstatic void
  493. Xtvdiff(t1, t2, diff)
  494. X    struct timeval *t1, *t2, *diff;
  495. X{
  496. X    diff->tv_sec = t2->tv_sec - t1->tv_sec;
  497. X    diff->tv_usec = t2->tv_usec - t1->tv_usec;
  498. X    if (diff->tv_usec < 0) {
  499. X    diff->tv_sec -= 1;
  500. X    diff->tv_usec += 1000000;
  501. X    }
  502. X}
  503. X
  504. X
  505. X/* ===== public functions ================================================= */
  506. X
  507. X
  508. X/*
  509. X * EventLoop
  510. X * 
  511. X * The main event loop.  Reads events from the wire and dispatches them.
  512. X */
  513. Xvoid
  514. XEventLoop( dpy )
  515. X    Display *dpy;
  516. X{
  517. X    XEvent        event;
  518. X
  519. X    for (;;) {
  520. X        if (timeoutFunc == NULL)
  521. X        {
  522. X            XNextEvent( dpy, &event );
  523. X        } 
  524. X        else
  525. X        {
  526. X            nextEventOrTimeout(dpy, &event);
  527. X        }
  528. X
  529. X        if (DeadChildren > 0)
  530. X            ReapChildren();
  531. X
  532. X        /*
  533. X         * Discard user events that have the Synthetic bit set.
  534. X         *
  535. X         * All device events (mouse and keyboard events) have types
  536. X         * that fall in between KeyPress and MotionNotify.
  537. X         */
  538. X        if (event.xany.send_event
  539. X            && event.type <= MotionNotify
  540. X            && event.type >= KeyPress)
  541. X            continue;
  542. X
  543. X
  544. X        /*
  545. X         * Handle MappingNotify events.  These events don't have 
  546. X         * window field, so they can't be dispatched normally.
  547. X         */
  548. X        if (event.xany.type == MappingNotify) {
  549. X            handleMappingNotify(dpy, &event);
  550. X            continue;
  551. X        }
  552. X
  553. X        /*
  554. X         * If there is an event interposer, and it returns True, that 
  555. X         * means it has successfully processed the event.  We continue 
  556. X         * around the loop instead of processing the event normally.
  557. X         */
  558. X        if ( interposer != NULL)
  559. X            dispatchInterposer(dpy, &event);
  560. X        else
  561. X            dispatchEvent(dpy, &event, lookupWindow(&event));
  562. X    }
  563. X
  564. X    /*NOTREACHED*/
  565. X}
  566. X
  567. X
  568. X/*
  569. X * Propagate an event to this window's parent.  REMIND: doesn't update the 
  570. X * event fields or the event coordinates.
  571. X */
  572. Xint
  573. XPropagateEventToParent(dpy,event,win)
  574. XDisplay *dpy;
  575. XXEvent *event;
  576. XWinGeneric *win;
  577. X{
  578. X    dispatchEvent(dpy,event,win->core.parent);
  579. X}
  580. X
  581. X
  582. X/*
  583. X * Propagate a ButtonPress event to a child window.  Win is assumed to be a
  584. X * child of the event window.  The event window and subwindow fields are
  585. X * updated, and the coordinates are translated to the child's coordinate
  586. X * system.  Sets the explicitPointerGrab flag.
  587. X */
  588. Xvoid
  589. XPropagatePressEventToChild(dpy, event, win)
  590. X    Display *dpy;
  591. X    XButtonPressedEvent *event;
  592. X    WinGeneric *win;
  593. X{
  594. X    event->window = win->core.self;
  595. X    event->subwindow = None;
  596. X    event->x -= win->core.x;
  597. X    event->y -= win->core.y;
  598. X    dispatchEvent(dpy, event, win);
  599. X    explicitPointerGrab = True;
  600. X}
  601. X
  602. X
  603. X/*
  604. X * FindModifierMask
  605. X *
  606. X * Given a keycode, look in the modifier mapping table to see if this keycode 
  607. X * is a modifier.  If it is, return the modifier mask bit for this key; 
  608. X * otherwise, return zero.
  609. X */
  610. Xunsigned int
  611. XFindModifierMask(kc)
  612. XKeyCode    kc;
  613. X{
  614. X    int i, j;
  615. X    KeyCode *mapentry;
  616. X
  617. X    if (ModMap == NULL || kc == 0)
  618. X    return 0;
  619. X
  620. X    mapentry = ModMap->modifiermap;
  621. X    for (i=0; i<8; ++i) {
  622. X    for (j=0; j<(ModMap->max_keypermod); ++j) {
  623. X        if (kc == *mapentry)
  624. X        return 1 <<
  625. X            ( (mapentry - ModMap->modifiermap) / 
  626. X              ModMap->max_keypermod );
  627. X        ++mapentry;
  628. X    }
  629. X    }
  630. X    return 0;
  631. X}
  632. X
  633. X
  634. X/*
  635. X * Wait on dpy for some events to come in or for a timeout to occur.  If
  636. X * events come in, return True and change timeout to indicate the amount of
  637. X * time remaining.  If no events come in before the timeout expires, return
  638. X * False.  A negative timestamp is considered to have timed out immediately.
  639. X */
  640. XBool
  641. XAwaitEvents(dpy, timeout)
  642. X    Display *dpy;
  643. X    struct timeval *timeout;
  644. X{
  645. X    struct timeval starttime, curtime, diff1, diff2;
  646. X    fd_set rfds;
  647. X    int s;
  648. X
  649. X    if (timeout->tv_sec < 0)
  650. X    return False;
  651. X
  652. X    (void) gettimeofday(&starttime, NULL);
  653. X
  654. X    while (1) {
  655. X    FD_ZERO(&rfds);
  656. X    FD_SET(ConnectionNumber(dpy), &rfds);
  657. X    s = select(ConnectionNumber(dpy)+1, &rfds, NULL, NULL, timeout);
  658. X    if (s == 0) {
  659. X        /* we timed out without getting anything */
  660. X        return False;
  661. X    }
  662. X
  663. X    /*
  664. X     * If an error occurred, report it and return False.
  665. X     */
  666. X    if (s == -1 && errno != EINTR) {
  667. X        perror("select");
  668. X#ifdef DEBUG
  669. X        fputs("olvwm: generating core dump for analysis...\n", stderr);
  670. X        if (fork() == 0) {
  671. X        abort();
  672. X        exit(1);
  673. X        }
  674. X#endif
  675. X        return False;
  676. X    }
  677. X
  678. X    /*
  679. X     * Either we got interrupted or the descriptor became ready, or both.
  680. X     * Compute the remaining time on the timeout.  This can be negative, 
  681. X     * because there is a slight window for delays between the select() 
  682. X     * call above and this gettimeofday() call.  This means that we can 
  683. X     * return an indication of valid data to the caller, yet also return
  684. X     * a value for the time remaining that is less than or equal to zero.
  685. X     */
  686. X    (void) gettimeofday(&curtime, NULL);
  687. X    tvdiff(&starttime, &curtime, &diff1);
  688. X    tvdiff(&diff1, timeout, &diff2);
  689. X    *timeout = diff2;
  690. X    starttime = curtime;
  691. X
  692. X    /*
  693. X     * If we got some data, return True.  Otherwise, we were interrupted.
  694. X     * If we timed out, return False.  If not, there is time remaining;
  695. X     * continue around the loop.
  696. X     */
  697. X    if (s > 0)
  698. X        return True;
  699. X
  700. X    if (timeout->tv_sec < 0)
  701. X        return False;
  702. X    }
  703. X}
  704. X    
  705. X
  706. X/***************************************************************************
  707. X* Interposer functions
  708. X***************************************************************************/
  709. X
  710. X/*
  711. X * InstallInterposer
  712. X *
  713. X * Install an event interposition function.  Nested interposition is illegal.
  714. X */
  715. Xvoid
  716. XInstallInterposer( func, cl )
  717. X    Bool (*func)();
  718. X    void *cl;
  719. X{
  720. X    if ( interposer != NULL ) {
  721. X    fputs( gettext("olvwm: warning, nested event interposer!\n"), stderr );
  722. X#ifdef DEBUG
  723. X    abort();
  724. X#endif /* DEBUG */
  725. X    }
  726. X    interposer = func;
  727. X    closure = cl;
  728. X}
  729. X
  730. X/*
  731. X * UninstallInterposer
  732. X *
  733. X * Uninstalls an event interposition function.  Does nothing if there is
  734. X * currently no interposer.  Replays any queued events.  Inhibits focus
  735. X * changes and colormap installation while replaying them.  This prevents 
  736. X * redundant focus changes and colormap installation.
  737. X */
  738. Xvoid
  739. XUninstallInterposer()
  740. X{
  741. X    interposer = (int (*)()) NULL;
  742. X
  743. X    if (deferredEventListHead != NULL) {
  744. X    ClientInhibitFocus(True);
  745. X    ColormapInhibit(True);
  746. X    ListApply(deferredEventListHead, redispatchEvent, 0);
  747. X    ListDestroy(deferredEventListHead);
  748. X    deferredEventListHead = deferredEventListTail = NULL_LIST;
  749. X    ClientInhibitFocus(False);
  750. X    ColormapInhibit(False);
  751. X    }
  752. X}
  753. X
  754. X
  755. X/*
  756. X * Return an indication of whether an interposer is currently installed.
  757. X */
  758. XBool
  759. XInterposerInstalled()
  760. X{
  761. X    return (interposer != NULL) ? True : False;
  762. X}
  763. X
  764. X
  765. X/***************************************************************************
  766. X* Timeout functions
  767. X***************************************************************************/
  768. X
  769. X/* TimeoutRequest(t,f,c) -- request that a timeout be generated t microseconds
  770. X *    in the future; when the timeout occurs, the function f is called
  771. X *    with the closure c.
  772. X */
  773. Xvoid
  774. XTimeoutRequest(t,f,c)
  775. Xint t;
  776. XTimeoutFunc f;
  777. Xvoid *c;
  778. X{
  779. X#ifdef DEBUG
  780. X    if (timeoutFunc != NULL)
  781. X    {
  782. X        ErrorWarning("Timeout being set while another timeout current");
  783. X    }
  784. X#endif
  785. X    gettimeofday(&timeoutNext,NULL);
  786. X    timeoutNext.tv_sec += t / 1000000;
  787. X    timeoutNext.tv_usec += t % 1000000;
  788. X    if (timeoutNext.tv_usec >= 1000000) {
  789. X        timeoutNext.tv_usec -= 1000000;
  790. X        timeoutNext.tv_sec += 1;
  791. X    }
  792. X    timeoutFunc = f;
  793. X    timeoutClosure = c;
  794. X}
  795. X
  796. X/* TimeoutCancel() -- cancel an outstanding timeout.
  797. X */
  798. Xvoid 
  799. XTimeoutCancel()
  800. X{
  801. X    timeoutNext.tv_sec = 0;
  802. X    timeoutNext.tv_usec = 0;
  803. X    timeoutFunc = NULL;
  804. X    timeoutClosure = NULL;
  805. X}
  806. X
  807. X
  808. X/*
  809. X * Initialize the event handling system.  This function is called exactly
  810. X * once at startup.
  811. X */
  812. Xvoid
  813. XInitEvents(dpy)
  814. X    Display *dpy;
  815. X{
  816. X    updateKeyboardMap(dpy);
  817. X    updateModifierMap(dpy);
  818. X}
  819. END_OF_FILE
  820. if test 16710 -ne `wc -c <'events.c'`; then
  821.     echo shar: \"'events.c'\" unpacked with wrong size!
  822. fi
  823. # end of 'events.c'
  824. fi
  825. if test -f 'slots.c' -a "${1}" != "-c" ; then 
  826.   echo shar: Will not clobber existing file \"'slots.c'\"
  827. else
  828. echo shar: Extracting \"'slots.c'\" \(16468 characters\)
  829. sed "s/^X//" >'slots.c' <<'END_OF_FILE'
  830. X/*
  831. X *      (c) Copyright 1990 Sun Microsystems, Inc. Sun design patents
  832. X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
  833. X *      file for terms of the license.
  834. X */
  835. X
  836. X#ident    "@(#)slots.c    1.1 olvwm version 1/3/92"
  837. X
  838. X/*
  839. X * Based on
  840. X#ident    "@(#)slots.c    26.8    91/09/14 SMI"
  841. X *
  842. X */
  843. X
  844. X#include <stdio.h>
  845. X#include <X11/Xos.h>
  846. X#include <X11/Xlib.h>
  847. X#include <X11/Xutil.h>
  848. X
  849. X#include "i18n.h"
  850. X#include "ollocale.h"
  851. X#include "mem.h"
  852. X#include "st.h"
  853. X#include "olwm.h"
  854. X#include "win.h"
  855. X#include "globals.h"
  856. X#include "list.h"
  857. X#include "slots.h"
  858. X
  859. X#define PLUSINFINITY 0xfffffff    /* REMIND fix this for architecture-independence */
  860. X
  861. X/***************************************************************************
  862. X* Local functions
  863. X***************************************************************************/
  864. X
  865. X#define ROUNDUP(n,d) (((n)+(d)-1)/(d))
  866. X/* #define ROUND(n,d) ((0.5+((float)(n)/(float)(d)))*(int)(d)) */
  867. X#define ROUND(n,d) (((((n)%(d))>((d)/2))?(((n)/(d))+1):((n)/(d)))*(d))
  868. X
  869. X#define SLOTOFFSET(ig,ma,mi)     (((ma))*(ig)->mislots+(mi))
  870. X#define AOCCUPANCY(ig,ma,mi)     ((ig->occupancy+SLOTOFFSET((ig),(ma),(mi))))
  871. X#define OCCUPANCY(ig,ma,mi)     (*(AOCCUPANCY((ig),(ma),(mi))))
  872. X
  873. X#define ISVERT(so) (((so)==SOBottomToTop)||((so)==SOTopToBottom))
  874. X#define ISHORZ(so) (((so)==SOLeftToRight)||((so)==SORightToLeft))
  875. X#define ISDECREASING(so) (((so)==SORightToLeft)||((so)==SOBottomToTop))
  876. X
  877. Xstatic char *
  878. Xsotochar(so)
  879. XSlotOrder so;
  880. X{
  881. X    if (so == SOTopToBottom)
  882. X        return ("SOTopToBottom");
  883. X    if (so == SOBottomToTop)
  884. X        return ("SOBottomToTop");
  885. X    if (so == SOLeftToRight)
  886. X        return ("SOLeftToRight");
  887. X    if (so == SORightToLeft)
  888. X        return ("SORightToLeft");
  889. X    return("SOIllegal");
  890. X}
  891. X
  892. X#ifdef notused
  893. X#ifdef DEBUG
  894. X/* dumpocc -- print the occupancy count table to stderr
  895. X */
  896. Xstatic void
  897. Xdumpocc()
  898. X{
  899. X    int ima, imi;
  900. X
  901. X    fprintf(stderr,"dump of occupancy table:\n");
  902. X    for (ima = 0; ima<maslots; ima++)
  903. X        for (imi = 0; imi<mislots; imi++)
  904. X        if (OCCUPANCY(ima,imi)!=0)
  905. X            fprintf(stderr,"%x: occ[%d,%d]/[%d] = %d\n",AOCCUPANCY(ima,imi),ima,imi,SLOTOFFSET(ima,imi),OCCUPANCY(ima,imi));
  906. X    fprintf(stderr,"end of dump of occupancy table\n");
  907. X}
  908. X#endif
  909. X#endif
  910. X
  911. X
  912. X/* setMajorMinor -- set two output variables from two input variables,
  913. X * based on the major/minor settings.
  914. X */
  915. Xstatic void
  916. XsetMajorMinor(iconGrid,r,c,pma,pmi)
  917. XIconGrid *iconGrid;
  918. Xint r, c, *pma, *pmi;
  919. X{
  920. X    if (ISVERT(iconGrid->SOmajor))
  921. X    {
  922. X        *pma = r;
  923. X        *pmi = c;
  924. X    }
  925. X    else
  926. X    {
  927. X        *pma = c;
  928. X        *pmi = r;
  929. X    }
  930. X}
  931. X
  932. X/* setAbsolute -- set two output variables from two input variables, based
  933. X * on major/minor settings; this is the inverse of setMajorMinor.
  934. X */
  935. Xstatic void
  936. XsetAbsolute(iconGrid,ma,mi,pr,pc)
  937. XIconGrid *iconGrid;
  938. Xint ma, mi;
  939. Xint *pr, *pc;
  940. X{
  941. X    if (ISVERT(iconGrid->SOmajor))
  942. X    {
  943. X    *pr = ma;
  944. X    *pc = mi;
  945. X    }
  946. X    else
  947. X    {
  948. X    *pc = ma;
  949. X    *pr = mi;
  950. X    }
  951. X}
  952. X
  953. X/* incrRegion -- increment the occupancy count of a region
  954. X */
  955. Xstatic void
  956. XincrRegion(iconGrid,slot,val)
  957. XIconGrid *iconGrid;
  958. XIconSlot *slot;
  959. Xint val;
  960. X{
  961. X    int ii,jj;
  962. X
  963. X    for (ii = slot->ma; 
  964. X        (ii>=0)&&(ii<iconGrid->maslots)&&(ii<slot->ma+slot->maw); ii++)
  965. X        for (jj = slot->mi; 
  966. X        (jj>=0)&&(jj<iconGrid->mislots)&&(jj<slot->mi+slot->miw); jj++)
  967. X        {
  968. X        if ((OCCUPANCY(iconGrid,ii,jj) += val) < iconGrid->minoccupancy)
  969. X            iconGrid->minoccupancy = OCCUPANCY(iconGrid,ii,jj);
  970. X        }
  971. X}
  972. X
  973. X/* findMinMaxRgn -- find the minimum and maximum occupancies of a region
  974. X */
  975. Xstatic void
  976. XfindMinMaxRgn(iconGrid,ma, mi, nmajor, nminor, pminrgn, pmaxrgn)
  977. XIconGrid *iconGrid;
  978. Xint ma, mi, nmajor, nminor, *pminrgn, *pmaxrgn;
  979. X{
  980. X    int min, max;
  981. X    int ii, jj;
  982. X    int occ;
  983. X
  984. X    min = PLUSINFINITY;
  985. X    max = -1;
  986. X
  987. X    for (ii=ma; ii<ma+nmajor; ii++)
  988. X        for (jj = mi; jj<mi+nminor; jj++)
  989. X        {
  990. X        occ = OCCUPANCY(iconGrid,ii,jj);
  991. X        if (occ < min)
  992. X            min = occ;
  993. X        if (occ > max)
  994. X            max = occ;
  995. X        }
  996. X    *pminrgn = min;
  997. X    *pmaxrgn = max;
  998. X}
  999. X
  1000. Xstatic IconSlot *
  1001. XincrDynamicSlots(iconGrid,nmajor, nminor)
  1002. XIconGrid *iconGrid;
  1003. Xint nmajor, nminor;
  1004. X{
  1005. X        int minoccrgn; /* smallest occupancy found for a region of given size */
  1006. X        int minfound, minfoundrgn;     /* smallest occupancy found for one slot
  1007. X                         * and a region respectively; used to reset
  1008. X                         * search values */
  1009. X        int ma, mi;    /* indices in major and minor directions */
  1010. X        int maxrgn, minrgn;      /* max and min occupancies in a region */
  1011. X    IconSlot *slot = MemNew(IconSlot);
  1012. X
  1013. X    minoccrgn = iconGrid->minoccupancy;
  1014. X    slot->positioned = False;
  1015. X
  1016. X    for (;;)    /* will actually only iterate twice */
  1017. X    {
  1018. X        minfound = minfoundrgn = PLUSINFINITY;
  1019. X        for (ma = 0; (ma <= iconGrid->maslots-nmajor); ma++)
  1020. X        {
  1021. X            for (mi = 0; (mi <= iconGrid->mislots-nminor); mi++)
  1022. X            {
  1023. X            findMinMaxRgn(iconGrid,ma,mi,nmajor,nminor,&minrgn,&maxrgn);
  1024. X            if (minrgn < minfound)
  1025. X            minfound = minrgn;
  1026. X            if (maxrgn < minfoundrgn)
  1027. X            minfoundrgn = maxrgn;
  1028. X            if (maxrgn <= minoccrgn)
  1029. X            {
  1030. X            slot->ma = ma;
  1031. X            slot->mi = mi;
  1032. X            slot->maw = nmajor;
  1033. X            slot->miw = nminor;
  1034. X            incrRegion(iconGrid,slot,1);
  1035. X            return slot;
  1036. X            }
  1037. X            }
  1038. X        }
  1039. X        /* no regions available with occupancy <= known minimum */
  1040. X        if (minfound > iconGrid->minoccupancy)  /* increase slot minimum */
  1041. X        iconGrid->minoccupancy = minfound;
  1042. X        minoccrgn = minfoundrgn;        /* increase local region min */
  1043. X    }
  1044. X}
  1045. X
  1046. X/* setIconPos -- given a slot, position the icon frame window accordingly.
  1047. X */
  1048. Xstatic void 
  1049. XsetIconPos(win, slot)
  1050. XWinIconFrame *win;
  1051. XIconSlot *slot;
  1052. X{
  1053. X    int x,y;
  1054. X    IconGrid *iconGrid = win->core.client->scrInfo->iconGrid;
  1055. X
  1056. X    if (iconGrid->SOmajor == SOTopToBottom)
  1057. X    {
  1058. X    y = ICON_GRID_HEIGHT*slot->ma;
  1059. X    if (iconGrid->SOminor == SOLeftToRight)
  1060. X    {
  1061. X        x = ICON_GRID_WIDTH*slot->mi;
  1062. X    }
  1063. X    else
  1064. X    {
  1065. X        x = iconGrid->pixhoriz - slot->mi*ICON_GRID_WIDTH - win->core.width;
  1066. X    }
  1067. X    }
  1068. X    else if (iconGrid->SOmajor == SOBottomToTop)
  1069. X    {
  1070. X    y = iconGrid->pixvert - ICON_GRID_HEIGHT*slot->ma - win->core.height;
  1071. X    if (iconGrid->SOminor == SOLeftToRight)
  1072. X    {
  1073. X        x = ICON_GRID_WIDTH*slot->mi;
  1074. X    }
  1075. X    else
  1076. X    {
  1077. X        x = iconGrid->pixhoriz - slot->mi*ICON_GRID_WIDTH - win->core.width;
  1078. X    }
  1079. X    }
  1080. X    else if (iconGrid->SOmajor == SOLeftToRight)
  1081. X    {
  1082. X    x = ICON_GRID_WIDTH*slot->ma;
  1083. X    if (iconGrid->SOminor == SOTopToBottom)
  1084. X    {
  1085. X        y = ICON_GRID_HEIGHT*slot->mi;
  1086. X    }
  1087. X    else
  1088. X    {
  1089. X        y = iconGrid->pixvert - slot->mi*ICON_GRID_HEIGHT - win->core.height;
  1090. X    }
  1091. X    }
  1092. X    else if (iconGrid->SOmajor == SORightToLeft)
  1093. X    {
  1094. X    x = iconGrid->pixhoriz - ICON_GRID_WIDTH*slot->ma - win->core.width;
  1095. X    if (iconGrid->SOminor == SOTopToBottom)
  1096. X    {
  1097. X        y = ICON_GRID_HEIGHT*slot->mi;
  1098. X    }
  1099. X    else
  1100. X    {
  1101. X        y = iconGrid->pixvert - slot->mi*ICON_GRID_HEIGHT - win->core.height;
  1102. X    }
  1103. X    }
  1104. X
  1105. X    x += slot->off_x;
  1106. X    y += slot->off_y;
  1107. X    (WinFunc(win,core.newposfunc))(win, x, y);
  1108. X}
  1109. X
  1110. X/* incrPositionedSlots -- an icon has been explicitly positioned; create an
  1111. X * iconslot record and increment the occupancy count of the affected slots.
  1112. X */
  1113. Xstatic IconSlot *
  1114. XincrPositionedSlots(iconGrid,x,y,w,h,snaptogrid)
  1115. XIconGrid *iconGrid;
  1116. Xint x,y,w,h;
  1117. XBool snaptogrid;
  1118. X{
  1119. X    IconSlot *slot = MemNew(IconSlot);
  1120. X#define ROUNDIF(v,w) (snaptogrid?ROUND((v),(w)):(v))/(w)
  1121. X#define ROUNDDIM(p,s,w) (ROUNDUP(((p)%(w))+(s),(w)))
  1122. X
  1123. X    if (iconGrid->SOmajor == SOTopToBottom)
  1124. X    {
  1125. X        slot->ma = ROUNDIF(y,ICON_GRID_HEIGHT);
  1126. X        slot->maw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
  1127. X        if (iconGrid->SOminor == SOLeftToRight)
  1128. X        {
  1129. X        slot->mi = ROUNDIF(x,ICON_GRID_WIDTH);
  1130. X            slot->miw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
  1131. X        }
  1132. X        else
  1133. X        {
  1134. X        slot->mi = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
  1135. X            slot->miw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
  1136. X        }
  1137. X    }
  1138. X    else if (iconGrid->SOmajor == SOBottomToTop)
  1139. X    {
  1140. X        slot->ma = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
  1141. X        slot->maw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
  1142. X        slot->miw = w;
  1143. X        if (iconGrid->SOminor == SOLeftToRight)
  1144. X        {
  1145. X        slot->mi = ROUNDIF(x,ICON_GRID_WIDTH);
  1146. X            slot->miw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
  1147. X        }
  1148. X        else
  1149. X        {
  1150. X        slot->mi = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
  1151. X            slot->miw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
  1152. X        }
  1153. X    }
  1154. X    else if (iconGrid->SOmajor == SOLeftToRight)
  1155. X    {
  1156. X        slot->ma = ROUNDIF(x,ICON_GRID_WIDTH);
  1157. X        slot->maw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
  1158. X        if (iconGrid->SOminor == SOTopToBottom)
  1159. X        {
  1160. X        slot->mi = ROUNDIF(y,ICON_GRID_HEIGHT);
  1161. X        slot->miw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
  1162. X        }
  1163. X        else
  1164. X        {
  1165. X        slot->mi = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
  1166. X        slot->miw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
  1167. X        }
  1168. X    }
  1169. X    else if (iconGrid->SOmajor == SORightToLeft)
  1170. X    {
  1171. X        slot->ma = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
  1172. X        slot->maw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
  1173. X        if (iconGrid->SOminor == SOTopToBottom)
  1174. X        {
  1175. X        slot->mi = ROUNDIF(y,ICON_GRID_HEIGHT);
  1176. X        slot->miw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
  1177. X        }
  1178. X        else
  1179. X        {
  1180. X        slot->mi = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
  1181. X        slot->miw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
  1182. X        }
  1183. X    }
  1184. X    if (slot->ma < 0) slot->ma = 0;
  1185. X    if (slot->ma >= iconGrid->maslots) slot->ma = iconGrid->maslots-1;
  1186. X    if (slot->mi < 0) slot->mi = 0;
  1187. X    if (slot->mi >= iconGrid->mislots) slot->mi = iconGrid->mislots-1;
  1188. X    slot->positioned = True;
  1189. X    incrRegion(iconGrid,slot,1);
  1190. X    return slot;
  1191. X}
  1192. X
  1193. X
  1194. X/***************************************************************************
  1195. X* Global functions
  1196. X***************************************************************************/
  1197. X
  1198. X/*
  1199. X * SlotInit -- 
  1200. X */
  1201. XIconGrid *
  1202. XSlotInit(dpy,screenno)
  1203. XDisplay *dpy;
  1204. Xint    screenno;
  1205. X{
  1206. X    IconGrid    *iconGrid;
  1207. X    int        occLen;
  1208. X
  1209. X    iconGrid = MemNew(IconGrid);
  1210. X    iconGrid->iconList = NULL_LIST;
  1211. X    iconGrid->pixhoriz = DisplayWidth(dpy,screenno);
  1212. X    iconGrid->pixvert = DisplayHeight(dpy,screenno);
  1213. X    iconGrid->slotshoriz = iconGrid->pixhoriz/ICON_GRID_WIDTH;
  1214. X    iconGrid->slotsvert = iconGrid->pixvert/ICON_GRID_HEIGHT;
  1215. X    occLen = iconGrid->slotshoriz * iconGrid->slotsvert * sizeof(int);
  1216. X    iconGrid->occupancy = MemAlloc(occLen);
  1217. X    iconGrid->minoccupancy = 0;
  1218. X    
  1219. X    SlotSetLocations(dpy,iconGrid);
  1220. X    
  1221. X    return iconGrid;
  1222. X}
  1223. X
  1224. X/* SlotAlloc - given a sized and possibly positioned icon window, allocate 
  1225. X * the appropriate slots for it.  If the window is positioned, 
  1226. X * True should be passed for the second parameter, and the x,y
  1227. X * position will be honoured.  If the window is not positioned, it
  1228. X * will be positioned by this function to the appropriate slots(s).
  1229. X * If snaptogrid is true and positioned is true, the given position is
  1230. X * modified so that the upper left corner of the icon is at the closest
  1231. X * icon grid point.  Modifies the icon structure to assign it the icon
  1232. X * slot.
  1233. X * Returns an IconSlot pointer if successful; NULL otherwise.
  1234. X *
  1235. X * If the window is not positioned, the x and y coordinates are used as
  1236. X * offsets to the position icon; this allows particular icons to be located`
  1237. X * in a particular logical screen within the virtual desktop.
  1238. X */
  1239. Xstruct _iconSlot * 
  1240. XSlotAlloc(winicon, positioned, snaptogrid)
  1241. XWinIconFrame *winicon;
  1242. XBool positioned;
  1243. XBool snaptogrid;
  1244. X{
  1245. X    int nhoriz, nvert;    /* number of slots occupied, horizontally & vertically */
  1246. X    int nmajor, nminor;    /* number of slots occupied, in major & minor directions */
  1247. X    IconSlot *slot;
  1248. X    IconGrid *iconGrid = winicon->core.client->scrInfo->iconGrid;
  1249. X    int        scr_x, scr_y;
  1250. X    int        dw, dh;
  1251. X
  1252. X    iconGrid->iconList = ListCons(winicon, iconGrid->iconList);
  1253. X
  1254. X    if (positioned)
  1255. X    {
  1256. X    dw = DisplayWidth(winicon->core.client->dpy,
  1257. X                        winicon->core.client->screen);
  1258. X    dh = DisplayHeight(winicon->core.client->dpy,
  1259. X                        winicon->core.client->screen);
  1260. X    scr_x = abs((winicon->core.x + ICON_HORZBORDER) % dw);
  1261. X    scr_y = abs((winicon->core.y + ICON_VERTBORDER) % dh);
  1262. X    slot = incrPositionedSlots(iconGrid, scr_x, scr_y,
  1263. X        winicon->core.width, winicon->core.height, snaptogrid);
  1264. X    if (winicon->core.x > 0)
  1265. X        slot->off_x = ((winicon->core.x + ICON_HORZBORDER) / dw) * dw;
  1266. X    else slot->off_x = ((winicon->core.x + ICON_HORZBORDER - dw) / dw) * dw;
  1267. X    if (winicon->core.y > 0)
  1268. X        slot->off_y = ((winicon->core.y + ICON_VERTBORDER) / dh) * dh;
  1269. X    else slot->off_y = ((winicon->core.y + ICON_VERTBORDER - dh) / dh) * dh;
  1270. X    winicon->iconslot = slot;
  1271. X    if (snaptogrid)
  1272. X        setIconPos(winicon, slot);
  1273. X    else
  1274. X        (WinFunc(winicon,core.newposfunc))(winicon,winicon->core.x,winicon->core.y);
  1275. X    }
  1276. X    else
  1277. X    {
  1278. X        nhoriz = ROUNDUP(winicon->core.width, ICON_GRID_WIDTH);
  1279. X        nvert = ROUNDUP(winicon->core.height, ICON_GRID_HEIGHT);
  1280. X    setMajorMinor(iconGrid, nvert, nhoriz, &nmajor, &nminor);
  1281. X    slot = incrDynamicSlots(iconGrid, nmajor, nminor);
  1282. X    slot->off_x = winicon->core.x + ICON_HORZBORDER;
  1283. X    slot->off_y = winicon->core.y + ICON_VERTBORDER;
  1284. X    winicon->iconslot = slot;
  1285. X    setIconPos(winicon,slot);
  1286. X    }
  1287. X
  1288. X    return slot;
  1289. X}
  1290. X
  1291. X/* SlotFree -- An icon is going away, so its references to slots should also go
  1292. X * away.  Returns True iff the free was successful.
  1293. X * Note that if this code is changed, the similar code in SlotSetLocations
  1294. X * may need to be changed also.
  1295. X */
  1296. XBool 
  1297. XSlotFree(winicon)
  1298. XWinIconFrame *winicon;
  1299. X{
  1300. X    List **l;
  1301. X    IconGrid    *iconGrid = winicon->core.client->scrInfo->iconGrid;
  1302. X    WinIconFrame    *win;
  1303. X
  1304. X    if (winicon->iconslot == NULL)
  1305. X    {
  1306. X        return;
  1307. X    }
  1308. X
  1309. X    incrRegion(iconGrid,winicon->iconslot,-1);
  1310. X    MemFree(winicon->iconslot);
  1311. X    winicon->iconslot = NULL;
  1312. X
  1313. X    l = &iconGrid->iconList;
  1314. X    for (win = ListEnum(l); win != NULL; win = ListEnum(l))
  1315. X    {
  1316. X        if (win == winicon)
  1317. X        {
  1318. X        ListDestroyCell(l);
  1319. X        break;
  1320. X        }
  1321. X    }
  1322. X}
  1323. X
  1324. X/* sets the order in which slots are allocated for icons which are
  1325. X * not explicitly positioned.  The order is gotten from the global
  1326. X * resource vector.
  1327. X * For example, the AlongBottom order is expressed as
  1328. X * major BottomToTop, minor LeftToRight.  The major and minor orders
  1329. X * cannot be both vertical or horizontal.  Any icons which were 
  1330. X * automatically positioned are repositioned to equivalent positions
  1331. X * in the new order.
  1332. X */
  1333. X/*ARGSUSED*/
  1334. XBool 
  1335. XSlotSetLocations(dpy,iconGrid)
  1336. XDisplay *dpy;
  1337. XIconGrid *iconGrid;
  1338. X{
  1339. X    List *lauto, *lpos;
  1340. X    List **l;
  1341. X    WinIconFrame *win;
  1342. X    int ima, imi;
  1343. X
  1344. X    /* set up the new order of things */
  1345. X        switch (GRV.IconPlacement)
  1346. X        {
  1347. X        case AlongTop:
  1348. X        iconGrid->SOmajor = SOTopToBottom;
  1349. X        iconGrid->SOminor = SOLeftToRight;
  1350. X                break;
  1351. X
  1352. X        case AlongTopRL:
  1353. X        iconGrid->SOmajor = SOTopToBottom;
  1354. X        iconGrid->SOminor = SORightToLeft;
  1355. X                break;
  1356. X
  1357. X        case AlongBottom:
  1358. X        iconGrid->SOmajor = SOBottomToTop;
  1359. X        iconGrid->SOminor = SOLeftToRight;
  1360. X                break;
  1361. X
  1362. X        case AlongBottomRL:
  1363. X        iconGrid->SOmajor = SOBottomToTop;
  1364. X        iconGrid->SOminor = SORightToLeft;
  1365. X                break;
  1366. X
  1367. X        case AlongLeft:
  1368. X        iconGrid->SOmajor = SOLeftToRight;
  1369. X        iconGrid->SOminor = SOTopToBottom;
  1370. X                break;
  1371. X
  1372. X        case AlongLeftBT:
  1373. X        iconGrid->SOmajor = SOLeftToRight;
  1374. X        iconGrid->SOminor = SOBottomToTop;
  1375. X                break;
  1376. X
  1377. X        case AlongRight:
  1378. X        iconGrid->SOmajor = SORightToLeft;
  1379. X        iconGrid->SOminor = SOTopToBottom;
  1380. X                break;
  1381. X
  1382. X        case AlongRightBT:
  1383. X        iconGrid->SOmajor = SORightToLeft;
  1384. X        iconGrid->SOminor = SOBottomToTop;
  1385. X                break;
  1386. X        }
  1387. X
  1388. X    setMajorMinor(iconGrid,iconGrid->slotsvert,iconGrid->slotshoriz,
  1389. X            &(iconGrid->maslots),&(iconGrid->mislots));
  1390. X
  1391. X    if (iconGrid->iconList == NULL_LIST)
  1392. X    {
  1393. X        for (ima = 0; ima<iconGrid->maslots; ima++)
  1394. X            for (imi = 0; imi<iconGrid->mislots; imi++)
  1395. X            OCCUPANCY(iconGrid,ima,imi)=0;
  1396. X        return;
  1397. X    }
  1398. X
  1399. X    /* partition existing icons */
  1400. X    lauto = NULL_LIST;
  1401. X    lpos = NULL_LIST;
  1402. X    l = &iconGrid->iconList;
  1403. X    for (win = ListEnum(l); win != NULL; win = ListEnum(l))
  1404. X    {
  1405. X        if (!win->iconslot->positioned)
  1406. X        {
  1407. X        lauto = ListCons(win,lauto);
  1408. X        }
  1409. X        else
  1410. X        {
  1411. X        lpos = ListCons(win,lpos);
  1412. X        }
  1413. X        /* this is the basics of a SlotFree */
  1414. X        MemFree(win->iconslot);
  1415. X        win->iconslot = NULL;
  1416. X    }
  1417. X    ListDestroy(iconGrid->iconList);
  1418. X    iconGrid->iconList = NULL_LIST;
  1419. X
  1420. X    for (ima = 0; ima<iconGrid->maslots; ima++)
  1421. X        for (imi = 0; imi<iconGrid->mislots; imi++)
  1422. X        OCCUPANCY(iconGrid,ima,imi)=0;
  1423. X
  1424. X    /* place positioned icons */
  1425. X    l = &lpos;
  1426. X    for (win = ListEnum(l); win != NULL; win = ListEnum(l))
  1427. X    {
  1428. X        SlotAlloc(win,True,False);
  1429. X        (WinFunc(win,core.setconfigfunc))(win->core.client->dpy,win);
  1430. X    }
  1431. X    ListDestroy(lpos);
  1432. X
  1433. X    /* place auto-positioned icons */
  1434. X    l = &lauto;
  1435. X    for (win = ListEnum(l); win != NULL; win = ListEnum(l))
  1436. X    {
  1437. X        SlotAlloc(win,False,False);
  1438. X        (WinFunc(win,core.setconfigfunc))(win->core.client->dpy,win);
  1439. X    }
  1440. X    ListDestroy(lauto);
  1441. X}
  1442. END_OF_FILE
  1443. if test 16468 -ne `wc -c <'slots.c'`; then
  1444.     echo shar: \"'slots.c'\" unpacked with wrong size!
  1445. fi
  1446. # end of 'slots.c'
  1447. fi
  1448. if test -f 'wingframe.c' -a "${1}" != "-c" ; then 
  1449.   echo shar: Will not clobber existing file \"'wingframe.c'\"
  1450. else
  1451. echo shar: Extracting \"'wingframe.c'\" \(15552 characters\)
  1452. sed "s/^X//" >'wingframe.c' <<'END_OF_FILE'
  1453. X/*
  1454. X *      (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
  1455. X *      pending in the U.S. and foreign countries. See LEGAL_NOTICE
  1456. X *      file for terms of the license.
  1457. X */
  1458. X
  1459. X/*
  1460. X * wingframe.c -- generic frame window routines
  1461. X */
  1462. X
  1463. X#ident    "@(#)wingframe.c    1.1 olvwm version 1/3/92"
  1464. X
  1465. X/*
  1466. X * Based on
  1467. X#ident    "@(#)wingframe.c    26.27    91/09/14 SMI"
  1468. X *
  1469. X */
  1470. X
  1471. X#include <errno.h>
  1472. X#include <stdio.h>
  1473. X#include <string.h>
  1474. X#include <X11/Xos.h>
  1475. X#include <X11/Xlib.h>
  1476. X#include <X11/Xutil.h>
  1477. X#include <X11/Xatom.h>
  1478. X#include <X11/keysym.h>
  1479. X#include <olgx/olgx.h>
  1480. X
  1481. X#include "i18n.h"
  1482. X#include "ollocale.h"
  1483. X#include "mem.h"
  1484. X#include "olwm.h"
  1485. X#include "win.h"
  1486. X#include "globals.h"
  1487. X#include "events.h"
  1488. X#include "virtual.h"
  1489. X
  1490. X/***************************************************************************
  1491. X* private data
  1492. X***************************************************************************/
  1493. X
  1494. X/*
  1495. X * REMIND
  1496. X * The hadSelect variable is necessary because we sometimes receive
  1497. X * MotionNotify events with all buttons up, even though we ask for only
  1498. X * ButtonMotionMask.  We set hadSelect only on receipt of an event that is 
  1499. X * bound to the Select action, and we ignore motion events that occur if
  1500. X * hadSelect isn't set.
  1501. X */
  1502. Xstatic  Bool            hadSelect = False;
  1503. Xstatic  Time            timeOfLastButPress = 0;
  1504. Xstatic  int             buttonPressX;
  1505. Xstatic  int             buttonPressY;
  1506. Xstatic  XButtonEvent    lastSelectRelease;
  1507. Xstatic  XButtonEvent    lastSelectPress;
  1508. Xstatic  Time            lastDoubleClickTime;
  1509. Xstatic    SemanticAction    currentAction = ACTION_NONE;
  1510. X
  1511. X/***************************************************************************
  1512. X* forward-declared functions
  1513. X***************************************************************************/
  1514. X
  1515. Xextern void ClientSetCurrent();
  1516. X
  1517. X/***************************************************************************
  1518. X* static functions
  1519. X***************************************************************************/
  1520. X
  1521. Xvoid
  1522. XautoRaise(frame)
  1523. X    WinGenericFrame *frame;
  1524. X{
  1525. X    Bool samescreen;
  1526. X    Window root, child;
  1527. X    int rootx, rooty, winx, winy;
  1528. X    unsigned int state;
  1529. X    Client *cli = frame->core.client;
  1530. X    if (cli->isFocus) {
  1531. X    if (GRV.FocusFollowsMouse) {
  1532. X        samescreen = XQueryPointer(cli->dpy, WinRootID(frame),
  1533. X            &root, &child, &rootx, &rooty, &winx, &winy, &state);
  1534. X        if (samescreen && child == frame->core.self)
  1535. X        ClientFront(cli);
  1536. X    } else {
  1537. X        ClientFront(cli);
  1538. X    }
  1539. X    }
  1540. X}
  1541. X
  1542. X/***************************************************************************
  1543. X* global functions
  1544. X***************************************************************************/
  1545. X
  1546. X/*
  1547. X * GFrameSelect -- handle selection state change
  1548. X */
  1549. X/*ARGSUSED*/    /* dpy arg will be used when multiple Displays supported */
  1550. Xint
  1551. XGFrameSelect(dpy, winInfo, selected)
  1552. XDisplay    *dpy;
  1553. XWinGeneric *winInfo;
  1554. XBool selected;
  1555. X{
  1556. X    (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
  1557. X}
  1558. X
  1559. X/*
  1560. X * GFrameFocus -- handle focus changes
  1561. X *
  1562. X * If we're in auto-raise mode, raise the window.  But if we're in focus-
  1563. X * follows-mouse, we query the pointer to make sure we're still in the same 
  1564. X * window before we do this raise.  This is to avoid restacking loops.
  1565. X *
  1566. X * If colormap installation is tracking the input focus, get the first entry 
  1567. X * in the client's WM_COLORMAP_WINDOWS list and install its colormap; 
  1568. X * otherwise, install the pane's colormap.
  1569. X */
  1570. X/*ARGSUSED*/
  1571. Xint
  1572. XGFrameFocus(dpy, winInfo, focus)
  1573. XDisplay        *dpy;
  1574. XWinGenericFrame *winInfo;
  1575. XBool        focus;
  1576. X{
  1577. X    WinGeneric *cmwi;
  1578. X
  1579. X    if (focus) {
  1580. X        ClientSetCurrent(winInfo->core.client);
  1581. X        ClientSetWindowState(winInfo->core.client);
  1582. X
  1583. X        if (GRV.ColorTracksInputFocus) {
  1584. X        if (winInfo->core.client->colormapWins)
  1585. X            cmwi = winInfo->core.client->colormapWins->value;
  1586. X        else
  1587. X            cmwi = (WinGeneric *) winInfo->fcore.panewin;
  1588. X        LockColormap(dpy, winInfo->core.client, cmwi);
  1589. X        }
  1590. X
  1591. X        if (GRV.AutoRaise) {
  1592. X        if (GRV.AutoRaiseDelay > 0) {
  1593. X            TimeoutCancel();
  1594. X            TimeoutRequest(GRV.AutoRaiseDelay, autoRaise, winInfo);
  1595. X        } else {
  1596. X            autoRaise(winInfo);
  1597. X        }
  1598. X        }
  1599. X    }
  1600. X}
  1601. X
  1602. X/*
  1603. X * GFrameSetConfigFunc -- change configuration of frame window
  1604. X * REMIND: ensure that transient windows are treated properly.
  1605. X */
  1606. Xint
  1607. XGFrameSetConfigFunc(dpy, win)
  1608. XDisplay    *dpy;
  1609. XWinGenericFrame *win;
  1610. X{
  1611. X        XWindowChanges xwc;
  1612. X    int    dw, dh;
  1613. X    Client    *cli = win->core.client;
  1614. X
  1615. X        if (win->core.dirtyconfig)
  1616. X        {
  1617. X        if (cli->sticky) {
  1618. X            dw = DisplayWidth(win->core.client->dpy,
  1619. X                      win->core.client->screen);
  1620. X            dh = DisplayHeight(win->core.client->dpy,
  1621. X                       win->core.client->screen);
  1622. X
  1623. X            if (win->core.x + (int) win->core.width < 0) {
  1624. X            win->core.x = (dw + (win->core.x % dw)) % dw; 
  1625. X            win->core.dirtyconfig |= CWX;
  1626. X            }
  1627. X            else if (win->core.x >= dw) {
  1628. X            win->core.x = win->core.x % dw; 
  1629. X            win->core.dirtyconfig |= CWX;
  1630. X            }
  1631. X            if (win->core.y + (int) win->core.height < 0) {
  1632. X            win->core.y = (dh + (win->core.y % dh)) % dh; 
  1633. X            win->core.dirtyconfig |= CWY;
  1634. X            }
  1635. X            else if (win->core.y >= dh) {
  1636. X            win->core.y = win->core.y % dh; 
  1637. X            win->core.dirtyconfig |= CWY;
  1638. X            }
  1639. X        }
  1640. X                xwc.x = win->core.x;
  1641. X                xwc.y = win->core.y;
  1642. X                xwc.width = win->core.width;
  1643. X                xwc.height = win->core.height;
  1644. X        xwc.sibling = win->core.stack_sib;
  1645. X        xwc.stack_mode = win->core.stack_mode;
  1646. X        if ((win->core.dirtyconfig & CWSibling) && 
  1647. X            !(win->core.dirtyconfig &CWStackMode))
  1648. X            win->core.dirtyconfig &= ~CWSibling;
  1649. X
  1650. X                ConfigureWindow(dpy,win,win->core.dirtyconfig,&xwc);
  1651. X        win->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode);
  1652. X        }
  1653. X}
  1654. X
  1655. X/* GFrameSetStack -- set the frame's stacking position.   Does not initiate
  1656. X *    a configuration change.
  1657. X */
  1658. Xvoid
  1659. XGFrameSetStack(win, mask, mode, sib)
  1660. XWinGenericFrame *win;
  1661. Xint mask;
  1662. Xint mode;
  1663. XWindow sib;
  1664. X{
  1665. X    WinGeneric *wsib;
  1666. X
  1667. X    if ((mask & CWSibling) && (mask & CWStackMode))
  1668. X    {
  1669. X        wsib = WIGetInfo(sib);
  1670. X        if (wsib != NULL)
  1671. X        {
  1672. X            win->core.stack_sib = wsib->core.client->framewin->core.self;
  1673. X            win->core.dirtyconfig |= CWSibling;
  1674. X        }
  1675. X    }
  1676. X    if (mask & CWStackMode)
  1677. X    {
  1678. X        win->core.stack_mode = mode;
  1679. X        win->core.dirtyconfig |= CWStackMode;
  1680. X    }
  1681. X}
  1682. X
  1683. X/* GFrameSetConfig - set the frame's size and position -- generally used in
  1684. X * resizing or moving the window.  We position the frame and resize the pane.
  1685. X * If the pane has refused resizing we skip that part.
  1686. X */
  1687. Xvoid
  1688. XGFrameSetConfig(win,x,y,w,h)
  1689. XWinGenericFrame *win;
  1690. Xint x,y,w,h;
  1691. X{
  1692. X        WinPane *pane = (WinPane *)win->fcore.panewin;
  1693. X
  1694. X        (WinFunc(win,core.newposfunc))(win,x,y);
  1695. X    if (pane != NULL)
  1696. X    {
  1697. X            if (WinFunc(pane,pcore.setsizefunc) != NULL)
  1698. X                (WinFunc(pane,pcore.setsizefunc))(pane,
  1699. X                    w-(WinFunc(win,fcore.widthleft))(win)-(WinFunc(win,fcore.widthright))(win),
  1700. X                    h-(WinFunc(win,fcore.heighttop))(win)-(WinFunc(win,fcore.heightbottom))(win));
  1701. X            WinCallConfig(win->core.client->dpy, pane, NULL);
  1702. X    }
  1703. X    else
  1704. X    {
  1705. X            WinCallConfig(win->core.client->dpy, win, NULL);
  1706. X    }
  1707. X}
  1708. X
  1709. X
  1710. X/***************************************************************************
  1711. X* global event functions
  1712. X***************************************************************************/
  1713. X
  1714. X/*
  1715. X * GFrameEventButtonRelease -- a button has been released
  1716. X *
  1717. X */
  1718. Xint
  1719. XGFrameEventButtonRelease(dpy, event, frameInfo)
  1720. XDisplay *dpy;
  1721. XXEvent  *event;
  1722. XWinGenericFrame *frameInfo;
  1723. X{
  1724. X        WinGenericPane    *winPane = (WinGenericPane*)frameInfo->fcore.panewin;
  1725. X        Client *cli = frameInfo->core.client;
  1726. X
  1727. X    if (!AllButtonsUp(event))
  1728. X        return;
  1729. X
  1730. X#define bevent  (event->xbutton)
  1731. X
  1732. X        switch (currentAction)
  1733. X        {
  1734. X        case ACTION_SELECT:
  1735. X        if (GRV.SelectWindows) {
  1736. X            ClearSelections(dpy);
  1737. X            AddSelection(cli, event->xbutton.time);
  1738. X        }
  1739. X
  1740. X        ClientSetCurrent(cli);
  1741. X        ClientFront(cli);
  1742. X
  1743. X                hadSelect = False;
  1744. X
  1745. X                if (WinFunc(frameInfo,fcore.selectClick) != NULL)
  1746. X                {
  1747. X            (WinFunc(frameInfo,fcore.selectClick))(dpy,event,frameInfo);
  1748. X                }
  1749. X
  1750. X                /* If the click happened in the decoration windows,
  1751. X                 * (i.e. not in the pane), check for a double click.
  1752. X                 * Check last click time to see if we are in double
  1753. X                 * click land.  Also check that the user hasn't just
  1754. X                 * hit the button 3 times very rapidly.  This would
  1755. X                 * cause a cycle of the window changing size.
  1756. X         * REMIND this is more nasty than it should be because
  1757. X         * not all frames are yet required to have panes.
  1758. X         * Once all panes have frames the subwindow test gets
  1759. X         * easier.
  1760. X                 */
  1761. X                if ((WinFunc(frameInfo,fcore.selectDoubleClick) != NULL) &&
  1762. X            ((winPane == NULL) || (bevent.subwindow != winPane->core.self)) &&
  1763. X                   ((bevent.time-lastSelectRelease.time) <= GRV.DoubleClickTime) &&
  1764. X                   ((bevent.time-lastDoubleClickTime) > GRV.DoubleClickTime))
  1765. X                {
  1766. X                    /* we have a double click */
  1767. X            if (WinFunc(frameInfo,fcore.selectDoubleClick) != NULL)
  1768. X            {
  1769. X            (WinFunc(frameInfo,fcore.selectDoubleClick))(dpy,event,frameInfo);
  1770. X            }
  1771. X
  1772. X                    lastDoubleClickTime = bevent.time;
  1773. X                 }
  1774. X                lastSelectRelease = event->xbutton;
  1775. X        currentAction = ACTION_NONE;
  1776. X                break;  /* out of ACTION_SELECT case */
  1777. X    case ACTION_ADJUST:
  1778. X                if (WinFunc(frameInfo,fcore.adjustClick) != NULL)
  1779. X                {
  1780. X            (WinFunc(frameInfo,fcore.adjustClick))(dpy,event,frameInfo);
  1781. X                }
  1782. X        currentAction = ACTION_NONE;
  1783. X        break;
  1784. X
  1785. X        }
  1786. X}
  1787. X
  1788. X/*
  1789. X * GFrameEventMotionNotify -- a button is down and the pointer is moving
  1790. X */
  1791. Xint
  1792. XGFrameEventMotionNotify(dpy, event, frameInfo)
  1793. XDisplay *dpy;
  1794. XXEvent  *event;
  1795. XWinGenericFrame *frameInfo;
  1796. X{
  1797. X        /* We get this only after a Select press */
  1798. X        if (hadSelect == False) /* watch for erroneous motions */
  1799. X        {
  1800. X                return;
  1801. X        }
  1802. X
  1803. X    if (!event->xmotion.same_screen)
  1804. X        return;
  1805. X
  1806. X        /* See if we have moved more than the threshold amount. */
  1807. X        if ((ABS(event->xmotion.x - buttonPressX) < GRV.MoveThreshold) &&
  1808. X            (ABS(event->xmotion.y - buttonPressY) < GRV.MoveThreshold))
  1809. X                return;
  1810. X
  1811. X    (WinFunc(frameInfo,fcore.selectDrag))(dpy, event, frameInfo, &lastSelectPress);
  1812. X
  1813. X        /*
  1814. X         * UserMoveWindows() will grab the pointer and handle events
  1815. X         * using an interposer, so we can clear the hadSelect flag.
  1816. X         */
  1817. X        hadSelect = False;
  1818. X}
  1819. X
  1820. X/*
  1821. X * GFrameEventButtonPress -- a mouse button has gone down.
  1822. X */
  1823. Xint
  1824. XGFrameEventButtonPress(dpy, event, frameInfo)
  1825. XDisplay *dpy;
  1826. XXEvent  *event;
  1827. XWinGenericFrame *frameInfo;
  1828. X{
  1829. X        WinPane         *winPane = (WinPane*)frameInfo->fcore.panewin;
  1830. X        Window          panewindow = winPane->core.self;
  1831. X    SemanticAction    a;
  1832. X    unsigned int    ignoremask;
  1833. X
  1834. X    ignoremask = ModMaskMap[MOD_CONSTRAIN] |
  1835. X             ModMaskMap[MOD_INVERT] |
  1836. X             ModMaskMap[MOD_REDUCE];
  1837. X
  1838. X    a = ResolveMouseBinding(dpy, event, ignoremask);
  1839. X
  1840. X    switch (a) {
  1841. X        case ACTION_SELECT:
  1842. X        currentAction = a;
  1843. X                /*
  1844. X         * Save the location where the button went down so we
  1845. X                 * can see if the user moves the mouse more than
  1846. X                 * GRV.MoveThreshold, and wants to move the window.
  1847. X                 */
  1848. X                buttonPressX = event->xbutton.x;
  1849. X                buttonPressY = event->xbutton.y;
  1850. X
  1851. X                if (!GRV.FocusFollowsMouse && 
  1852. X            (WinFunc(frameInfo,fcore.selectPress) != NULL))
  1853. X                {
  1854. X                /* It is possible for us to replay the event and
  1855. X                 * have the window, (decoration window, e.g. the
  1856. X                 * resize corner, the titlebar), in which the
  1857. X                 * button press happened to ignore it.
  1858. X                 * In this case we would get the event
  1859. X                 * again.  For example, the user could button press
  1860. X                 * in the title bar, (which doesn't select this event),
  1861. X                 * and have this EventFrame routine get the same event
  1862. X                 * twice.  So, we check that the time stamp of this
  1863. X                 * button press is different than the last.
  1864. X                 */
  1865. X                        if (event->xbutton.time == timeOfLastButPress)
  1866. X                                /* We already dealt with this event. */
  1867. X                                break;
  1868. X                        timeOfLastButPress = event->xbutton.time;
  1869. X                        if (event->xbutton.subwindow == panewindow)
  1870. X                        {
  1871. X                (WinFunc(frameInfo,fcore.selectPress))(dpy,event,frameInfo);
  1872. X                        }
  1873. X
  1874. X                        /* Let the button press through
  1875. X                         * if we had grabbed it.
  1876. X                         */
  1877. X                        XAllowEvents(dpy, ReplayPointer, CurrentTime);
  1878. X                }  /* End if not GRV.FocusFollowsMouse */
  1879. X
  1880. X                lastSelectPress = event->xbutton;
  1881. X                hadSelect = True;
  1882. X                break;  /* Break case ACTION_SELECT */
  1883. X
  1884. X        case ACTION_ADJUST:
  1885. X        currentAction = a;
  1886. X        if (!GRV.FocusFollowsMouse) {
  1887. X        if (event->xbutton.time == timeOfLastButPress)
  1888. X            break;
  1889. X        timeOfLastButPress = event->xbutton.time;
  1890. X        if (event->xbutton.subwindow == panewindow
  1891. X            && WinFunc(frameInfo,fcore.adjustPress) != NULL) {
  1892. X            (WinFunc(frameInfo,fcore.adjustPress))
  1893. X            (dpy,event,frameInfo);
  1894. X        }
  1895. X        XAllowEvents(dpy, ReplayPointer, CurrentTime);
  1896. X        }
  1897. X        break;
  1898. X        case ACTION_MENU:
  1899. X        currentAction = a;
  1900. X        if (WinFunc(frameInfo,fcore.menuPress) != NULL)
  1901. X        (WinFunc(frameInfo,fcore.menuPress))(dpy, event, frameInfo);
  1902. X            break;
  1903. X
  1904. X        }  /*  End switch on button pressed */
  1905. X}
  1906. X
  1907. X
  1908. X/*
  1909. X * GFrameEventEnterNotify
  1910. X *
  1911. X * If we entered from outside and we're in follows-mouse mode, set the focus.
  1912. X * If we enter the frame from the pane or directly from elsewhere (i.e.
  1913. X * nonlinearly) install the appropriate colormap.
  1914. X */
  1915. Xint
  1916. XGFrameEventEnterNotify(dpy, event, frameInfo)
  1917. XDisplay    *dpy;
  1918. XXEvent    *event;
  1919. XWinGenericFrame *frameInfo;
  1920. X{
  1921. X    Client *cli = frameInfo->core.client;
  1922. X
  1923. X    if (GRV.FocusFollowsMouse && event->xcrossing.detail != NotifyInferior)
  1924. X    ClientSetFocus(cli,True,event->xcrossing.time);
  1925. X
  1926. X    switch (event->xcrossing.detail) {
  1927. X    case NotifyInferior:
  1928. X    case NotifyNonlinear:
  1929. X    ColorWindowCrossing(dpy, event, cli->scrInfo->rootwin);
  1930. X    break;
  1931. X    }
  1932. X}
  1933. X
  1934. X
  1935. X/*
  1936. X * GFrameEventFocus
  1937. X *
  1938. X * If the focus changed normally (i.e. not as the result of a keyboard grab or 
  1939. X * ungrab), call the focus functions.
  1940. X */
  1941. Xint
  1942. XGFrameEventFocus(dpy, event, frameInfo)
  1943. X    Display *dpy;
  1944. X    XEvent *event;
  1945. X    WinGenericFrame *frameInfo;
  1946. X{
  1947. X    switch (event->xfocus.mode) {
  1948. X    case NotifyNormal:
  1949. X    case NotifyWhileGrabbed:
  1950. X    if (event->xfocus.detail <= NotifyNonlinearVirtual) {
  1951. X        if (event->type == FocusIn)
  1952. X        WinCallFocus(frameInfo, True);
  1953. X        else {
  1954. X            Client    *cli;
  1955. X
  1956. X            cli = frameInfo->core.client;
  1957. X            /*
  1958. X             * When we lose focus,
  1959. X             * we have to WinCallFocus on both the Icon and the regular
  1960. X             * Frame:  if we double click on an icon, it gets input
  1961. X             * focus and when it loses it, it must redraw the frame.
  1962. X             * Otherwise, the newly opened frame gets drawn as if it
  1963. X             * had input focus
  1964. X         *
  1965. X         * We can't do this when getting focus, since it confuses
  1966. X         * autoraise.  There's got to be a better way . . .
  1967. X             */
  1968. X            if (cli->framewin)
  1969. X                WinCallFocus(cli->framewin, False);
  1970. X            if (cli->iconwin)
  1971. X                WinCallFocus(cli->iconwin, False);
  1972. X        }
  1973. X    }
  1974. X    break;
  1975. X    }
  1976. X}
  1977. END_OF_FILE
  1978. if test 15552 -ne `wc -c <'wingframe.c'`; then
  1979.     echo shar: \"'wingframe.c'\" unpacked with wrong size!
  1980. fi
  1981. # end of 'wingframe.c'
  1982. fi
  1983. echo shar: End of archive 16 \(of 21\).
  1984. cp /dev/null ark16isdone
  1985. MISSING=""
  1986. 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
  1987.     if test ! -f ark${I}isdone ; then
  1988.     MISSING="${MISSING} ${I}"
  1989.     fi
  1990. done
  1991. if test "${MISSING}" = "" ; then
  1992.     echo You have unpacked all 21 archives.
  1993.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1994. else
  1995.     echo You still need to unpack the following archives:
  1996.     echo "        " ${MISSING}
  1997. fi
  1998. ##  End of shell archive.
  1999. exit 0
  2000. --
  2001. Molecular Simulations, Inc.             mail: dcmartin@postgres.berkeley.edu
  2002. 796 N. Pastoria Avenue                  uucp: uwvax!ucbvax!dcmartin
  2003. Sunnyvale, California 94086             at&t: 408/522-9236
  2004.