home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
xmotfevt.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-04
|
10KB
|
330 lines
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
// Support for event translation and handling under X/Motif
#if defined(__GNUC__)
#pragma implementation
#endif
#include <Xm/BulletinB.h>
#include <Xm/DrawingA.h>
#include <Xm/Xm.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <iostream.h> // DEBUG
#include "ui/cntroler.h"
#include "ui/applic.h"
extern XtAppContext _YACLXAppContext; // Declared in cntroler.cxx
static struct {
int message ;
UI_EventType yaclEvent;
} TransTable [] = {
ButtonPress , Event_LButtonPress ,
ButtonRelease , Event_LButtonRelease,
MotionNotify , Event_MouseMove ,
KeyPress , Event_KeyTyped ,
KeyRelease , Event_KeyUp ,
EnterNotify , Event_ViewEnter ,
LeaveNotify , Event_ViewLeave ,
FocusIn , Event_GetFocus ,
FocusOut , Event_LoseFocus ,
Expose , Event_Paint ,
GraphicsExpose , Event_GraphicsExpose,
ConfigureNotify, Event_Reconfigure ,
0 , Event_Other
};
bool UI_Controller::_DoOneEvent (NativeEventStruct& xevent)
{
XtDispatchEvent (&xevent);
UI_Event e (Event_None, 0);
if (TranslateNativeEvent (xevent, e) &&
(!_eventFilter || _eventFilter->Execute (e, 0)))
DispatchNativeEvent (e);
if (_termination && _termination->Execute (e, 0))
return FALSE;
DispatchSoftEvents ();
return TRUE;
}
bool UI_Controller::ProcessNativeEvents ()
{
XEvent xevent;
while (_root) {
XtAppNextEvent (_YACLXAppContext, &xevent);
if (!_DoOneEvent (xevent))
return FALSE;
}
return TRUE;
}
void UI_Controller::FlushEventQueue ()
{
XEvent xevent;
while ( XtAppPending (_YACLXAppContext) != 0 ) {
XtAppNextEvent (_YACLXAppContext, &xevent);
}
}
void UI_Controller::DispatchPendingEvents ()
{
DispatchSoftEvents ();
XEvent xevent;
while ( XtAppPending (_YACLXAppContext) != 0 ) {
XtAppNextEvent (_YACLXAppContext, &xevent);
_DoOneEvent (xevent);
}
XmUpdateDisplay (_shell);
DispatchSoftEvents();
}
void UI_Controller::XEventHandler (struct _WidgetRec* w, void *,
XEvent* xevent, char *)
{
if (!xevent)
return;
UI_Event e (Event_None, 0);
UI_Controller& controller = _TheApplication->Controller();
if (controller.TranslateNativeEvent (*xevent, e)) {
if (!controller._eventFilter ||
controller._eventFilter->Execute (e, 0))
controller.DispatchNativeEvent (e);
}
}
bool UI_Controller::DispatchNativeEvent ( UI_Event& e )
{
if (!_root)
return TRUE;
bool ret_val = TRUE;
UI_VisualObject* view = e.Origin();
switch (e.Type ()) {
case Event_MouseMove:
ret_val = DispatchEvent (&e);
break;
case Event_Paint:
if (view && _uninitedObjs.Includes (view)) {
_uninitedObjs.Remove (view);
view->Initialize ();
}
ret_val = DispatchEvent (&e);
break;
case Event_ViewEnter:
if (!_inWaitState)
SetCurrentCursor (e.Destination()->Cursor());
ret_val = DispatchEvent (&e);
break;
default:
ret_val = DispatchEvent (&e);
break;
}
return ret_val;
}
bool UI_Controller::TranslateNativeEvent (NativeEventStruct& msg, UI_Event& e)
{
char keystring [31];
XComposeStatus composestat;
KeySym keysym ;
Widget widget;
UI_VisualObject *view = 0;
UI_EventType type;
e._nativeEvent = new NativeEventStruct;
*(NativeEventStruct*) (e._nativeEvent) = msg;
XLookupString (&msg.xkey, keystring, 30, &keysym, &composestat);
e.key = keysym;
e.curPos = UI_Rectangle (msg.xbutton.x, msg.xbutton.y, 0, 0);
for (short i = 0; TransTable[i].message != 0; i++) {
if ( TransTable [i].message == msg.type ) {
break;
}
}
e._type = TransTable [i].yaclEvent;
// Now set the destination of the event
widget = XtWindowToWidget (msg.xany.display, msg.xany.window);
if ( widget == NULL )
return FALSE;
// Check the map for the corresponding visual object for the
// widget in which the event occured. Due to the way events
// are handled in X, if the entry is not present for the widget
// a special case needs to be handled.
// Since X delivers events from the window manager, like
// resizing the main window, to the top level
// of the application, and the top level of the application is
// not registered in the map, any event to the top level window
// of the application is delivered to the the object in focus; if the
// latter is NULL, it is delivered to the root composite object.
view = ( UI_VisualObject* ) _visualObjMap [(long) widget];
if (!view) {
if (_focus)
view = _focus;
else if ( widget == _shell )
view = _root;
else
return FALSE;
}
e._origin = e._dest = view;
switch (msg.type) {
case Expose:
if (msg.xexpose.count > 0)
return FALSE;
break;
case ButtonPress:
switch (msg.xbutton.button) {
case Button1: e._type = Event_LButtonPress; break;
case Button2: e._type = Event_MButtonPress; break;
case Button3: e._type = Event_RButtonPress; break;
}
break;
case ButtonRelease:
switch (msg.xbutton.button) {
case Button1: e._type = Event_LButtonRelease; break;
case Button2: e._type = Event_MButtonRelease; break;
case Button3: e._type = Event_RButtonRelease; break;
}
break;
case ConfigureNotify:
{
// We have to resort to the Xt stuff here, because the event
// structure always gives us (0, 0) for x and y when the window is
// reshaped at the left or top.
Position x = msg.xconfigure.x, y = msg.xconfigure.y;
if (widget) {
XtVaGetValues (widget, XtNx, &x, XtNy, &y, NULL);
}
e.curPos = UI_Rectangle (x, y, msg.xconfigure.width,
msg.xconfigure.height);
break;
}
}
return TRUE;
}
static bool _IsTopWindow (Widget w)
{
Widget parentW = XtParent (w);
return (XtIsTopLevelShell (parentW) || XtIsVendorShell (parentW));
}
void UI_Controller::_MakeXInterface (const UI_Event& e)
{
UI_VisualObject* origin = e.Origin ();
if (!origin)
return;
bool b = origin->MakeVisualElement ();
if (!b)
return;
Register (origin);
// origin->_created = TRUE; // Another hack to force the initial paint event
Widget w = origin->_xwidget;
if (!w)
return;
XtRealizeWidget (origin->_xwidget);
origin->_PrivateInitialize ();
// The following hack is needed because I don't get expose events for
// button groups. Don't know why I don't get them.
// ------------ BEGIN HACK -----------------
WidgetClass wClass = XtClass (w);
Widget parentW = XtParent (w);
if (wClass == xmBulletinBoardWidgetClass && _IsTopWindow (w))
_uninitedObjs.Add (origin);
// The reason for using this set _uninitedObjs is to ensure that
// a Composite's Initialize is called only after it is visible
// on the screen, so that graphics operations on it are
// permissible in the Initialize method.
else
origin->Initialize ();
// ------------- END HACK -----------------
// if (origin->_visible)
// XtManageChild (origin->_xwidget);
ulong mask = PointerMotionMask | FocusChangeMask;
if (wClass == xmBulletinBoardWidgetClass && !_IsTopWindow (w))
mask |= ExposureMask;
// Without ExposureMask, the initial expose event is not sent to a
// widget that is a child of a composite.
XtEventHandler p = &UI_Controller::XEventHandler;
XtAddEventHandler (w, mask, FALSE, p, NULL);
}
// RegisterTimeOut: register a timeout function with Xt. The return value is
// a handle to the registered function.
ulong UI_Controller::RegisterTimeOut
(long msec, void (*function) (void*, ulong*), void* client_data)
{
if (function && msec > 0) // Guard against errors
return XtAppAddTimeOut (_YACLXAppContext, msec, (XtTimerCallbackProc)
function, client_data);
else
return 0;
}
void UI_Controller::UnregisterTimeOut (ulong handle)
{
XtRemoveTimeOut (handle);
}