home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gwm18a.zip / wl_event.c < prev    next >
C/C++ Source or Header  |  1995-07-03  |  38KB  |  1,512 lines

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /***********************\
  5. *                 *
  6. *  WOOL_OBJECT: Event  *
  7. *  BODY                *
  8. *                 *
  9. \***********************/
  10.  
  11. #include "EXTERN.h"
  12. #include <stdio.h>
  13. #include "wool.h"
  14. #include "wl_atom.h"
  15. #include "wl_pointer.h"
  16. #include "wl_string.h"
  17. #include "wl_number.h"
  18. #include "wl_list.h"
  19. #include "wl_func.h"
  20. #include "gwm.h"
  21. #include <X11/Xatom.h>
  22. #include <X11/Xutil.h>
  23. #include "INTERN.h"
  24. #include "wl_event.h"
  25. #include "EXTERN.h"
  26. #include "wl_cursor.h"
  27. #include "wl_fsm.h"
  28.  
  29. extern WOB_METHOD       MenuClass[], PlugClass[];
  30.  
  31. /* table of events getting redirected to grabbing wob during a GWM grab
  32.  */
  33.  
  34. Card32 EventProperties[] = {
  35. /* zero */             0,
  36. /* one */              0,
  37. /* KeyPress */         EPGrabRedirected|EPKeyOrButton|EPXY|EPXYRoot|EPTime,
  38. /* KeyRelease */       EPGrabRedirected|EPKeyOrButton|EPXY|EPXYRoot|EPTime,
  39. /* ButtonPress */      EPGrabRedirected|EPKeyOrButton|EPXY|EPXYRoot|EPTime,
  40. /* ButtonRelease */    EPGrabRedirected|EPKeyOrButton|EPXY|EPXYRoot|EPTime,
  41. /* MotionNotify */     EPGrabRedirected|EPKeyOrButton|EPXY|EPXYRoot|EPTime,
  42. /* EnterNotify */      EPRedirectable|EPCrossing|EPXY|EPXYRoot|EPTime,
  43. /* LeaveNotify */      EPRedirectable|EPCrossing|EPXY|EPXYRoot|EPTime,
  44. /* FocusIn */          EPRedirectable|EPFocus,
  45. /* FocusOut */         EPRedirectable|EPFocus,
  46. /* KeymapNotify */     0,
  47. /* Expose */           0,
  48. /* GraphicsExpose */   0,
  49. /* NoExpose */         0,
  50. /* VisibilityNotify */ 0,
  51. /* CreateNotify */     0,
  52. /* DestroyNotify */    0,
  53. /* UnmapNotify */      0,
  54. /* MapNotify */        0,
  55. /* MapRequest */       0,
  56. /* ReparentNotify */   0,
  57. /* ConfigureNotify */  0,
  58. /* ConfigureRequest */ 0,
  59. /* GravityNotify */    0,
  60. /* ResizeRequest */    0,
  61. /* CirculateNotify */  0,
  62. /* CirculateRequest */ 0,
  63. /* PropertyNotify */   EPTime,
  64. /* SelectionClear */   EPTime,
  65. /* SelectionRequest */ EPTime,
  66. /* SelectionNotify */  EPTime,
  67. /* ColormapNotify */   0,
  68. /* ClientMessage */    0,
  69. /* MappingNotify */    0,
  70. /* LASTEvent */        0,
  71. /* GWMUserEvent */     0
  72. };
  73.  
  74. /* offset of the Time field of events possessing it */
  75. /* IF THIS GIVES COMPILES ERROR, USE THE FLAG -DNO_STRUCTURE_OFFSETS */
  76. XEvent dummy_evt_ptr;
  77. #define XEventFieldOffset(evt_type, field) \
  78.     ((char *)(&(dummy_evt_ptr.evt_type.field))) - \
  79.     ((char *)(&(dummy_evt_ptr.type)))
  80.  
  81. int EventTimeFieldOffset
  82. #ifndef NO_STRUCTURE_OFFSETS
  83. [] = {
  84. /* zero */             0,
  85. /* one */              0,
  86. /* KeyPress */         XEventFieldOffset(xkey, time),
  87. /* KeyRelease */       XEventFieldOffset(xkey, time),
  88. /* ButtonPress */      XEventFieldOffset(xbutton, time),
  89. /* ButtonRelease */    XEventFieldOffset(xbutton, time),
  90. /* MotionNotify */     XEventFieldOffset(xmotion, time),
  91. /* EnterNotify */      XEventFieldOffset(xcrossing, time),
  92. /* LeaveNotify */      XEventFieldOffset(xcrossing, time),
  93. /* FocusIn */          0,
  94. /* FocusOut */         0,
  95. /* KeymapNotify */     0,
  96. /* Expose */           0,
  97. /* GraphicsExpose */   0,
  98. /* NoExpose */         0,
  99. /* VisibilityNotify */ 0,
  100. /* CreateNotify */     0,
  101. /* DestroyNotify */    0,
  102. /* UnmapNotify */      0,
  103. /* MapNotify */        0,
  104. /* MapRequest */       0,
  105. /* ReparentNotify */   0,
  106. /* ConfigureNotify */  0,
  107. /* ConfigureRequest */ 0,
  108. /* GravityNotify */    0,
  109. /* ResizeRequest */    0,
  110. /* CirculateNotify */  0,
  111. /* CirculateRequest */ 0,
  112. /* PropertyNotify */   XEventFieldOffset(xproperty, time),
  113. /* SelectionClear */   XEventFieldOffset(xselectionclear, time),
  114. /* SelectionRequest */ XEventFieldOffset(xselectionrequest, time),
  115. /* SelectionNotify */  XEventFieldOffset(xselection, time),
  116. /* ColormapNotify */   0,
  117. /* ClientMessage */    0,
  118. /* MappingNotify */    0,
  119. /* LASTEvent */        0,
  120. /* GWMUserEvent */     0
  121. }
  122. #else
  123. [GWMUserEvent]
  124. #endif /* NO_STRUCTURE_OFFSETS */
  125. ;
  126.  
  127. /* to filter button releases events from the fact that they get the same button
  128.  * pressed as a modifier...
  129.  */
  130. unsigned int ButtonMasks[] = {
  131.     ~0,
  132.     ~Button1Mask,
  133.     ~Button2Mask,
  134.     ~Button3Mask,
  135.     ~Button4Mask,
  136.     ~Button5Mask
  137.     };
  138.  
  139. /*
  140.  * to built a Event from C
  141.  */
  142.  
  143. WOOL_Event
  144. wool_event_make(name, x_type, match, release, mask, state, detail)
  145. char *        name;
  146. int        x_type;
  147. int        (*match)();
  148. int        (*release)();
  149. unsigned int    mask, state, detail;
  150. {
  151.     WOOL_Event     object = (WOOL_Event) WLEvent_make(state, detail);
  152.  
  153.     object -> x_type = x_type;
  154.     object -> match = match;
  155.     object -> release = release;
  156.     object -> mask = mask;
  157.     return (WOOL_Event) WLAtom_set(wool_atom(name), object);
  158. }
  159.  
  160. WOOL_Event
  161. WLEvent_make(state, detail)
  162. unsigned int    state, detail;
  163. {
  164.     WOOL_Event     object = (WOOL_Event) Malloc(
  165.                            sizeof(struct _WOOL_Event));
  166.  
  167.     zrt_put(object);
  168.     object -> type = WLEvent;
  169.     object -> state = state;
  170.     object -> detail = detail;
  171.     object -> user_mask = 0;
  172.     object -> flags = 0;
  173.     return object;
  174. }
  175.  
  176. WOOL_OBJECT
  177. WLEvent_print(obj)
  178. WOOL_Event obj;
  179. {
  180.     wool_printf("{EVENT %s", eventtype[obj->x_type]);
  181.     wool_printf(" d=%d", obj->detail);
  182.     wool_printf(" s=%d", obj->state);
  183.     /*print_atom_pointing_to(obj); */
  184.     wool_puts("}");
  185.     return (WOOL_OBJECT) obj;
  186. }
  187.  
  188. /*
  189.  * List of matching procedures for each event
  190.  */
  191.  
  192. int 
  193. WLEvent_user(wl_event, evt)
  194. WOOL_Event    wl_event;
  195. Event    evt;
  196. {
  197.     if ((wl_event -> detail == (int) evt -> xany.display)
  198.     || (wl_event -> detail == (unsigned int) ANY))
  199.     return TRUE;
  200.     else
  201.     return FALSE;
  202. }
  203.  
  204. int 
  205. WLEvent_propertychange(wl_event, evt)
  206. WOOL_Event    wl_event;
  207. Event    evt;
  208. {
  209.     if (evt -> xproperty.atom == (Atom) wl_event -> detail
  210.     || (wl_event -> detail == (unsigned int) ANY)) {
  211.     return TRUE;
  212.     } else
  213.     return FALSE;
  214. }
  215.  
  216. int 
  217. WLEvent_clientmessage(wl_event, evt)
  218. WOOL_Event    wl_event;
  219. Event    evt;
  220. {
  221.     if (evt -> xclient.message_type == (Atom) wl_event -> detail
  222.     || (wl_event -> detail == (unsigned int) ANY)) {
  223.     return TRUE;
  224.     } else
  225.     return FALSE;
  226. }
  227.  
  228. int 
  229. WLEvent_property_icon_pixmap_change(wl_event, evt)
  230. WOOL_Event    wl_event;
  231. Event    evt;
  232. {
  233.     if ((evt -> xproperty.atom == (Atom) XA_WM_HINTS) 
  234.     &&
  235.     (SetTarget(TargetWob),
  236.      TargetWindow -> cached_props -> wm_hints.flags & IconPixmapHint)
  237.     &&
  238.     (!(GWM_backup_of_old_property.wm_hints.flags & IconPixmapHint)
  239.      ||
  240.      TargetWindow -> cached_props -> wm_hints.icon_pixmap !=
  241.      GWM_backup_of_old_property.wm_hints.icon_pixmap))
  242.     return TRUE;
  243.     else
  244.     return FALSE;
  245. }
  246.  
  247. int 
  248. WLEvent_configurenotify(wl_event, evt)
  249. WOOL_Event    wl_event;
  250. Event    evt;
  251. {
  252.     return TRUE;
  253. }
  254.  
  255. int 
  256. WLEvent_buttonpress(wl_event, evt)
  257. WOOL_Event    wl_event;
  258. Event    evt;
  259. {
  260.     if (((wl_event -> detail == (unsigned int) ANY) ||
  261.      (wl_event -> detail == evt -> xbutton.button))
  262.     &&
  263.     ((wl_event -> state == (unsigned int) ANY) ||
  264.      (wl_event -> state == evt -> xbutton.state)))
  265.     return TRUE;
  266.     else
  267.     return FALSE;
  268. }
  269.  
  270. int 
  271. WLEvent_double_buttonpress(wl_event, evt)
  272. WOOL_Event    wl_event;
  273. Event    evt;
  274. {
  275.     if (((wl_event -> detail == (unsigned int) ANY) ||
  276.      (wl_event -> detail == evt -> xbutton.button))
  277.     &&
  278.     ((wl_event -> state == (unsigned int) ANY) ||
  279.      (wl_event -> state == evt -> xbutton.state))
  280.     &&
  281.     evt -> xbutton.button == GWM_LastEvent.xbutton.button
  282.     &&
  283.     evt -> xbutton.window == GWM_LastEvent.xbutton.window
  284.     &&
  285.     evt -> xbutton.time <
  286.     (GWM_LastEvent.xbutton.time + GWM_DoubleClickDelay))
  287.     return TRUE;
  288.     else
  289.     return FALSE;
  290. }
  291.  
  292. int 
  293. WLEvent_buttonrelease(wl_event, evt)
  294. WOOL_Event    wl_event;
  295. Event    evt;
  296. {
  297.     unsigned int butmask = ButtonMasks[evt -> xbutton.button];
  298.  
  299.     if (((wl_event -> detail == (unsigned int) ANY) ||
  300.      (wl_event -> detail == evt -> xbutton.button))
  301.     &&
  302.     ((wl_event -> state == (unsigned int) ANY) ||
  303.      ((wl_event -> state & butmask) == (evt -> xbutton.state & butmask)
  304.       )))
  305.     return TRUE;
  306.     else
  307.     return FALSE;
  308. }
  309.  
  310. int 
  311. WLEvent_keypress(wl_event, evt)
  312. WOOL_Event    wl_event;
  313. Event    evt;
  314. {
  315.     if (((wl_event -> detail == (unsigned int) ANY) ||
  316.      (wl_event -> detail == XKeycodeToKeysym(dpy,
  317.                     evt -> xkey.keycode, 0)))
  318.     &&
  319.     ((wl_event -> state == (unsigned int) ANY) ||
  320.      (wl_event -> state == evt -> xkey.state))) {
  321.     return TRUE;
  322.     } else
  323.     return FALSE;
  324. }
  325.  
  326. int 
  327. WLEvent_keyrelease(wl_event, evt)
  328. WOOL_Event    wl_event;
  329. Event    evt;
  330. {
  331.     if (((wl_event -> detail == (unsigned int) ANY) ||
  332.      (wl_event -> detail == XKeycodeToKeysym(dpy,
  333.                     evt -> xkey.keycode, 0)))
  334.     &&
  335.     ((wl_event -> state == (unsigned int) ANY) ||
  336.      (wl_event -> state == evt -> xkey.state))) {
  337.     return TRUE;
  338.     } else
  339.     return FALSE;
  340. }
  341.  
  342. /*
  343.  * enter & leave in the subtree of the window
  344.  */
  345.  
  346. int
  347. WLEvent_enterwindow(wl_event, evt)
  348. WOOL_Event    wl_event;
  349. Event    evt;
  350. {
  351.     XEvent          report;
  352.  
  353.     if (evt -> xcrossing.detail != NotifyInferior) {
  354.     /* XSync(dpy, 0); */
  355.     if (!XCheckTypedWindowEvent(dpy, evt -> xcrossing.window,
  356.                     LeaveNotify, &report)
  357.         || report.xcrossing.detail == NotifyInferior)
  358.         return TRUE;
  359.     else
  360.         return FALSE;
  361.     } else
  362.     return FALSE;
  363. }
  364.  
  365. int
  366. WLEvent_leavewindow(wl_event, evt)
  367. WOOL_Event    wl_event;
  368. Event    evt;
  369. {
  370.     XEvent          report;
  371.  
  372.     if (evt -> xcrossing.detail != NotifyInferior) {
  373.     /* XSync(dpy, 0); */
  374.     if (!XCheckTypedWindowEvent(dpy, evt -> xcrossing.window,
  375.                     EnterNotify, &report)
  376.         || report.xcrossing.detail == NotifyInferior)
  377.         return TRUE;
  378.     else
  379.         return FALSE;
  380.     } else
  381.     return FALSE;
  382. }
  383.  
  384. int
  385. WLEvent_enterwindow_nograb(wl_event, evt)
  386. WOOL_Event    wl_event;
  387. Event    evt;
  388. {
  389.     XEvent          report;
  390.  
  391.     if (evt -> xcrossing.detail != NotifyInferior) {
  392.     /* XSync(dpy, 0); */
  393.     if ((!XCheckTypedWindowEvent(dpy, evt -> xcrossing.window,
  394.                     LeaveNotify, &report)
  395.         || report.xcrossing.detail == NotifyInferior)
  396.         && evt -> xcrossing.mode != NotifyGrab
  397.         && evt -> xcrossing.mode != NotifyUngrab)
  398.         return TRUE;
  399.     else
  400.         return FALSE;
  401.     } else
  402.     return FALSE;
  403. }
  404.  
  405. int
  406. WLEvent_leavewindow_nograb(wl_event, evt)
  407. WOOL_Event    wl_event;
  408. Event    evt;
  409. {
  410.     XEvent          report;
  411.  
  412.     if (evt -> xcrossing.detail != NotifyInferior) {
  413.     /* XSync(dpy, 0); */
  414.     if ((!XCheckTypedWindowEvent(dpy, evt -> xcrossing.window,
  415.                     EnterNotify, &report)
  416.         || report.xcrossing.detail == NotifyInferior)
  417.         && evt -> xcrossing.mode != NotifyGrab
  418.         && evt -> xcrossing.mode != NotifyUngrab)
  419.         return TRUE;
  420.     else
  421.         return FALSE;
  422.     } else
  423.     return FALSE;
  424. }
  425.  
  426. /* Focus management
  427.  */
  428.  
  429. int
  430. WLEvent_focusin(wl_event, evt)
  431. WOOL_Event    wl_event;
  432. Event    evt;
  433. {
  434.     if (evt -> xfocus.detail == NotifyNonlinearVirtual
  435.      || TargetWob -> type == PlugClass) {
  436.     return TRUE;
  437.     } else
  438.     return FALSE;
  439. }
  440.  
  441. int
  442. WLEvent_focusout(wl_event, evt)
  443. WOOL_Event    wl_event;
  444. Event    evt;
  445. {
  446.     if (evt -> xfocus.detail == NotifyNonlinearVirtual
  447.      || TargetWob -> type == PlugClass) {
  448.     return TRUE;
  449.     } else
  450.     return FALSE;
  451. }
  452.  
  453.  
  454. /* visibility management
  455.  */
  456.  
  457. int
  458. WLEvent_visibility_partially_obscured(wl_event, evt)
  459. WOOL_Event      wl_event;
  460. Event   evt;
  461. {
  462.     return (evt -> xvisibility.state == VisibilityPartiallyObscured);
  463. }
  464.  
  465. int
  466. WLEvent_visibility_fully_obscured(wl_event, evt)
  467. WOOL_Event      wl_event;
  468. Event   evt;
  469. {
  470.     return (evt -> xvisibility.state == VisibilityFullyObscured);
  471. }
  472.  
  473. int
  474. WLEvent_visibility_unobscured(wl_event, evt)
  475. WOOL_Event      wl_event;
  476. Event   evt;
  477. {
  478.     return (evt -> xvisibility.state == VisibilityUnobscured);
  479. }
  480.  
  481. /*
  482.  * list of release procedures
  483.  */
  484.  
  485. int
  486. WLEvent_button_release(wl_event, evt)
  487. WOOL_Event      wl_event;
  488. Event   evt;
  489. {
  490.     wait_for_button_release(evt -> xbutton.button);
  491.     return 0;
  492. }
  493.  
  494. int
  495. WLEvent_key_release(wl_event, evt)
  496. WOOL_Event      wl_event;
  497. Event   evt;
  498. {
  499.     wait_for_key_release(evt -> xkey.keycode);
  500.     return 0;
  501. }
  502.  
  503. /* mapping of window
  504.  */
  505.  
  506. int
  507. WLEvent_map_notify(wl_event, evt)
  508. WOOL_Event      wl_event;
  509. Event   evt;
  510. {
  511.     return TRUE;
  512. }
  513.  
  514. /*
  515.  * functions to make the different events
  516.  */
  517.  
  518. WOOL_Event
  519. WLEvent_user_make(data)
  520. WOOL_Atom    data;
  521. {
  522.     WOOL_Event      event;
  523.  
  524.     if (data -> type == WLNumber && (((WOOL_Number) data) -> number == ANY))
  525.     event = WLEvent_make(0, ANY);
  526.     else
  527.     event = WLEvent_make(0, (unsigned int)data);
  528.     event -> x_type = GWMUserEvent;
  529.     event -> match = WLEvent_user;
  530.     event -> release = NULL;
  531.     event -> mask = 0;
  532.     event -> user_mask = 1;
  533.     return event;
  534. }
  535.  
  536. WOOL_Event
  537. WLEvent_propertychange_make(name)
  538. WOOL_String    name;
  539. {
  540.     WOOL_Event      event = WLEvent_make(0, 0);
  541.     WOOL_Pointer    x_atom;
  542.     Atom            property_name;
  543.  
  544.     event -> x_type = PropertyNotify;
  545.     event -> match = WLEvent_propertychange;
  546.     event -> release =  NULL;
  547.     event -> mask = PropertyChangeMask;
  548.     if (is_a_string(name)) {
  549.     if (wool_self_pointer_make(name -> string, '\030', &x_atom)) {
  550.         property_name = *(x_atom -> ptr);
  551.     } else {
  552.         property_name = XInternAtom(dpy, name -> string, False);
  553.         *(x_atom -> ptr) = property_name;
  554.     }
  555.     } else {
  556.     property_name = (Atom) ANY;
  557.     }
  558.     event -> detail = (unsigned int) property_name;    
  559.     return event;
  560. }
  561.  
  562. WOOL_Event
  563. WLEvent_clientmessage_make(name)
  564. WOOL_String    name;
  565. {
  566.     WOOL_Event      event = WLEvent_make(0, 0);
  567.     WOOL_Pointer    x_atom;
  568.     Atom            property_name;
  569.  
  570.     event -> x_type = ClientMessage;
  571.     event -> match = WLEvent_clientmessage;
  572.     event -> release =  NULL;
  573.     event -> mask = 0;
  574.     must_be_string(name, 0);
  575.     if (wool_self_pointer_make(name -> string, '\030', &x_atom)) {
  576.     property_name = *(x_atom -> ptr);
  577.     } else {
  578.     property_name = XInternAtom(dpy, name -> string, False);
  579.     *(x_atom -> ptr) = property_name;
  580.     }
  581.     event -> detail = (unsigned int) property_name;    
  582.     return event;
  583. }
  584.  
  585. WOOL_Event
  586. WLEvent_button_make(button, modifier)
  587. WOOL_Number    modifier;
  588. WOOL_Number    button;
  589. {
  590.     WOOL_Event      event = WLEvent_make(modifier -> number,
  591.           (button -> number == AnyButton ? ANY : button -> number));
  592.  
  593.     event -> x_type = ButtonPress;
  594.     event -> match = WLEvent_buttonpress;
  595.     event -> release =  WLEvent_button_release;
  596.     event -> mask = ButtonPressMask | ButtonReleaseMask;
  597.     return event;
  598. }
  599.  
  600. WOOL_Event
  601. WLEvent_buttonpress_make(button, modifier)
  602. WOOL_Number    modifier;
  603. WOOL_Number    button;
  604. {
  605.     WOOL_Event      event = WLEvent_button_make(button, modifier);
  606.  
  607.     event -> release = NULL;
  608.     return event;
  609. }
  610.  
  611. WOOL_Event
  612. WLEvent_double_button_make(button, modifier)
  613. WOOL_Number    modifier;
  614. WOOL_Number    button;
  615. {
  616.     WOOL_Event      event = WLEvent_make(modifier -> number,
  617.           (button -> number == AnyButton ? ANY : button -> number));
  618.  
  619.     event -> x_type = ButtonPress;
  620.     event -> match = WLEvent_double_buttonpress;
  621.     event -> release =  WLEvent_button_release;
  622.     event -> mask = ButtonPressMask | ButtonReleaseMask;
  623.     return event;
  624. }
  625.  
  626. WOOL_Event
  627. WLEvent_double_buttonpress_make(button, modifier)
  628. WOOL_Number    modifier;
  629. WOOL_Number    button;
  630. {
  631.     WOOL_Event      event = WLEvent_double_button_make(button, modifier);
  632.  
  633.     event -> release = NULL;
  634.     return event;
  635. }
  636.  
  637. WOOL_Event
  638. WLEvent_buttonrelease_make(button, modifier)
  639. WOOL_Number    modifier;
  640. WOOL_Number    button;
  641. {
  642.     WOOL_Event      event =
  643.     WLEvent_button_make(button,
  644.             WLNumber_make(((unsigned long) modifier -> number) |
  645.       (((unsigned long) Button1Mask) << (button -> number - Button1))));
  646.  
  647.     event -> x_type = ButtonRelease;
  648.     event -> match = WLEvent_buttonrelease;
  649.     event -> release = NULL;
  650.     return event;
  651. }
  652.  
  653. WOOL_Event
  654. WLEvent_key_make(key, modifier)
  655. WOOL_Number    modifier;
  656. WOOL_Number    key;
  657. {
  658.     WOOL_Event      event;
  659.     KeySym          keysym;
  660.  
  661.     must_be_number(modifier, 1);
  662.     if (key -> type == WLNumber)
  663.     keysym = key -> number;
  664.     else {
  665.     if ((keysym = XStringToKeysym(((WOOL_String) key) -> string))
  666.         == NoSymbol) {
  667.         wool_printf("unknown key name: \"%s\"\n", 
  668.             ((WOOL_String) key) -> string);
  669.         keysym = (KeySym) UNDEFINED_KEYCODE;
  670.         }
  671.     }
  672.     event = WLEvent_make(modifier -> number, keysym);
  673.     event -> x_type = KeyPress;
  674.     event -> match = WLEvent_keypress;
  675.     event -> release = WLEvent_key_release;
  676.     event -> mask = KeyPressMask | KeyReleaseMask;
  677.     return event;
  678. }
  679.  
  680. WOOL_Event
  681. WLEvent_keypress_make(key, modifier)
  682. WOOL_Number    modifier;
  683. WOOL_Number    key;
  684. {
  685.     WOOL_Event      event = WLEvent_key_make(key, modifier);
  686.  
  687.     event -> release = NULL;
  688.     return event;
  689. }
  690.  
  691. WOOL_Event
  692. WLEvent_keyrelease_make(key, modifier)
  693. WOOL_Number    modifier;
  694. WOOL_Number    key;
  695. {
  696.     WOOL_Event      event = WLEvent_key_make(key, modifier);
  697.  
  698.     event -> x_type = KeyRelease;
  699.     event -> match = WLEvent_keyrelease;
  700.     event -> release = NULL;
  701.     return event;
  702. }
  703.  
  704. /*
  705.  * Initialize all the events
  706.  */
  707.  
  708. void
  709. wool_all_events_make()
  710. {
  711.     grab_queue_init();
  712.  
  713.     wool_atom_with_numeric_value_make("any", ANY);
  714.     wool_atom_with_numeric_value_make("alone", 0);
  715.     wool_atom_with_numeric_value_make("with-button-1", Button1Mask);
  716.     wool_atom_with_numeric_value_make("with-button-2", Button2Mask);
  717.     wool_atom_with_numeric_value_make("with-button-3", Button3Mask);
  718.     wool_atom_with_numeric_value_make("with-button-4", Button4Mask);
  719.     wool_atom_with_numeric_value_make("with-button-5", Button5Mask);
  720.     wool_atom_with_numeric_value_make("with-shift", ShiftMask);
  721.     wool_atom_with_numeric_value_make("with-lock", LockMask);
  722.     wool_atom_with_numeric_value_make("with-control", ControlMask);
  723.     wool_atom_with_numeric_value_make("with-alt", Mod1Mask);
  724.     wool_atom_with_numeric_value_make("with-modifier-1", Mod1Mask);
  725.     wool_atom_with_numeric_value_make("with-modifier-2", Mod2Mask);
  726.     wool_atom_with_numeric_value_make("with-modifier-3", Mod3Mask);
  727.     wool_atom_with_numeric_value_make("with-modifier-4", Mod4Mask);
  728.     wool_atom_with_numeric_value_make("with-modifier-5", Mod5Mask);
  729.  
  730.     wool_subr_make(WLSubr, WLEvent_buttonpress_make, "buttonpress", 2);
  731.     wool_subr_make(WLSubr, WLEvent_keypress_make, "keypress", 2);
  732.     wool_subr_make(WLSubr, WLEvent_button_make, "button", 2);
  733.     wool_subr_make(WLSubr, WLEvent_key_make, "key", 2);
  734.     wool_subr_make(WLSubr, WLEvent_buttonrelease_make, "buttonrelease", 2);
  735.     wool_subr_make(WLSubr, WLEvent_keyrelease_make, "keyrelease", 2);
  736.     wool_subr_make(WLSubr, WLEvent_user_make, "user-event", 1);
  737.     wool_subr_make(WLSubr, WLEvent_propertychange_make, "property-change", 1);
  738.     wool_subr_make(WLSubr, WLEvent_clientmessage_make, "client-message", 1);
  739.     wool_subr_make(WLSubr, WLEvent_double_buttonpress_make,
  740.            "double-buttonpress", 2);
  741.     wool_subr_make(WLSubr, WLEvent_double_button_make, "double-button", 2);
  742.     wool_event_make("name-change", PropertyNotify, WLEvent_propertychange,
  743.     NULL, PropertyChangeMask, 0, XA_WM_NAME);
  744.     wool_event_make("window-icon-pixmap-change", PropertyNotify,
  745.             WLEvent_property_icon_pixmap_change, NULL,
  746.             PropertyChangeMask, 0, XA_WM_HINTS);
  747.     wool_event_make("geometry-change", ConfigureNotify,
  748.     WLEvent_configurenotify, NULL, SubstructureNotifyMask, 0, 0);
  749.     wool_event_make("enter-window", EnterNotify, WLEvent_enterwindow, NULL,
  750.             EnterWindowMask, 0, 0);
  751.     wool_event_make("leave-window", LeaveNotify, WLEvent_leavewindow, NULL,
  752.             LeaveWindowMask, 0, 0);
  753.     wool_event_make("enter-window-not-from-grab", EnterNotify,
  754.             WLEvent_enterwindow_nograb, NULL,
  755.             EnterWindowMask, 0, 0);
  756.     wool_event_make("leave-window-not-from-grab", LeaveNotify,
  757.             WLEvent_leavewindow_nograb, NULL,
  758.             LeaveWindowMask, 0, 0);
  759.     wool_event_make("focus-in", FocusIn, WLEvent_focusin, NULL,
  760.             FocusChangeMask, 0, 0);
  761.     wool_event_make("focus-out", FocusOut, WLEvent_focusout, NULL,
  762.             FocusChangeMask, 0, 0);
  763.     wool_event_make("map-notify", MapNotify, WLEvent_map_notify, NULL,
  764.             StructureNotifyMask, 0, 0);
  765.     wool_event_make("visibility-unobscured", VisibilityNotify,
  766.             WLEvent_visibility_unobscured,
  767.             NULL, VisibilityChangeMask, 0, 0);
  768.     wool_event_make("visibility-partially-obscured", VisibilityNotify,
  769.             WLEvent_visibility_partially_obscured,
  770.             NULL, VisibilityChangeMask, 0, 0);
  771.     wool_event_make("visibility-fully-obscured", VisibilityNotify,
  772.             WLEvent_visibility_fully_obscured,
  773.             NULL, VisibilityChangeMask, 0, 0);
  774. }
  775.  
  776. /*
  777.  * wait for release of button n
  778.  */
  779.  
  780. int
  781. LookForButtonRelease(display, evt, arg)
  782. Display *display;
  783. XEvent *evt;
  784. char *arg;
  785. {
  786.     int n = (int)arg;
  787.     if ((evt -> type == ButtonRelease) && (evt -> xbutton.button == n))
  788.     return True;
  789.     else
  790.     return False;
  791. }
  792.  
  793. wait_for_button_release(n)
  794. int n;
  795. {
  796.     XEvent        button_event;
  797.  
  798.     XIfEvent(dpy, &button_event, LookForButtonRelease, (char *)n);
  799. }
  800.  
  801. /*
  802.  * wait for release of key of code n
  803.  */
  804.  
  805. int
  806. LookForKeyRelease(display, evt, arg)
  807. Display *display;
  808. XEvent *evt;
  809. char *arg;
  810. {
  811.     if ((evt -> type == KeyRelease) && (evt -> xkey.keycode == (int)arg))
  812.     return True;
  813.     else
  814.     return False;
  815. }
  816.  
  817. wait_for_key_release(n)
  818. int n;
  819. {
  820.     XEvent        button_event;
  821.  
  822.     XIfEvent(dpy, &button_event, LookForKeyRelease, (char *)n);
  823. }
  824.  
  825. /* grab management
  826.  */
  827.  
  828. WOOL_OBJECT
  829. set_grab(wob)
  830. Wob    wob;
  831. {
  832.     WOOL_Cursor     cursor;
  833.     int             status;
  834.  
  835.     if (wob -> type == MenuClass)
  836.     cursor = (WOOL_Cursor) wob -> cursor;
  837.     else
  838.     cursor =
  839.         (WOOL_Cursor) WOOL_send(WOOL_eval, WA_cursor, (WA_cursor));
  840.     if ((status =
  841.      XGrabPointer(dpy, wob -> hook, True,
  842.               LegalPointerEventMask(((WOOL_Fsm) wob -> fsm) -> mask),
  843.               GrabModeAsync, GrabModeAsync,
  844.               (GWM_confine_grabs ? wob -> hook : None),
  845.               (cursor == (WOOL_Cursor) NIL ? None : cursor -> cursor),
  846.               CurrentTime))
  847.     != GrabSuccess)
  848.     return (WOOL_OBJECT) WLNumber_make(status);
  849.     if (GWM_grab_keyboard_also)
  850.     if ((status = XGrabKeyboard(dpy, wob -> hook, True,
  851.                  GrabModeAsync, GrabModeAsync, CurrentTime))
  852.         != GrabSuccess) {
  853.         XUngrabPointer(dpy, CurrentTime);
  854.         return (WOOL_OBJECT) WLNumber_make(status);
  855.     } else {
  856.         GWM_KeyboardGrabbed = wob;
  857.     }
  858.     if (GWM_GrabServer)
  859.     XGrabServer(dpy);
  860.     GWM_ServerGrabbed = wob;
  861.     return NIL;
  862. }
  863.  
  864. WOOL_OBJECT
  865. remove_grab(wob)
  866. Wob    wob;
  867. {
  868.     if (!wob || wob == GWM_ServerGrabbed) {
  869.     if (GWM_ServerGrabbed)
  870.       XUngrabPointer(dpy, CurrentTime);
  871.     if (GWM_KeyboardGrabbed)
  872.       XUngrabKeyboard(dpy, CurrentTime);
  873.     if (GWM_GrabServer)
  874.       XUngrabServer(dpy);
  875.     XSync(dpy, 0);
  876.     GWM_ServerGrabbed = GWM_KeyboardGrabbed = NULL;
  877.     FlushQueuedGrabEvents();
  878.     }
  879.     return NIL;
  880. }
  881.  
  882. WOOL_OBJECT
  883. wool_set_grab(argc, argv)
  884. int    argc;
  885. WOOL_Number    argv[];
  886. {
  887.     GWM_GrabChildEvents = 0;
  888.     switch (argc) {
  889.     case 0:
  890.     return set_grab(TargetWob);
  891.     case 2:
  892.     GWM_GrabChildEvents = 1;
  893.     }
  894.     must_be_number(argv[0], 0);
  895.     return set_grab(argv[0] -> number);
  896. }
  897.  
  898. WOOL_OBJECT
  899. wool_remove_grab(argc, argv)
  900. int    argc;
  901. WOOL_Number    argv[];
  902. {
  903.     if (!argc)
  904.     return remove_grab(0);
  905.     must_be_number(argv[0], 0);
  906.     return remove_grab(argv[0] -> number);
  907. }
  908.  
  909. /* replay back event in a grab
  910.  * if arg != NIL, replay key event
  911.  */
  912.  
  913. WOOL_OBJECT
  914. wool_ungrab_and_replay_event(key)
  915. WOOL_OBJECT    key;
  916. {
  917.     if (key == NIL)
  918.     XAllowEvents(dpy, ReplayPointer, CurrentTime);
  919.     else
  920.     XAllowEvents(dpy, ReplayKeyboard, CurrentTime);
  921.     return NIL;
  922. }
  923.  
  924. /* makes a button event replayable */
  925.  
  926. WOOL_OBJECT
  927. wool_makes_replayable(event)
  928. WOOL_Event     event;
  929. {
  930.     must_be_event(event, 0);
  931.     event -> flags |= FREEZE_ON_GRABS;
  932.     return (WOOL_OBJECT) event;
  933. }
  934.  
  935. /* allows event processing after a freeze due to a replayable event
  936.  */
  937.  
  938. WOOL_OBJECT
  939. wool_allow_events()
  940. {
  941.     XAllowEvents(dpy, AsyncPointer, CurrentTime);
  942.     XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
  943.     return NIL;
  944. }
  945.  
  946. /* last events of some type
  947.  */
  948.  
  949. WOOL_OBJECT
  950. wool_last_key_struck()
  951. {
  952.     char            s[81];
  953.     int             l;
  954.  
  955.     if ((TriggeringEvent -> type == KeyPress ||
  956.      TriggeringEvent -> type == KeyRelease)
  957.     && (l = XLookupString(&TriggeringEvent->xkey, s, 80, 0, 0))) {
  958.     s[l] = '\0';
  959.     return (WOOL_OBJECT) WLString_make(s);
  960.     } else
  961.     return NIL;
  962. }
  963.  
  964. WOOL_OBJECT
  965. wool_last_user_event()
  966. {
  967.     if (TriggeringEvent -> type == GWMUserEvent)
  968.     return (WOOL_OBJECT) TriggeringEvent -> xany.display;
  969.     else
  970.     return wool_error("last event%s was not an user event", "");
  971. }
  972.  
  973. Event
  974. last_key_or_button_event(evt)
  975. Event    evt;
  976. {
  977.     if (event_is_key_or_button(*TriggeringEvent))
  978.     return TriggeringEvent;
  979.     else
  980.     return &GWM_LastEvent;
  981. }
  982.  
  983. /*
  984.  * returns the coords of the click relative to the client as a list
  985.  * (logical-x logical-y x y) for the current window's client
  986.  */
  987.  
  988. #ifdef NOBASEDIMS
  989. #ifdef PBaseSize
  990. #undef PBaseSize
  991. #endif
  992. #define PBaseSize PMinSize
  993. #define base_width min_width
  994. #define base_height min_height
  995. #endif /* NOBASEDIMS */
  996.  
  997.  
  998. WOOL_OBJECT
  999. wool_logical_coords()
  1000. {
  1001.     int             x=0 , y=0;
  1002.     Window          child;
  1003.     WOOL_List       wl_list = wool_list_make(6);
  1004.     Event           evt = last_key_or_button_event(TriggeringEvent);
  1005.     XSizeHints     *normal_hints =
  1006.     &(TargetWindow -> cached_props -> normal_hints);
  1007.  
  1008.     if (TargetWindow -> client)
  1009.     XTranslateCoordinates(dpy, evt -> xbutton.root,
  1010.                   TargetWindow -> client, evt -> xbutton.x_root,
  1011.                   evt -> xbutton.y_root, &x, &y, &child);
  1012.     increase_reference(wl_list -> list[0] = (WOOL_OBJECT) WLNumber_make(
  1013.         (x - (normal_hints -> flags & PBaseSize ?
  1014.           normal_hints -> base_width : 0))
  1015.      / (normal_hints -> flags & PResizeInc ?
  1016.         normal_hints -> width_inc : 1)));
  1017.     increase_reference(wl_list -> list[1] = (WOOL_OBJECT) WLNumber_make(
  1018.         (y - (normal_hints -> flags & PBaseSize ?
  1019.           normal_hints -> base_height : 0))
  1020.      / (normal_hints -> flags & PResizeInc ?
  1021.         normal_hints -> height_inc : 1)));
  1022.     increase_reference(wl_list -> list[2] = (WOOL_OBJECT) WLNumber_make(x));
  1023.     increase_reference(wl_list -> list[3] = (WOOL_OBJECT) WLNumber_make(y));
  1024.  
  1025.     XTranslateCoordinates(dpy, evt -> xbutton.root,
  1026.                               TargetWindow -> hook, evt -> xbutton.x_root,
  1027.                               evt -> xbutton.y_root, &x, &y, &child);
  1028.     increase_reference(wl_list -> list[4] = (WOOL_OBJECT) WLNumber_make(x));
  1029.     increase_reference(wl_list -> list[5] = (WOOL_OBJECT) WLNumber_make(y));
  1030.  
  1031.     return (WOOL_OBJECT) wl_list;
  1032. }
  1033.  
  1034. int EventMasks[]={0,0,
  1035.     KeyPressMask,
  1036.     KeyReleaseMask,
  1037.     ButtonPressMask,
  1038.     ButtonReleaseMask};
  1039.  
  1040. WOOL_OBJECT
  1041. wool_resend_event(wob)
  1042. WOOL_Number    wob;
  1043. {
  1044.     Window          window;
  1045.     Event        evt = last_key_or_button_event(TriggeringEvent);
  1046.  
  1047.     if (wob = (WOOL_Number) NIL)
  1048.     window = TargetWindow -> client;
  1049.     else
  1050.     window = ((Wob) wob) -> hook;
  1051.     if (window) {
  1052.     evt -> xany.window = window;
  1053.     XSendEvent(dpy, TargetWindow -> client, False,
  1054.            EventMasks[evt->type], evt);
  1055.     XFlush(dpy);
  1056.     }
  1057.     return (WOOL_OBJECT) NIL;
  1058. }
  1059.  
  1060. WOOL_OBJECT
  1061. wool_send_keycode_to_client(keycode, mod)
  1062. WOOL_Number    keycode, mod;
  1063. {
  1064.     XEvent event;
  1065.  
  1066.     fill_x_key_event(&event, keycode -> number, mod -> number);
  1067.     XSendEvent(dpy, TargetWindow -> client, False, KeyPressMask, &event);
  1068.     fill_x_key_event(&event, keycode -> number, mod -> number);
  1069.     event.type = KeyRelease;
  1070.     XSendEvent(dpy, TargetWindow -> client, False, KeyReleaseMask, &event);
  1071.     return (WOOL_OBJECT) keycode;
  1072. }
  1073.  
  1074. WOOL_OBJECT
  1075. wool_send_key_to_client(key, mod)
  1076. WOOL_Number    key, mod;
  1077. {
  1078.     XEvent event;
  1079.     char           *p = 0;
  1080.     int             keysym, keycode;
  1081.     int modifier;
  1082.  
  1083.     must_be_number(mod, 1);
  1084.     if (key -> type != WLNumber) {
  1085.     must_be_string(key, 0);
  1086.     p = ((WOOL_String) key) -> string;
  1087.     if (!(*p))
  1088.         return NIL;
  1089.     }
  1090.     do {                /* we MUST re-init event each time */
  1091.     modifier = mod -> number;
  1092.     if (key -> type == WLNumber)
  1093.         keysym = key -> number;
  1094.     else {
  1095.         keysym = *p++;
  1096.     }
  1097.     if (!(keycode = XKeysymToKeycode(dpy, keysym)))
  1098.         return wool_error("unknown keysym for this server: 0x%x", keysym);
  1099.  
  1100.     /* add shift automatically for shifted chars */
  1101.     /* We should do same thing for control chars & meta... */
  1102.     if (keysym != XKeycodeToKeysym(dpy, keycode, 0)) {
  1103.         if (keysym == XKeycodeToKeysym(dpy, keycode, 1)) {
  1104.         modifier |= ShiftMask;
  1105.         }
  1106.     }
  1107.  
  1108.     fill_x_key_event(&event, keycode, modifier);
  1109.     XSendEvent(dpy, TargetWindow -> client, False, KeyPressMask, &event);
  1110.     fill_x_key_event(&event, keycode, modifier);
  1111.     event.type = KeyRelease;
  1112.     XSendEvent(dpy, TargetWindow -> client, False, KeyReleaseMask,
  1113.            &event);
  1114.     } while (p && *p);
  1115.     return (WOOL_OBJECT) key;
  1116. }
  1117.  
  1118. fill_x_key_event(evt, keycode, modifier)
  1119. XKeyPressedEvent *evt;
  1120. int keycode, modifier;
  1121. {
  1122.     evt -> type = KeyPress;
  1123.     evt -> display = dpy;
  1124.     evt -> window =  evt -> subwindow = TargetWindow -> client;
  1125.     evt -> root = Context->root;
  1126.     evt -> time = CurrentTime;
  1127.     evt -> x = evt -> y = evt -> x_root = evt -> y_root = 0;
  1128.     evt -> same_screen = 1;
  1129.     evt -> keycode = keycode;
  1130.     evt -> state = modifier;
  1131. }
  1132.  
  1133. /* same with button: button modifier x y
  1134.  */
  1135.  
  1136. fill_x_button_event(evt, button, modifier, x, y, x_root, y_root, child)
  1137. XButtonEvent *evt;
  1138. int button, modifier, x, y, x_root, y_root;
  1139. Window child;
  1140. {
  1141.     evt -> type = ButtonPress;
  1142.     evt -> display = dpy;
  1143.     evt -> window = child;
  1144.     evt -> subwindow = 0;
  1145.     evt -> root = Context->root;
  1146.     evt -> time = CurrentTime;
  1147.     evt -> x = x;
  1148.     evt -> y = y;
  1149.     evt -> x_root = x_root;
  1150.     evt -> y_root = y_root;
  1151.     evt -> same_screen = 1;
  1152.     evt -> button = button;
  1153.     evt -> state = modifier;
  1154. }
  1155.  
  1156. /* look which window would receive button event
  1157.  */
  1158.  
  1159. Window
  1160. WindowGettingButtonEvent(w, x, y)
  1161. Window w;
  1162. int x,y;
  1163. {
  1164.     int x2, y2;
  1165.     Window child, w2 = w;
  1166.     XWindowAttributes wa;
  1167.  
  1168.  find_window:
  1169.     XTranslateCoordinates(dpy, w, w2, x, y, &x2, &y2, &child);
  1170.     if (child) {
  1171.     x = x2;
  1172.     y = y2;
  1173.     w = w2;
  1174.     w2 = child;
  1175.     goto find_window;
  1176.     }
  1177.     x = x2;
  1178.     y = y2;
  1179.     w = w2;
  1180.  
  1181.  find_listener:
  1182.     XGetWindowAttributes(dpy, w, &wa);
  1183.     if (!(wa.all_event_masks & (ButtonPressMask | ButtonReleaseMask))) {
  1184.     Window d1, d2, *d3, parent;
  1185.     unsigned int d4;
  1186.     
  1187.     XQueryTree(dpy, w, &d1, &parent, &d3, &d4);
  1188.     XFreeN(d3);
  1189.     if (parent) {
  1190.         w = parent;
  1191.         goto find_listener;
  1192.     }
  1193.     }
  1194.     return w;
  1195. }
  1196.  
  1197. WOOL_OBJECT
  1198. wool_send_button_to_client(argc, argv)
  1199. int    argc;
  1200. WOOL_Number    argv[];
  1201. {
  1202.     XEvent event;
  1203.     int button, modifier, x, y, x2, y2, x_root, y_root, i;
  1204.     Window child, dummy;
  1205.  
  1206.     if (argc != 4)
  1207.     return wool_error(BAD_NUMBER_OF_ARGS, argc);
  1208.     for (i = 0; i < argc; i++)
  1209.     must_be_number(argv[i], i);
  1210.     button = argv[0] -> number;
  1211.     modifier = argv[1] -> number;
  1212.     x = argv[2] -> number;
  1213.     y = argv[3] -> number;
  1214.  
  1215.     XTranslateCoordinates(dpy, TargetWindow -> client, Context -> root, x, y,
  1216.               &x_root, &y_root, &child);
  1217.  
  1218.     child = WindowGettingButtonEvent(TargetWindow -> client, x, y);
  1219.     x2 =x, y2 =y;
  1220.     XTranslateCoordinates(dpy, TargetWindow -> client, child, x2, y2,
  1221.               &x, &y, &dummy);
  1222.  
  1223.     fill_x_button_event(&event, button, modifier, x, y, x_root, y_root, child);
  1224.     XSendEvent(dpy, child, False, ButtonPressMask, &event);
  1225.     fill_x_button_event(&event, button, modifier, x, y, x_root, y_root, child);
  1226.     event.type = ButtonRelease;
  1227.     XSendEvent(dpy, child, False, ButtonReleaseMask, &event);
  1228.     return (WOOL_OBJECT) argv[0];
  1229. }
  1230.  
  1231. /* management of the enter/leave on grabs for menus
  1232.  * these functions are used
  1233.  * - just before sending event in GWM_ProcessEvents (gwm.c)
  1234.  *         if (IsNotGrabDiscarded(&evt)) {
  1235.  *         send-event...
  1236.  *         }
  1237.  * - in remove_grab (at the end) for FlushQueuedGrabEvents
  1238.  * 
  1239.  * - in wool_all_events_make for grab_queue_init
  1240.  */
  1241.  
  1242. static XEvent *grab_queue;
  1243. static int     grab_queue_start;
  1244. static int     grab_queue_size;
  1245. static int     grab_queue_limit;
  1246.  
  1247. grab_queue_init()
  1248. {
  1249.     grab_queue_size = 0;
  1250.     grab_queue_limit = 1;
  1251.     grab_queue = (XEvent *) Malloc(grab_queue_limit * sizeof(XEvent));
  1252. }
  1253.  
  1254. int
  1255. IsNotGrabDiscarded(evt)
  1256. Event    evt;
  1257. {
  1258.     if (((evt -> type == LeaveNotify)
  1259.      && (evt -> xcrossing.mode == NotifyGrab))
  1260.     || ((evt -> type == FocusOut)
  1261.         && (evt -> xfocus.mode == NotifyGrab))) {
  1262.     if (grab_queue_size == grab_queue_limit) {
  1263.         grab_queue_limit *= 2;
  1264.         grab_queue = (XEvent *) Realloc(grab_queue, grab_queue_limit
  1265.                         * sizeof(XEvent));
  1266.     }
  1267.     bcopy(evt, &grab_queue[grab_queue_size++], sizeof(XEvent));
  1268.     return FALSE;
  1269.     } else {
  1270.     if (((evt -> type == EnterNotify)
  1271.      && (evt -> xcrossing.mode == NotifyUngrab))
  1272.     || ((evt -> type == FocusIn)
  1273.         && (evt -> xfocus.mode == NotifyUngrab))) {
  1274.         return TRUE;
  1275.     } else {
  1276.         return FALSE;
  1277.     }
  1278.     }
  1279. }
  1280.  
  1281. FlushQueuedGrabEvents()
  1282. {
  1283.     Wob             wob;
  1284.  
  1285.     SAVE_EVENT_CONTEXT;
  1286.     while (grab_queue_start < grab_queue_size) {
  1287.     if (wob = (Wob) LookUpWob(grab_queue[grab_queue_start].xany.window)) {
  1288.         WOOL_send(WOOL_process_event, wob,
  1289.               (wob, &grab_queue[grab_queue_start]));
  1290.     }
  1291.     grab_queue_start++;
  1292.     }
  1293.     RESTORE_EVENT_CONTEXT;
  1294.     grab_queue_size = 0;
  1295.     grab_queue_start = 0;
  1296. }
  1297.  
  1298.  
  1299. /*
  1300.  * recuperates parameters of the triggering event
  1301.  */
  1302.  
  1303. #define field_of_event(evt, event_property, etype, field) \
  1304.     if(TriggeringEvent->type > 1 && TriggeringEvent->type < LASTEvent && \
  1305.        EventProperties[TriggeringEvent->type] & event_property) \
  1306.     return (WOOL_OBJECT) WLNumber_make(((etype *) evt) -> field); \
  1307.     else return (WOOL_OBJECT) WLNumber_make(0);
  1308.  
  1309. WOOL_OBJECT
  1310. wool_get_triggering_event_data()
  1311. {
  1312.     if (TriggeringEvent->type == ClientMessage)
  1313.     {
  1314.     
  1315.  
  1316.     switch (((XClientMessageEvent *) TriggeringEvent)->format)
  1317.     {
  1318.     case 8:
  1319.         return ((WOOL_OBJECT) WLString_make(
  1320.             ((XClientMessageEvent *) TriggeringEvent)->data.b));
  1321.     case 16:
  1322.         {
  1323.         WOOL_Number ListArgv[10];
  1324.         int i;
  1325.         
  1326.         for (i=0;i<10;i++)
  1327.         {
  1328.             ListArgv[i] = WLNumber_make(
  1329.             ((XClientMessageEvent *) TriggeringEvent)->data.s[i]);
  1330.         }
  1331.         return ((WOOL_OBJECT) wool_list_make_from_evaluated_array(10,
  1332.                            (WOOL_OBJECT *) ListArgv));
  1333.         }
  1334.     case 32:
  1335.         {
  1336.         WOOL_Number ListArgv[5];
  1337.         int i;
  1338.         
  1339.         for (i=0;i<5;i++)
  1340.         {
  1341.             ListArgv[i] = WLNumber_make(
  1342.             ((XClientMessageEvent *) TriggeringEvent)->data.l[i]);
  1343.         }
  1344.         return ((WOOL_OBJECT) wool_list_make_from_evaluated_array(5,
  1345.                            (WOOL_OBJECT *) ListArgv));
  1346.         }
  1347.     }
  1348.     }
  1349.     return wool_error("internal error, event was not of good type%s", "");
  1350. }
  1351.  
  1352. WOOL_OBJECT
  1353. wool_get_triggering_event_state()
  1354. {
  1355.     field_of_event(TriggeringEvent, EPKeyOrButton, XButtonEvent, state);
  1356. }
  1357.  
  1358. WOOL_OBJECT
  1359. wool_get_triggering_event_code()
  1360. {
  1361.     field_of_event(TriggeringEvent, EPKeyOrButton, XButtonEvent, button);
  1362. }
  1363.  
  1364. WOOL_OBJECT
  1365. wool_get_triggering_event_x()
  1366. {
  1367.     field_of_event(TriggeringEvent, EPXYRoot, XButtonEvent, x_root);
  1368. }
  1369.  
  1370. WOOL_OBJECT
  1371. wool_get_triggering_event_y()
  1372. {
  1373.     field_of_event(TriggeringEvent, EPXYRoot, XButtonEvent, y_root);
  1374. }
  1375.  
  1376. WOOL_OBJECT
  1377. wool_get_triggering_event_x_relative()
  1378. {
  1379.     field_of_event(TriggeringEvent, EPXY, XButtonEvent, x);
  1380. }
  1381.  
  1382. WOOL_OBJECT
  1383. wool_get_triggering_event_y_relative()
  1384. {
  1385.     field_of_event(TriggeringEvent, EPXY, XButtonEvent, y);
  1386. }
  1387.  
  1388. WOOL_OBJECT
  1389. wool_get_triggering_event_time()
  1390. {
  1391.     field_of_event(TriggeringEvent, EPXY, XButtonEvent, time);
  1392. }
  1393.  
  1394. /* used to know if current event was due to a grab */
  1395.  
  1396. WOOL_OBJECT
  1397. wool_event_was_due_to_a_grab()
  1398. {
  1399.     WOOL_Atom             result = (WOOL_Atom) NIL;
  1400.  
  1401.     if (event_is_crossing(*TriggeringEvent)) {
  1402.     if (TriggeringEvent -> xcrossing.mode == NotifyGrab)
  1403.         result = WA_grab;
  1404.     else if (TriggeringEvent -> xcrossing.mode == NotifyUngrab)
  1405.         result = WA_ungrab;
  1406.     } else if (event_is_focus(*TriggeringEvent)) {
  1407.     if (TriggeringEvent -> xfocus.mode == NotifyGrab)
  1408.         result = WA_grab;
  1409.     else if (TriggeringEvent -> xfocus.mode == NotifyUngrab)
  1410.         result = WA_ungrab;
  1411.     }
  1412.     return (WOOL_OBJECT) result;
  1413. }
  1414.  
  1415. /********************\
  1416. *              *
  1417. * Tracing of events  *
  1418. *              *
  1419. \********************/
  1420.  
  1421. #ifdef DEBUG
  1422.  
  1423. char *FocusDetailText[] = {
  1424.     "NotifyAncestor",        /* 0 */
  1425.     "NotifyVirtual",        /* 1 */
  1426.     "NotifyInferior",        /* 2 */
  1427.     "NotifyNonlinear",        /* 3 */
  1428.     "NotifyNonlinearVirtual",    /* 4 */
  1429.     "NotifyPointer",        /* 5 */
  1430.     "NotifyPointerRoot",    /* 6 */
  1431.     "NotifyDetailNone"        /* 7 */
  1432. };
  1433.  
  1434. char *FocusModeText[] = {
  1435.     "NotifyNormal",            /* 0 */
  1436.     "NotifyGrab",              /* 1 */
  1437.     "NotifyUngrab",            /* 2 */
  1438.     "NotifyWhileGrabbed"       /* 3 */
  1439. };
  1440.  
  1441. GWM_prettyprint_fsm_event(wob, evt, text, state, newstate)
  1442. Wob    wob;
  1443. Event           evt;
  1444. char    *text;
  1445. int state, newstate;
  1446. {
  1447.     fprintf(stderr, "%s %s (0x%lx/0x%lx): ",
  1448.         text, ((WOOL_Atom) wob -> type[0])-> p_name,
  1449.         wob, wob -> hook);
  1450.     if (state || newstate) {
  1451.     fprintf(stderr, " (s%d", state);
  1452.     if (state != newstate) {
  1453.         fprintf(stderr, "->%d", newstate);
  1454.     }
  1455.     fprintf(stderr, ")");
  1456.     }
  1457.     GWM_prettyprint_event(" ", evt, "\n");
  1458. }
  1459.  
  1460. GWM_prettyprint_event(tag, evt, end)
  1461.     char *tag;
  1462.     Event evt;
  1463.     char *end;
  1464. {
  1465.     fputs(tag, stderr);
  1466.     fprintf(stderr, "%s ", eventtype[evt -> type]); 
  1467.     switch (evt->type) {
  1468.     case GWMUserEvent:
  1469.     fprintf(stderr, "%s",
  1470.         ((WOOL_String) (evt->xany.display))->string);
  1471.     break;
  1472.     case FocusIn:
  1473.     case FocusOut:
  1474.     fprintf(stderr, "w 0x%x, detail %s, mode %s",
  1475.         evt->xfocus.window,
  1476.         FocusDetailText[evt->xfocus.detail],
  1477.         FocusModeText[evt->xfocus.mode]);
  1478.     break;
  1479.     case EnterNotify:
  1480.     case LeaveNotify:
  1481.     fprintf(stderr, "w 0x%x, detail %s, mode %s",
  1482.         evt->xcrossing.window,
  1483.         FocusDetailText[evt->xcrossing.detail],
  1484.         FocusModeText[evt->xcrossing.mode]);
  1485.     break;
  1486.     case PropertyNotify:
  1487.     fprintf(stderr, "w 0x%x, %s",
  1488.         evt->xproperty.window,
  1489.         XGetAtomName(dpy, evt->xproperty.atom));
  1490.     break;
  1491.     case ReparentNotify:
  1492.     fprintf(stderr, "w 0x%x to 0x%x %s",
  1493.         evt->xreparent.window, evt->xreparent.parent,
  1494.         (evt->xreparent.override_redirect ? "(Override)":""));
  1495.     break;
  1496.  
  1497.     case ConfigureNotify:
  1498.     fprintf(stderr, "event 0x%x window 0x%x x %d y %d w %d h %d bw %d above 0x%x\n", evt->xconfigure.event, evt->xconfigure.window, evt->xconfigure.x, evt->xconfigure.y, evt->xconfigure.width, evt->xconfigure.height, evt->xconfigure.border_width, evt->xconfigure.above);
  1499.     break;
  1500.  
  1501.     case ConfigureRequest:
  1502.     fprintf(stderr, "parent 0x%x window 0x%x x %d y %d w %d h %d bw %d above 0x%x detail %d mask %d\n", evt->xconfigurerequest.parent, evt->xconfigurerequest.window, evt->xconfigurerequest.x, evt->xconfigurerequest.y, evt->xconfigurerequest.width, evt->xconfigurerequest.height, evt->xconfigurerequest.border_width, evt->xconfigurerequest.above, evt->xconfigurerequest.detail, evt->xconfigurerequest.value_mask);
  1503.     break;
  1504.  
  1505.     default:
  1506.     fprintf(stderr, "w 0x%x", evt->xany.window);
  1507.     }
  1508.     fputs(end, stderr);    
  1509. }
  1510.  
  1511. #endif /* DEBUG */
  1512.