home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / xmotfevt.cxx < prev    next >
C/C++ Source or Header  |  1995-04-04  |  10KB  |  330 lines

  1.  
  2.  
  3.  
  4. /*
  5.  *
  6.  *          Copyright (C) 1994, M. A. Sridhar
  7.  *  
  8.  *
  9.  *     This software is Copyright M. A. Sridhar, 1994. You are free
  10.  *     to copy, modify or distribute this software  as you see fit,
  11.  *     and to use  it  for  any  purpose, provided   this copyright
  12.  *     notice and the following   disclaimer are included  with all
  13.  *     copies.
  14.  *
  15.  *                        DISCLAIMER
  16.  *
  17.  *     The author makes no warranties, either expressed or implied,
  18.  *     with respect  to  this  software, its  quality, performance,
  19.  *     merchantability, or fitness for any particular purpose. This
  20.  *     software is distributed  AS IS.  The  user of this  software
  21.  *     assumes all risks  as to its quality  and performance. In no
  22.  *     event shall the author be liable for any direct, indirect or
  23.  *     consequential damages, even if the  author has been  advised
  24.  *     as to the possibility of such damages.
  25.  *
  26.  */
  27.  
  28.  
  29. // Support for event translation and handling under X/Motif
  30. #if defined(__GNUC__)
  31. #pragma implementation
  32. #endif
  33.  
  34.  
  35. #include <Xm/BulletinB.h>
  36. #include <Xm/DrawingA.h>
  37. #include <Xm/Xm.h>
  38. #include <X11/StringDefs.h>
  39. #include <X11/Intrinsic.h>
  40. #include <X11/Shell.h>
  41. #include <iostream.h> // DEBUG
  42.  
  43.  
  44.  
  45. #include "ui/cntroler.h"
  46. #include "ui/applic.h"
  47.  
  48. extern XtAppContext _YACLXAppContext; // Declared in cntroler.cxx
  49.  
  50.  
  51. static struct {
  52.     int          message  ;
  53.     UI_EventType yaclEvent;
  54. } TransTable [] = {
  55.     ButtonPress    , Event_LButtonPress  ,
  56.     ButtonRelease  , Event_LButtonRelease,
  57.     MotionNotify   , Event_MouseMove     ,
  58.     KeyPress       , Event_KeyTyped      ,
  59.     KeyRelease     , Event_KeyUp         ,
  60.     EnterNotify    , Event_ViewEnter     ,
  61.     LeaveNotify    , Event_ViewLeave     ,
  62.     FocusIn        , Event_GetFocus      ,
  63.     FocusOut       , Event_LoseFocus     , 
  64.     Expose         , Event_Paint         ,
  65.     GraphicsExpose , Event_GraphicsExpose,
  66.     ConfigureNotify, Event_Reconfigure   ,
  67.     0              , Event_Other         
  68. };
  69.  
  70.  
  71.  
  72. bool UI_Controller::_DoOneEvent (NativeEventStruct& xevent)
  73. {
  74.     XtDispatchEvent (&xevent);
  75.     UI_Event e (Event_None, 0);
  76.     if (TranslateNativeEvent (xevent, e) &&
  77.     (!_eventFilter || _eventFilter->Execute (e, 0)))
  78.         DispatchNativeEvent (e);
  79.     if (_termination && _termination->Execute (e, 0))
  80.     return FALSE;
  81.     DispatchSoftEvents ();
  82.     return TRUE;
  83. }
  84.  
  85. bool UI_Controller::ProcessNativeEvents ()
  86. {
  87.     XEvent xevent;
  88.     while (_root) {
  89.         XtAppNextEvent  (_YACLXAppContext, &xevent);
  90.         if (!_DoOneEvent (xevent))
  91.             return FALSE;
  92.     }
  93.     return TRUE;
  94. }
  95.  
  96.  
  97. void UI_Controller::FlushEventQueue ()
  98. {
  99.     XEvent           xevent;
  100.     while ( XtAppPending (_YACLXAppContext) != 0 ) {
  101.         XtAppNextEvent  (_YACLXAppContext, &xevent);
  102.     }
  103. }
  104.  
  105.  
  106.  
  107. void UI_Controller::DispatchPendingEvents ()
  108. {
  109.     DispatchSoftEvents ();
  110.     XEvent           xevent;
  111.     while ( XtAppPending (_YACLXAppContext) != 0 ) {
  112.         XtAppNextEvent  (_YACLXAppContext, &xevent);
  113.         _DoOneEvent (xevent);
  114.     }
  115.     XmUpdateDisplay (_shell);
  116.     DispatchSoftEvents();
  117. }
  118.  
  119.  
  120. void UI_Controller::XEventHandler (struct _WidgetRec* w, void *,
  121.                                    XEvent* xevent, char *)
  122. {
  123.     if (!xevent)
  124.         return;
  125.     UI_Event e (Event_None, 0);
  126.     UI_Controller& controller = _TheApplication->Controller();
  127.     if (controller.TranslateNativeEvent (*xevent, e)) {
  128.         if (!controller._eventFilter ||
  129.             controller._eventFilter->Execute (e, 0))
  130.             controller.DispatchNativeEvent (e);
  131.     }
  132. }
  133.  
  134.  
  135.  
  136.  
  137. bool UI_Controller::DispatchNativeEvent ( UI_Event& e )
  138. {
  139.     if (!_root)
  140.         return TRUE;
  141.     bool ret_val = TRUE;
  142.     UI_VisualObject* view = e.Origin();
  143.     switch (e.Type ()) {
  144.     case Event_MouseMove:
  145.         ret_val = DispatchEvent (&e);
  146.         break;
  147.  
  148.     case Event_Paint:
  149.         if (view && _uninitedObjs.Includes (view)) {
  150.             _uninitedObjs.Remove (view);
  151.             view->Initialize ();
  152.         }
  153.         ret_val = DispatchEvent (&e);
  154.         break;   
  155.  
  156.     case Event_ViewEnter:
  157.         if (!_inWaitState)
  158.             SetCurrentCursor (e.Destination()->Cursor());
  159.         ret_val = DispatchEvent (&e);
  160.         break;
  161.  
  162.         
  163.     default:
  164.         ret_val = DispatchEvent (&e);
  165.         break;
  166.     }
  167.     return ret_val;
  168. }
  169.  
  170.  
  171.  
  172. bool UI_Controller::TranslateNativeEvent (NativeEventStruct& msg, UI_Event& e)
  173. {
  174.     char keystring [31];
  175.     XComposeStatus composestat;
  176.     KeySym         keysym     ; 
  177.  
  178.     Widget           widget;
  179.     UI_VisualObject *view = 0;
  180.     UI_EventType     type;
  181.  
  182.     e._nativeEvent = new NativeEventStruct;
  183.     *(NativeEventStruct*) (e._nativeEvent) = msg;
  184.  
  185.     XLookupString (&msg.xkey, keystring, 30, &keysym, &composestat);
  186.     e.key = keysym;
  187.  
  188.     e.curPos = UI_Rectangle (msg.xbutton.x, msg.xbutton.y, 0, 0);
  189.  
  190.     for (short i = 0; TransTable[i].message != 0; i++) {
  191.         if ( TransTable [i].message == msg.type ) {
  192.             break;
  193.     }
  194.     }
  195.     e._type = TransTable [i].yaclEvent;
  196.  
  197.     // Now set the destination of the event
  198.     widget = XtWindowToWidget (msg.xany.display, msg.xany.window);
  199.     if ( widget == NULL )
  200.         return FALSE;
  201.  
  202.     // Check the map for the corresponding visual object for the 
  203.     // widget in which the event occured. Due to the way events
  204.     // are handled in X, if the entry is not present for the widget
  205.     // a special case needs to be handled.
  206.     // Since X delivers events from the window manager, like 
  207.     // resizing the main window, to the top level
  208.     // of the application, and the top level of the application is 
  209.     // not registered in the map, any event to the top level window
  210.     // of the application is delivered to the the object in focus; if the
  211.     // latter is NULL, it is delivered to the root composite object.
  212.  
  213.     view = ( UI_VisualObject* ) _visualObjMap [(long) widget];
  214.     if (!view) {
  215.         if (_focus)
  216.             view = _focus;
  217.         else if ( widget == _shell )
  218.             view = _root;
  219.         else
  220.             return FALSE;
  221.     }
  222.  
  223.     e._origin = e._dest = view;
  224.     switch (msg.type) {
  225.     case Expose:
  226.         if (msg.xexpose.count > 0)
  227.             return FALSE;
  228.         break;
  229.         
  230.     case ButtonPress:
  231.         switch (msg.xbutton.button) {
  232.           case Button1: e._type = Event_LButtonPress; break;
  233.           case Button2: e._type = Event_MButtonPress; break;
  234.           case Button3: e._type = Event_RButtonPress; break;
  235.         }
  236.         break;
  237.         
  238.     case ButtonRelease:
  239.         switch (msg.xbutton.button) {
  240.           case Button1: e._type = Event_LButtonRelease; break;
  241.           case Button2: e._type = Event_MButtonRelease; break;
  242.           case Button3: e._type = Event_RButtonRelease; break;
  243.         }
  244.         break;
  245.  
  246.     case ConfigureNotify:
  247.     {
  248.         // We have to resort to the Xt stuff here, because the event
  249.         // structure always gives us (0, 0) for x and y when the window is
  250.         // reshaped at the left or top.
  251.         Position x = msg.xconfigure.x, y = msg.xconfigure.y;
  252.         if (widget) {
  253.             XtVaGetValues (widget, XtNx, &x, XtNy, &y, NULL);
  254.         }
  255.         e.curPos = UI_Rectangle (x, y, msg.xconfigure.width,
  256.                                  msg.xconfigure.height);
  257.         break;
  258.     }
  259.  
  260.     }
  261.     return TRUE;
  262. }
  263.  
  264.  
  265.  
  266. static bool _IsTopWindow (Widget w)
  267. {
  268.     Widget      parentW = XtParent (w);
  269.     return (XtIsTopLevelShell (parentW) || XtIsVendorShell (parentW));
  270. }
  271.  
  272. void UI_Controller::_MakeXInterface (const UI_Event& e)
  273. {
  274.     UI_VisualObject* origin = e.Origin ();
  275.     if (!origin)
  276.         return;
  277.     bool b = origin->MakeVisualElement ();
  278.     if (!b)
  279.         return;
  280.     Register (origin);
  281.     // origin->_created = TRUE; // Another hack to force the initial paint event
  282.     Widget w = origin->_xwidget;
  283.     if (!w)
  284.         return;
  285.     XtRealizeWidget (origin->_xwidget);
  286.     origin->_PrivateInitialize ();
  287.     // The following hack is needed because I don't get expose events for
  288.     // button groups. Don't know why I don't get them.
  289.     // ------------ BEGIN HACK -----------------
  290.     WidgetClass wClass  = XtClass (w);
  291.     Widget      parentW = XtParent (w);
  292.     if (wClass == xmBulletinBoardWidgetClass && _IsTopWindow (w)) 
  293.         _uninitedObjs.Add (origin);
  294.         // The reason for using this set _uninitedObjs is to ensure that
  295.         // a Composite's Initialize is called only after it is visible
  296.         // on the screen, so that graphics operations on it are
  297.         // permissible in the Initialize method.
  298.     else
  299.         origin->Initialize ();
  300.     // ------------- END HACK -----------------
  301. //     if (origin->_visible)
  302. //         XtManageChild (origin->_xwidget);
  303.     ulong mask = PointerMotionMask | FocusChangeMask;
  304.     if (wClass == xmBulletinBoardWidgetClass && !_IsTopWindow (w))
  305.         mask |= ExposureMask;
  306.     // Without ExposureMask, the initial expose event is not sent to a
  307.     // widget that is a child of a composite.
  308.     XtEventHandler p = &UI_Controller::XEventHandler;
  309.     XtAddEventHandler (w, mask, FALSE, p, NULL);
  310. }
  311.  
  312.  
  313. // RegisterTimeOut: register a timeout function with Xt. The return value is
  314. // a handle to the registered function.
  315. ulong UI_Controller::RegisterTimeOut
  316.     (long msec, void (*function) (void*, ulong*), void* client_data)
  317. {
  318.     if (function && msec > 0) // Guard against errors
  319.         return XtAppAddTimeOut (_YACLXAppContext, msec, (XtTimerCallbackProc)
  320.                                 function, client_data);
  321.     else
  322.         return 0;
  323. }
  324.  
  325. void UI_Controller::UnregisterTimeOut (ulong handle)
  326. {
  327.     XtRemoveTimeOut (handle);
  328. }
  329.  
  330.