home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / twm / part02 / events.c next >
Encoding:
C/C++ Source or Header  |  1988-06-12  |  22.6 KB  |  1,003 lines

  1. /*****************************************************************************/
  2. /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
  3. /**                          Salt Lake City, Utah                           **/
  4. /**                                                                         **/
  5. /**                           All Rights Reserved                           **/
  6. /**                                                                         **/
  7. /**    Permission to use, copy, modify, and distribute this software and    **/
  8. /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
  9. /**    granted, provided that the above copyright notice appear  in  all    **/
  10. /**    copies and that both  that  copyright  notice  and  this  permis-    **/
  11. /**    sion  notice appear in supporting  documentation,  and  that  the    **/
  12. /**    name  of Evans & Sutherland  not be used in advertising or publi-    **/
  13. /**    city pertaining to distribution  of the software without  specif-    **/
  14. /**    ic, written prior permission.                                        **/
  15. /**                                                                         **/
  16. /**    EVANS  & SUTHERLAND  DISCLAIMS  ALL  WARRANTIES  WITH  REGARD  TO    **/
  17. /**    THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI-    **/
  18. /**    TY AND FITNESS, IN NO EVENT SHALL EVANS &  SUTHERLAND  BE  LIABLE    **/
  19. /**    FOR  ANY  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY  DAM-    **/
  20. /**    AGES  WHATSOEVER RESULTING FROM  LOSS OF USE,  DATA  OR  PROFITS,    **/
  21. /**    WHETHER   IN  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS    **/
  22. /**    ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE  OR PER-    **/
  23. /**    FORMANCE OF THIS SOFTWARE.                                           **/
  24. /*****************************************************************************/
  25.  
  26. /***********************************************************************
  27.  *
  28.  * $Header: events.c,v 1.31 88/04/15 07:09:47 tlastran Exp $
  29.  *
  30.  * twm event handling
  31.  *
  32.  * 17-Nov-87 Thomas E. LaStrange        File created
  33.  *
  34.  ***********************************************************************/
  35.  
  36. #ifndef lint
  37. static char RCSinfo[]=
  38. "$Header: events.c,v 1.31 88/04/15 07:09:47 tlastran Exp $";
  39. #endif
  40.  
  41. #include <stdio.h>
  42. #include "twm.h"
  43. #include "add_window.h"
  44. #include "menus.h"
  45. #include "events.h"
  46. #include "resize.h"
  47. #include "gram.h"
  48.  
  49. #include "twm.bm"
  50.  
  51. static event_proc EventHandler[LASTEvent]; /* event handler jump table */
  52. static XEvent event;        /* the current event */
  53. static TwmWindow *tmp_win;    /* the current twm window */
  54. static Window w;        /* the window that caused the event */
  55.  
  56. static int ConstMove = FALSE;    /* constrained move variables */
  57. static int ConstMoveDir;
  58. static int ConstMoveX;
  59. static int ConstMoveY;
  60. static int ConstMoveXL;
  61. static int ConstMoveXR;
  62. static int ConstMoveYT;
  63. static int ConstMoveYB;
  64.  
  65. #define MOVE_NONE    0    /* modes of constrained move */
  66. #define MOVE_VERT    1
  67. #define MOVE_HORIZ    2
  68.  
  69. static Window DragWindow;    /* variables used in moving windows */
  70. static int DragX;
  71. static int DragY;
  72. static int DragWidth;
  73. static int DragHeight;
  74. static int enter_flag;
  75.  
  76.  
  77. /***********************************************************************
  78.  *
  79.  *  Procedure:
  80.  *    InitEvents - initialize the event jump table
  81.  *
  82.  ***********************************************************************
  83.  */
  84.  
  85. void
  86. InitEvents()
  87. {
  88.     int i;
  89.  
  90.     ResizeWindow = NULL;
  91.     DragWindow = NULL;
  92.     enter_flag = FALSE;
  93.  
  94.     for (i = 0; i < LASTEvent; i++)
  95.     EventHandler[i] = HandleUnknown;
  96.  
  97.     EventHandler[Expose] = HandleExpose;
  98.     EventHandler[DestroyNotify] = HandleDestroyNotify;
  99.     EventHandler[MapRequest] = HandleMapRequest;
  100.     EventHandler[MapNotify] = HandleMapNotify;
  101.     EventHandler[UnmapNotify] = HandleUnmapNotify;
  102.     EventHandler[MotionNotify] = HandleMotionNotify;
  103.     EventHandler[ButtonRelease] = HandleButtonRelease;
  104.     EventHandler[ButtonPress] = HandleButtonPress;
  105.     EventHandler[EnterNotify] = HandleEnterNotify;
  106.     EventHandler[LeaveNotify] = HandleLeaveNotify;
  107.     EventHandler[ConfigureNotify] = HandleConfigureNotify;
  108.     EventHandler[ClientMessage] = HandleClientMessage;
  109. }
  110.  
  111. /***********************************************************************
  112.  *
  113.  *  Procedure:
  114.  *    HandleEvents - handle X events
  115.  *
  116.  ***********************************************************************
  117.  */
  118.  
  119. void
  120. HandleEvents()
  121. {
  122.     InitEvents();
  123.  
  124.     while (TRUE)
  125.     {
  126.     XNextEvent(dpy, &event);
  127.     w = event.xany.window;
  128.     if (XFindContext(dpy, w, TwmContext, &tmp_win) == XCNOENT)
  129.         tmp_win = NULL;
  130.  
  131. #ifdef DEBUG
  132.     if (event.type != MotionNotify)
  133.     if (tmp_win != NULL)
  134.     {
  135.         fprintf(stderr, "Event w=%x, t->w=%x, t->frame=%x, t->title=%x, ",
  136.         w, tmp_win->w, tmp_win->frame, tmp_win->title_w);
  137.     }
  138.     else
  139.     {
  140.         fprintf(stderr, "Event w=%x, ", w);
  141.     }
  142. #endif
  143.     if (event.type >= 0 && event.type < LASTEvent)
  144.         (*EventHandler[event.type])();
  145.     }
  146. }
  147.  
  148. /***********************************************************************
  149.  *
  150.  *  Procedure:
  151.  *    HandleClientMessage - client message event handler
  152.  *
  153.  ***********************************************************************
  154.  */
  155.  
  156. void
  157. HandleClientMessage()
  158. {
  159. #ifdef DEBUG
  160.     fprintf(stderr, "ClientMessage\n");
  161. #endif
  162.  
  163.     enter_flag = FALSE;
  164. }
  165. /***********************************************************************
  166.  *
  167.  *  Procedure:
  168.  *    HandleExpose - expose event handler
  169.  *
  170.  ***********************************************************************
  171.  */
  172.  
  173. void
  174. HandleExpose()
  175. {
  176.     MenuItem *tmp;
  177.  
  178. #ifdef DEBUG
  179.     fprintf(stderr, "Expose %d\n", event.xexpose.count);
  180. #endif
  181.  
  182.     if (event.xexpose.count != 0)
  183.     return;
  184.  
  185.     if (w == VersionWindow)
  186.     {
  187.     XDrawImageString(dpy, VersionWindow, VersionNormalGC,
  188.         twm_width + 10,
  189.         2 + VersionFont->ascent, Version, strlen(Version));
  190.     }
  191.  
  192.     if (tmp_win != NULL)
  193.     {
  194.     if (tmp_win->title_w == w)
  195.     {
  196.         XDrawImageString(dpy, tmp_win->title_w,
  197.         TitleNormalGC,
  198.         TitleBarX, TitleBarY,
  199.         tmp_win->name, strlen(tmp_win->name));
  200.         return;
  201.     }
  202.  
  203.     if (tmp_win->icon_w == w)
  204.     {
  205.         XDrawImageString(dpy, tmp_win->icon_w,
  206.         IconNormalGC,
  207.         tmp_win->icon_x, tmp_win->icon_y,
  208.         tmp_win->icon_name, strlen(tmp_win->icon_name));
  209.         return;
  210.     }
  211.     }
  212.  
  213.     if (XFindContext(dpy, w, MenuContext, &tmp) == 0)
  214.     {
  215.     if (tmp->state)
  216.         XDrawImageString(dpy,w, MenuReverseGC, tmp->y, MenuY,
  217.         tmp->item, strlen(tmp->item));
  218.     else
  219.         XDrawImageString(dpy,w, MenuNormalGC, tmp->y, MenuY,
  220.         tmp->item, strlen(tmp->item));
  221.  
  222.     return;
  223.     }
  224. }
  225.  
  226. /***********************************************************************
  227.  *
  228.  *  Procedure:
  229.  *    HandleDestroyNotify - DestroyNotify event handler
  230.  *
  231.  ***********************************************************************
  232.  */
  233.  
  234. void
  235. HandleDestroyNotify()
  236. {
  237. #ifdef DEBUG
  238.     fprintf(stderr, "DestroyNotify\n");
  239. #endif
  240.     if (tmp_win == NULL)
  241.     return;
  242.  
  243.     if (tmp_win == Focus)
  244.     {
  245.     FocusOnRoot();
  246.     }
  247.     XDeleteContext(dpy, tmp_win->w, TwmContext);
  248.     XDeleteContext(dpy, tmp_win->frame, TwmContext);
  249.     XDeleteContext(dpy, tmp_win->title_w, TwmContext);
  250.     XDeleteContext(dpy, tmp_win->iconify_w, TwmContext);
  251.     XDeleteContext(dpy, tmp_win->resize_w, TwmContext);
  252.     XDeleteContext(dpy, tmp_win->icon_w, TwmContext);
  253.     XDeleteContext(dpy, tmp_win->focus_w, TwmContext);
  254.     XDeleteContext(dpy, tmp_win->hilite_w, TwmContext);
  255.  
  256.     XDestroyWindow(dpy, tmp_win->frame);
  257.     XDestroyWindow(dpy, tmp_win->icon_w);
  258.     tmp_win->prev->next = tmp_win->next;
  259.     if (tmp_win->next != NULL)
  260.     tmp_win->next->prev = tmp_win->prev;
  261.  
  262.     free((char *)tmp_win);
  263. }
  264.  
  265. /***********************************************************************
  266.  *
  267.  *  Procedure:
  268.  *    HandleMapRequest - MapRequest event handler
  269.  *
  270.  ***********************************************************************
  271.  */
  272.  
  273. void
  274. HandleMapRequest()
  275. {
  276.     int stat;
  277.     XWindowChanges xwc;
  278.     unsigned int   xwcm;
  279.  
  280. #ifdef DEBUG
  281.     fprintf(stderr, "MapRequest\n");
  282. #endif
  283.  
  284.     stat = XFindContext(dpy, event.xmaprequest.window, TwmContext, &tmp_win);
  285.     if (stat == XCNOENT)
  286.     tmp_win = NULL;
  287.  
  288.     if (tmp_win == NULL)
  289.     {
  290.     tmp_win = AddWindow(event.xmaprequest.window);
  291.     if (tmp_win->wmhints && (tmp_win->wmhints->flags & StateHint))
  292.     {
  293.         switch (tmp_win->wmhints->initial_state)
  294.         {
  295.         case DontCareState:
  296.         case NormalState:
  297.         case ZoomState:
  298.         case InactiveState:
  299.             XMapWindow(dpy, event.xmaprequest.window);
  300.             XMapRaised(dpy, tmp_win->frame);
  301.             break;
  302.  
  303.         case IconicState:
  304.             xwcm = 0;
  305.             xwcm |= CWX;
  306.             xwcm |= CWY;
  307.  
  308.             xwc.x = 0;
  309.             xwc.y = 0;
  310.  
  311.             if (tmp_win->wmhints->flags & IconPositionHint)
  312.             {
  313.             xwc.x = tmp_win->wmhints->icon_x;
  314.             xwc.y = tmp_win->wmhints->icon_y;
  315.             }
  316.  
  317.             XConfigureWindow(dpy, tmp_win->icon_w, xwcm, &xwc);
  318.             XMapSubwindows(dpy, tmp_win->icon_w);
  319.             XMapRaised(dpy, tmp_win->icon_w);
  320.             tmp_win->iconified = TRUE;
  321.             tmp_win->icon = TRUE;
  322.             break;
  323.         }
  324.     }
  325.     else
  326.     {
  327.         if (!tmp_win->icon)
  328.         {
  329.         XMapWindow(dpy, event.xmaprequest.window);
  330.         XMapRaised(dpy, tmp_win->frame);
  331.         }
  332.     }
  333.     }
  334.     else
  335.     {
  336.     if (!tmp_win->icon)
  337.     {
  338.         XMapWindow(dpy, event.xmaprequest.window);
  339.         XMapRaised(dpy, tmp_win->frame);
  340.     }
  341.     }
  342.     XRaiseWindow(dpy, VersionWindow);
  343. }
  344.  
  345. /***********************************************************************
  346.  *
  347.  *  Procedure:
  348.  *    HandleMapNotify - MapNotify event handler
  349.  *
  350.  ***********************************************************************
  351.  */
  352.  
  353. void
  354. HandleMapNotify()
  355. {
  356. #ifdef DEBUG
  357.     fprintf(stderr, "MapNotify\n");
  358. #endif
  359.     if (tmp_win == NULL)
  360.     return;
  361.  
  362.     XMapSubwindows(dpy, tmp_win->title_w);
  363.     XMapSubwindows(dpy, tmp_win->frame);
  364.     XUnmapWindow(dpy, tmp_win->hilite_w);
  365.  
  366.     if (tmp_win->title_height == 0)
  367.     XUnmapWindow(dpy, tmp_win->title_w);
  368.  
  369.     XMapRaised(dpy, tmp_win->frame);
  370.     tmp_win->mapped = TRUE;
  371.     XRaiseWindow(dpy, VersionWindow);
  372. }
  373.  
  374. /***********************************************************************
  375.  *
  376.  *  Procedure:
  377.  *    HandleUnmapNotify - UnmapNotify event handler
  378.  *
  379.  ***********************************************************************
  380.  */
  381.  
  382. void
  383. HandleUnmapNotify()
  384. {
  385. #ifdef DEBUG
  386.     fprintf(stderr, "UnmapNotify\n");
  387. #endif
  388.     if (tmp_win == NULL)
  389.     return;
  390.  
  391.     XUnmapWindow(dpy, tmp_win->frame);
  392.     tmp_win->mapped = FALSE;
  393. }
  394.  
  395. /***********************************************************************
  396.  *
  397.  *  Procedure:
  398.  *    HandleMotionNotify - MotionNotify event handler
  399.  *
  400.  ***********************************************************************
  401.  */
  402.  
  403. void
  404. HandleMotionNotify()
  405. {
  406. #ifdef DEBUG
  407.     /*
  408.     fprintf(stderr, "MotionNotify\n");
  409.     */
  410. #endif
  411.     /*XUnmapWindow(dpy, VersionWindow);*/
  412.     if (ConstMove)
  413.     {
  414.     switch (ConstMoveDir)
  415.     {
  416.         case MOVE_NONE:
  417.         if (event.xbutton.x_root < ConstMoveXL ||
  418.             event.xbutton.x_root > ConstMoveXR)
  419.             ConstMoveDir = MOVE_HORIZ;
  420.  
  421.         if (event.xbutton.y_root < ConstMoveYT ||
  422.             event.xbutton.y_root > ConstMoveYB)
  423.             ConstMoveDir = MOVE_VERT;
  424.  
  425.         XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild,
  426.             &JunkX, &JunkY, &DragX, &DragY, &JunkMask);
  427.         break;
  428.  
  429.         case MOVE_VERT:
  430.         ConstMoveY = event.xbutton.y_root - DragY - BorderWidth;
  431.         break;
  432.  
  433.         case MOVE_HORIZ:
  434.         ConstMoveX= event.xbutton.x_root - DragX - BorderWidth;
  435.         break;
  436.     }
  437.  
  438.     if (ConstMoveDir != MOVE_NONE)
  439.     {
  440.         MoveOutline(event.xbutton.root,
  441.         ConstMoveX, ConstMoveY,
  442.         DragWidth + 2 * BorderWidth,
  443.         DragHeight + 2 * BorderWidth);
  444.     }
  445.     return;
  446.     }
  447.  
  448.     if (DragWindow != NULL)
  449.     {
  450.     MoveOutline(event.xbutton.root,
  451.         event.xbutton.x_root - DragX - BorderWidth,
  452.         event.xbutton.y_root - DragY - BorderWidth,
  453.         DragWidth + 2 * BorderWidth,
  454.         DragHeight + 2 * BorderWidth);
  455.  
  456.     return;
  457.     }
  458.  
  459.     if (ResizeWindow != NULL)
  460.     {
  461.     XFindContext(dpy, ResizeWindow, TwmContext, &tmp_win);
  462.     DoResize(event, tmp_win);
  463.     }
  464. }
  465.  
  466. /***********************************************************************
  467.  *
  468.  *  Procedure:
  469.  *    HandleButtonRelease - ButtonRelease event handler
  470.  *
  471.  ***********************************************************************
  472.  */
  473.  
  474. void
  475. HandleButtonRelease()
  476. {
  477. #ifdef DEBUG
  478.     fprintf(stderr, "ButtonRelease\n");
  479. #endif
  480.     XUngrabPointer(dpy, CurrentTime);
  481.     XUngrabServer(dpy);
  482.     EventHandler[EnterNotify] = HandleEnterNotify;
  483.     EventHandler[LeaveNotify] = HandleLeaveNotify;
  484.  
  485.     if (DragWindow != NULL)
  486.     {
  487.     XEvent client_event;
  488.     XWindowChanges xwc;
  489.     unsigned int   xwcm;
  490.  
  491.     MoveOutline(event.xbutton.root, 0, 0, 0, 0);
  492.  
  493.     xwcm = 0;
  494.     xwcm |= CWX;
  495.     xwcm |= CWY;
  496.  
  497.     xwc.x = event.xbutton.x_root - DragX - BorderWidth;
  498.     xwc.y = event.xbutton.y_root - DragY - BorderWidth;
  499.  
  500.     if (ConstMove)
  501.     {
  502.         if (ConstMoveDir == MOVE_HORIZ)
  503.         xwc.y = ConstMoveY;
  504.  
  505.         if (ConstMoveDir == MOVE_VERT)
  506.         xwc.x = ConstMoveX;
  507.  
  508.         if (ConstMoveDir == MOVE_NONE)
  509.         {
  510.         xwc.y = ConstMoveY;
  511.         xwc.x = ConstMoveX;
  512.         }
  513.     }
  514.     
  515.     XFindContext(dpy, DragWindow, TwmContext, &tmp_win);
  516.     tmp_win->frame_x = xwc.x;
  517.     tmp_win->frame_y = xwc.y;
  518.  
  519.     XConfigureWindow(dpy, DragWindow, xwcm, &xwc);
  520.     XRaiseWindow(dpy, DragWindow);
  521.     DragWindow = NULL;
  522.     ConstMove = FALSE;
  523.  
  524.     enter_flag = TRUE;
  525.     client_event.type = ClientMessage;
  526.     XSendEvent(dpy, tmp_win->frame, False, 0, &client_event);
  527.  
  528.     return;
  529.     }
  530.  
  531.     if (ResizeWindow != NULL)
  532.     {
  533.     EndResize();
  534.     EventHandler[EnterNotify] = HandleEnterNotify;
  535.     EventHandler[LeaveNotify] = HandleLeaveNotify;
  536.     }
  537.  
  538.     if (w == Root)
  539.     {
  540.     MenuRoot *tmp;
  541.  
  542.     /*
  543.     if (ActiveItem != NULL)
  544.     {
  545.         int i;
  546.  
  547.         for (i = 0; i < 4; i++)
  548.         XFillRectangle(dpy, ActiveItem->w,
  549.             MenuXorGC,0,0,1000, 100);
  550.  
  551.         XFlush();
  552.     }
  553.     */
  554.     for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev)
  555.     {
  556.         XUnmapWindow(dpy, tmp->shadow);
  557.         XUnmapWindow(dpy, tmp->w);
  558.     }
  559.     XFlush(dpy);
  560.     ActiveMenu = NULL;
  561.  
  562.     if (ActiveItem != NULL)
  563.     {
  564.         ActiveItem->state = 0;
  565.         ExecuteFunction(ActiveItem);
  566.         ActiveItem = NULL;
  567.         XUngrabPointer(dpy, CurrentTime);
  568.     }
  569.  
  570.     return;
  571.     }
  572. }
  573.  
  574. /***********************************************************************
  575.  *
  576.  *  Procedure:
  577.  *    HandleButtonPress - ButtonPress event handler
  578.  *
  579.  ***********************************************************************
  580.  */
  581.  
  582. void
  583. HandleButtonPress()
  584. {
  585.  
  586. #ifdef DEBUG
  587.     fprintf(stderr, "ButtonPress\n");
  588. #endif
  589.  
  590.     XUnmapWindow(dpy, VersionWindow);
  591.  
  592.     if (w == Root)
  593.     {
  594.     if (Menu[event.xbutton.button] != NULL)
  595.     {
  596.         XGrabPointer(dpy, Root, True,
  597.         ButtonReleaseMask | ButtonMotionMask,
  598.         GrabModeAsync, GrabModeSync,
  599.         Root, RightArrowCursor, CurrentTime);
  600.  
  601.         PopUpMenu(Menu[event.xbutton.button], 
  602.         event.xbutton.x, event.xbutton.y);
  603.     }
  604.     else if (Item[event.xbutton.button] != NULL)
  605.     {
  606.         ExecuteFunction(Item[event.xbutton.button]);
  607.     }
  608.  
  609.     return;
  610.     }
  611.  
  612.     if (tmp_win == NULL)
  613.     return;
  614.  
  615.     if (w == tmp_win->frame || w == tmp_win->title_w || w == tmp_win->icon_w)
  616.     {
  617.     if (w != tmp_win->icon_w)
  618.         w = tmp_win->frame;
  619.  
  620.     HandleTitleButton(w, tmp_win, event);
  621.  
  622.     return;
  623.     }
  624.  
  625.     if (w == tmp_win->iconify_w)
  626.     {
  627.     if (!tmp_win->iconified)
  628.     {
  629.         XWindowChanges xwc;
  630.         unsigned int   xwcm;
  631.  
  632.         xwcm = 0;
  633.         xwcm |= CWX;
  634.         xwcm |= CWY;
  635.  
  636.         if (tmp_win->wmhints && tmp_win->wmhints->flags & IconPositionHint)
  637.         {
  638.         xwc.x = tmp_win->wmhints->icon_x;
  639.         xwc.y = tmp_win->wmhints->icon_y;
  640.         }
  641.         else
  642.         {
  643.         xwc.x = event.xbutton.x_root - 5;
  644.         xwc.y = event.xbutton.y_root - 5;
  645.         }
  646.  
  647.         XConfigureWindow(dpy, tmp_win->icon_w, xwcm, &xwc);
  648.         tmp_win->iconified = TRUE;
  649.     }
  650.  
  651.     XUnmapWindow(dpy, tmp_win->frame);
  652.     XMapSubwindows(dpy, tmp_win->icon_w);
  653.     XMapRaised(dpy, tmp_win->icon_w);
  654.     if (tmp_win == Focus)
  655.     {
  656.         XSetInputFocus(dpy, Root, RevertToPointerRoot,
  657.         CurrentTime);
  658.         Focus = NULL;
  659.         FocusRoot = TRUE;
  660.     }
  661.     return;
  662.     }
  663.  
  664.     if (w == tmp_win->resize_w)
  665.     {
  666.     EventHandler[EnterNotify] = HandleUnknown;
  667.     EventHandler[LeaveNotify] = HandleUnknown;
  668.     StartResize(event, tmp_win);
  669.     }
  670.  
  671.     if (w == tmp_win->focus_w)
  672.     {
  673.     if (Focus != NULL && Focus != tmp_win)
  674.     {
  675.         XUnmapWindow(dpy, Focus->hilite_w);
  676.     }
  677.     XMapWindow(dpy, tmp_win->hilite_w);
  678.     XSetInputFocus(dpy, tmp_win->w, RevertToPointerRoot,
  679.         CurrentTime);
  680.     FocusRoot = FALSE;
  681.     Focus = tmp_win;
  682.  
  683.     return;
  684.     }
  685. }
  686.  
  687. /***********************************************************************
  688.  *
  689.  *  Procedure:
  690.  *    HandleEnterNotify - EnterNotify event handler
  691.  *
  692.  ***********************************************************************
  693.  */
  694.  
  695. void
  696. HandleEnterNotify()
  697. {
  698.     MenuItem *tmp;
  699.  
  700. #ifdef DEBUG
  701.     fprintf(stderr, "EnterNotify\n");
  702. #endif
  703.  
  704.     if (ActiveMenu == NULL && tmp_win != NULL)
  705.     {
  706.     if (FocusRoot && tmp_win->mapped)
  707.     {
  708.         if (Focus != NULL && Focus != tmp_win)
  709.         XUnmapWindow(dpy, Focus->hilite_w);
  710.  
  711.         XMapWindow(dpy, tmp_win->hilite_w);
  712.         XSetInputFocus(dpy, tmp_win->w, RevertToPointerRoot,
  713.             CurrentTime);
  714.         Focus = tmp_win;
  715.     }
  716.     if (enter_flag == FALSE && tmp_win->auto_raise)
  717.     {
  718.         XEvent client_event;
  719.  
  720.         XRaiseWindow(dpy, tmp_win->frame);
  721.         enter_flag = TRUE;
  722.         client_event.type = ClientMessage;
  723.         XSendEvent(dpy, tmp_win->frame, False, 0, &client_event);
  724.     }
  725.     return;
  726.     }
  727.  
  728.  
  729.     if (XFindContext(dpy, w, MenuContext, &tmp) != 0)
  730.     return;
  731.  
  732.     if (w == tmp->w && tmp->root == ActiveMenu)
  733.     {
  734.     if (ActiveItem != NULL && ActiveItem->state != 0)
  735.     {
  736. #ifdef DEBUG
  737.         fprintf(stderr, "turning off \"%s\"\n", ActiveItem->item);
  738. #endif
  739.         XFillRectangle(dpy, ActiveItem->w,MenuXorGC,0,0,1000, 100);
  740.         if (tmp->pull != NULL)
  741.         XFillRectangle(dpy, ActiveItem->pull, MenuXorGC,0,0,1000, 100);
  742.         ActiveItem->state = 0;
  743.     }
  744.  
  745.     if (tmp->state == 0)
  746.     {
  747. #ifdef DEBUG
  748.         fprintf(stderr, "turning on \"%s\"\n", tmp->item);
  749. #endif
  750.         XFillRectangle(dpy, tmp->w,MenuXorGC,0,0,1000, 100);
  751.         if (tmp->pull)
  752.         XFillRectangle(dpy, tmp->pull, MenuXorGC,0,0,1000, 100);
  753.         tmp->state = 1;
  754.     }
  755.     ActiveItem = tmp;
  756.  
  757.     return;
  758.     }
  759.  
  760.     if (w == tmp->pull && tmp->root == ActiveMenu)
  761.     {
  762.     XGrabServer(dpy);
  763.     PopUpMenu(tmp->sub, event.xcrossing.x_root,
  764.         event.xcrossing.y_root);
  765.     XUngrabServer(dpy);
  766.  
  767.     return;
  768.     }
  769. }
  770.  
  771. /***********************************************************************
  772.  *
  773.  *  Procedure:
  774.  *    HandleLeaveNotify - LeaveNotify event handler
  775.  *
  776.  ***********************************************************************
  777.  */
  778.  
  779. void
  780. HandleLeaveNotify()
  781. {
  782.     MenuItem *tmp;
  783.  
  784. #ifdef DEBUG
  785.     fprintf(stderr, "LeaveNotify\n");
  786. #endif
  787.     if (tmp_win != NULL)
  788.     {
  789.     XUnmapWindow(dpy, VersionWindow);
  790.     if (FocusRoot)
  791.     {
  792.         if (event.xcrossing.detail != NotifyInferior)
  793.         {
  794.         XUnmapWindow(dpy, tmp_win->hilite_w);
  795.         XSetInputFocus(dpy, Root, RevertToPointerRoot,
  796.             CurrentTime);
  797.         Focus = NULL;
  798.         }
  799.     }
  800.     return;
  801.     }
  802.  
  803.     if (XFindContext(dpy, w, MenuContext, &tmp) != 0)
  804.     return;
  805.  
  806.     if (w == tmp->root->w)
  807.     {
  808.     int rootx, rooty, x, y;
  809.     int wx, wy, ww, wh;
  810.  
  811.     /* see if the mouse really left the window
  812.      * or just crossed into a sub-window
  813.      */
  814.  
  815.     XQueryPointer(dpy, w, &JunkRoot,
  816.         &JunkChild, &rootx, &rooty, &x, &y, &JunkMask);
  817.  
  818.     XGetGeometry(dpy, w, &JunkRoot, &wx, &wy,
  819.         &ww, &wh, &JunkBW,
  820.         &JunkDepth);
  821.     
  822.     if (rootx < wx ||
  823.         rootx > (wx + ww) ||
  824.         rooty < wy ||
  825.         rooty > (wy + wh))
  826.     {
  827.         ActiveItem = NULL;
  828.         if (tmp->root->prev != NULL)
  829.         {
  830.         if (ActiveMenu == tmp->root)
  831.         {
  832.             XUnmapWindow(dpy, ActiveMenu->shadow);
  833.             XUnmapWindow(dpy, ActiveMenu->w);
  834.             ActiveMenu = tmp->root->prev;
  835.         }
  836.         }
  837.     }
  838.     return;
  839.     }
  840.  
  841.     if (w == tmp->w);
  842.     {
  843.     if (tmp == ActiveItem)
  844.         ActiveItem = NULL;
  845.  
  846.     if (tmp->state != 0)
  847.     {
  848. #ifdef DEBUG
  849.         fprintf(stderr, "turning off \"%s\"\n", tmp->item);
  850. #endif
  851.         XFillRectangle(dpy, tmp->w,MenuXorGC,0,0,1000, 100);
  852.         if (tmp->pull != NULL)
  853.         XFillRectangle(dpy, tmp->pull, MenuXorGC,0,0,1000, 100);
  854.         tmp->state = 0;
  855.     }
  856.  
  857.     return;
  858.     }
  859. }
  860.  
  861. /***********************************************************************
  862.  *
  863.  *  Procedure:
  864.  *    HandleConfigureNotify - ConfigureNotify event handler
  865.  *
  866.  ***********************************************************************
  867.  */
  868.  
  869. void
  870. HandleConfigureNotify()
  871. {
  872. #ifdef DEBUG
  873.     fprintf(stderr, "ConfigureNotify\n");
  874. #endif
  875.     if (tmp_win == NULL)
  876.     return;
  877.  
  878.     if (event.xconfigure.override_redirect)
  879.     return;
  880.  
  881.     SetupWindow(tmp_win,
  882.     tmp_win->frame_x + event.xconfigure.x,
  883.     tmp_win->frame_y + event.xconfigure.y - TITLE_BAR_HEIGHT - BorderWidth,
  884.     event.xconfigure.width,
  885.     event.xconfigure.height + TITLE_BAR_HEIGHT + BorderWidth);
  886. }
  887.  
  888. /***********************************************************************
  889.  *
  890.  *  Procedure:
  891.  *    HandleUnknown - unknown event handler
  892.  *
  893.  ***********************************************************************
  894.  */
  895.  
  896. void
  897. HandleUnknown()
  898. {
  899. #ifdef DEBUG
  900.     fprintf(stderr, "type = %d\n", event.type);
  901. #endif
  902. }
  903.  
  904. /***********************************************************************
  905.  *
  906.  *  Procedure:
  907.  *    HandleTitleButton - handle a button press event in the title bar
  908.  *
  909.  *  Inputs:
  910.  *    w    - the window effected by the button press
  911.  *    tmp_win    - the TwmWindow structure
  912.  *    event    - the X event structure for the button press
  913.  *
  914.  ***********************************************************************
  915.  */
  916.  
  917. HandleTitleButton(w, tmp_win, event)
  918. Window w;
  919. TwmWindow *tmp_win ;
  920. XEvent event;
  921. {
  922.     static Time last_time = 0;
  923.  
  924.     if (event.xbutton.button > MAX_BUTTONS)
  925.     return;
  926.  
  927.     switch (TitleButton[event.xbutton.button])
  928.     {
  929.     case T_NOP:
  930.     break;
  931.      
  932.     case T_RAISE:
  933.     if (w == tmp_win->icon_w)
  934.     {
  935.         XUnmapWindow(dpy, tmp_win->icon_w);
  936.         XMapWindow(dpy, tmp_win->w);
  937.         XMapRaised(dpy, tmp_win->frame);
  938.         if (WarpCursor)
  939.         {
  940.         XWarpPointer(dpy, None, tmp_win->frame,
  941.             0, 0, 0, 0, 30, 8);
  942.         }
  943.         tmp_win->icon = FALSE;
  944.     }
  945.     else
  946.         XRaiseWindow(dpy, tmp_win->frame);
  947.     break;
  948.  
  949.     case T_LOWER:
  950.     XLowerWindow(dpy, w);
  951.     break;
  952.  
  953.     case T_MOVE:
  954.     EventHandler[EnterNotify] = HandleUnknown;
  955.     EventHandler[LeaveNotify] = HandleUnknown;
  956.     XGrabServer(dpy);
  957.     XGrabPointer(dpy, event.xbutton.root, True,
  958.         ButtonReleaseMask | ButtonMotionMask,
  959.         GrabModeAsync, GrabModeSync,
  960.         Root, MoveCursor, CurrentTime);
  961.  
  962.     DragWindow = w;
  963.  
  964.     DragX = event.xbutton.x;
  965.     DragY = event.xbutton.y;
  966.  
  967.     XGetGeometry(dpy, w, &JunkRoot, &JunkX, &JunkY,
  968.         &DragWidth, &DragHeight, &JunkBW,
  969.         &JunkDepth);
  970.  
  971.     MoveOutline((Window)event.xbutton.root,
  972.         event.xbutton.x_root-DragX-BorderWidth,
  973.         event.xbutton.y_root-DragY-BorderWidth,
  974.         DragWidth + 2 * BorderWidth,
  975.         DragHeight + 2 * BorderWidth);
  976.  
  977.     if ((event.xbutton.time - last_time) < 400)
  978.     {
  979.         int width, height;
  980.  
  981.         ConstMove = TRUE;
  982.         ConstMoveDir = MOVE_NONE;
  983.         ConstMoveX = event.xbutton.x_root - DragX - BorderWidth;
  984.         ConstMoveY = event.xbutton.y_root - DragY - BorderWidth;
  985.         width = DragWidth + 2 * BorderWidth;
  986.         height = DragHeight + 2 * BorderWidth;
  987.         ConstMoveXL = ConstMoveX + width/3;
  988.         ConstMoveXR = ConstMoveX + 2*(width/3);
  989.         ConstMoveYT = ConstMoveY + height/3;
  990.         ConstMoveYB = ConstMoveY + 2*(height/3);
  991.  
  992.         XWarpPointer(dpy, None, w,
  993.         0, 0, 0, 0, DragWidth/2, DragHeight/2);
  994.  
  995.         XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild,
  996.         &JunkX, &JunkY, &DragX, &DragY, &JunkMask);
  997.     }
  998.     last_time = event.xbutton.time;
  999.     break;
  1000.  
  1001.     }
  1002. }
  1003.