new event decomposition code.
authorClaus Gittinger <cg@exept.de>
Tue, 11 Jul 2000 15:40:18 +0200
changeset 3230 e6e06f7b7df4
parent 3229 e83490cc4472
child 3231 b7fc5adc9404
new event decomposition code.
XWorkstation.st
--- a/XWorkstation.st	Mon Jul 10 18:50:02 2000 +0200
+++ b/XWorkstation.st	Tue Jul 11 15:40:18 2000 +0200
@@ -4333,19 +4333,61 @@
 
 !XWorkstation methodsFor:'event forwarding'!
 
+buttonMotion:view state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a buttonMotion event for some view"
+
+    self buttonMotion:state x:x y:y view:view
+!
+
+buttonPress:view button:button state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a buttonPress event for some view"
+
+    |logicalButton nextMultiClickTime|
+
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+
+    "/ physical to logical button translation
+    logicalButton := buttonTranslation at:button ifAbsent:button.
+    buttonsPressed := buttonsPressed bitOr:(1 bitShift:logicalButton-1).
+
+    multiClickTimeDelta notNil ifTrue:[
+        nextMultiClickTime := time + multiClickTimeDelta.
+        multiClickTime notNil ifTrue:[
+            time < multiClickTime ifTrue:[
+                multiClickTime := nextMultiClickTime.
+                self buttonMultiPress:logicalButton x:x y:y view:view.
+                ^ self.
+            ]
+        ].
+        multiClickTime := nextMultiClickTime.
+    ].
+
+    self buttonPress:logicalButton x:x y:y view:view
+!
+
 buttonPress:button x:x y:y view:aView
     "forward a button-press event for some view"
 
+    aView isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
     button == 1 ifTrue:[
-	activateOnClick == true ifTrue:[
-	    "/ dont raise above an active popup view.
-	    (activeKeyboardGrab isNil and:[activePointerGrab isNil]) ifTrue:[
-		aView topView raise.
+        activateOnClick == true ifTrue:[
+            "/ dont raise above an active popup view.
+            (activeKeyboardGrab isNil and:[activePointerGrab isNil]) ifTrue:[
+                aView topView raise.
 "/            ] ifFalse:[
 "/                activeKeyboardGrab printCR.
 "/                activePointerGrab printCR.
-	    ]
-	].
+            ]
+        ].
     ].
     super buttonPress:button x:x y:y view:aView
 
@@ -4353,6 +4395,27 @@
 
 !
 
+buttonRelease:view button:button state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a buttonPress event for some view"
+
+    |logicalButton|
+
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+
+    "/ physical to logical button translation
+    logicalButton := buttonTranslation at:button ifAbsent:button.
+
+    buttonsPressed := buttonsPressed bitClear:(1 bitShift:logicalButton-1).
+
+    self buttonRelease:logicalButton x:x y:y view:view
+!
+
 circulateNotifyView:aView
     "sent, when the stacking order changes.
      ignored for now."
@@ -4400,9 +4463,19 @@
     "sent, when another colormap is installed.
      This is a very X-specific mechanism."
 
+    aView isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
     aView colorMapChange
 !
 
+configure:view x:x y:y width:w height:h above:above
+    "forward a size-change event for some view"
+
+    self configureX:x y:y width:w height:h view:view
+!
+
 configureRequestView:aView
     "ignored for now"
 
@@ -4525,22 +4598,126 @@
     "Modified: 6.4.1997 / 14:50:44 / cg"
 !
 
+expose:view x:x y:y width:w height:h count:count
+    "forward an expose event for some view"
+
+    self exposeX:x y:y width:w height:h view:view.
+
+
+
+
+!
+
+focusIn:view mode:mode detail:detail
+    "forward a key-press event for some view"
+
+    self focusInView:view
+!
+
+focusOut:view mode:mode detail:detail
+    "forward a key-press event for some view"
+
+    self focusOutView:view
+!
+
+graphicsExpose:view x:x y:y width:w height:h count:count
+    "forward a graphics-expose event for some view"
+
+    self graphicsExposeX:x y:y width:w height:h final:(count==0) view:view
+
+
+
+
+!
+
 gravityNotifyView:aView
     "ignored for now"
 
     "/ aView gravityNotify
 !
 
+keyPress:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a key-press event for some view"
+
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    key isNil ifTrue:[
+        "/ happens sometimes on some systems
+        "/ (alt-graph on sun has no keysym) 
+        ^ self
+    ].
+    eventRootX := rX.
+    eventRootY := rY.
+    self keyPress:key x:x y:y view:view.
+
+
+!
+
+keyRelease:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a key-release event for some view"
+
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    key isNil ifTrue:[
+        "/ happens sometimes on some systems
+        "/ (alt-graph on sun has no keysym) 
+        ^ self
+    ].
+    eventRootX := rX.
+    eventRootY := rY.
+    self keyRelease:key x:x y:y view:view.
+
+
+
+
+!
+
 mapRequestView:aView
     "ignored for now"
 
     "/ aView mapRequest
 !
 
+pointerEnter:view x:x y:y rootX:rX rootY:rY state:state mode:mode detail:detail time:time
+    "forward a pointer enter event for some view"
+
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+    self pointerEnter:state x:x y:y view:view
+!
+
+pointerLeave:view x:x y:y rootX:rX rootY:rY state:state mode:mode detail:detail time:time
+    "forward a pointer leave event for some view"
+
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+    self pointerLeave:state view:view
+!
+
 propertyChangeView:aView
     "sent when an X property changes.
      This is a very X-specific mechanism."
 
+    aView isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
     aView propertyChange
 !
 
@@ -4686,6 +4863,451 @@
 
 !XWorkstation methodsFor:'event handling'!
 
+decomposeLastEventInto:eventArr
+    "extracet event fields and place them into an array:
+     the fields are:
+        1:      windowID
+        2:      eventType-ID
+        3:      eventTypeSymbol
+
+        4..     args
+    "
+%{ 
+#   define ANYBUTTON   (Button1MotionMask | Button2MotionMask | Button3MotionMask)
+
+    OBJ eB;
+    XEvent *ev;
+    int ev_x, ev_y;
+
+#   define ae ((XAnyEvent *)ev)
+#   define ee ((XExposeEvent *)ev)
+#   define ke ((XKeyPressedEvent *)ev)
+#   define be ((XButtonPressedEvent *)ev)
+#   define ce ((XConfigureEvent *)ev)
+#   define cr ((XConfigureRequestEvent *)ev)
+#   define me ((XMotionEvent *)ev)
+#   define ele ((XCrossingEvent *)ev)
+#   define de ((XDestroyWindowEvent *)ev)
+#   define ve ((XVisibilityEvent *)ev)
+#   define fe ((XFocusChangeEvent *)ev)
+#   define cre ((XCreateWindowEvent *)ev)
+#   define mape ((XMappingEvent *)ev)
+#   define gre ((XGravityEvent *)ev)
+#   define rr ((XResizeRequestEvent *)ev)
+#   define cie ((XCirculateEvent *)ev)
+#   define pe ((XPropertyEvent *)ev)
+#   define sce ((XSelectionClearEvent *)ev)
+#   define cme ((XColormapEvent *)ev)
+
+    KeySym keySym;
+    unsigned char buffer[10];
+    int i, nchars;
+    char *keySymString;
+    char keySymStringBuffer[32];
+    unsigned INT nextMultiClickTime;
+    OBJ arg, sym, t, windowID;
+
+    eB = __INST(eventBuffer);
+
+    if (__isByteArray(eB)) {
+        ev = (XEvent *)(__ByteArrayInstPtr(eB)->ba_element);
+    } else {
+        printf("DISPLAY: no eventBuffer\n");
+        RETURN (false);
+    }
+    if (!__isArray(eventArr)) {
+        printf("DISPLAY: bad argument\n");
+        RETURN (false);
+    }
+    if (__arraySize(eventArr) < 11) {
+        printf("DISPLAY: bad argument\n");
+        RETURN (false);
+    }
+
+    if (((t = __INST(lastId)) != nil)
+     && __isExternalAddress(t)
+     && (_WindowVal(t) == ae->window)) {
+        windowID = t;
+    } else {
+        windowID = __MKEXTERNALADDRESS(ae->window);
+    }
+
+    __ArrayInstPtr(eventArr)->a_element[0] = windowID; __STORE(eventArr, windowID);
+    __ArrayInstPtr(eventArr)->a_element[1] = __MKSMALLINT(ev->type);
+
+    switch (ev->type) {
+        case KeyRelease:
+            sym = @symbol(keyRelease:key:code:state:x:y:rootX:rootY:time:);
+            goto keyPressAndRelease;
+
+        case KeyPress:
+            sym = @symbol(keyPress:key:code:state:x:y:rootX:rootY:time:);
+            /* FALL INTO */
+
+        keyPressAndRelease:
+            arg = nil;
+            nchars = XLookupString(ke, (char *)buffer, sizeof(buffer), &keySym, NULL);
+            if (nchars 
+             && (((buffer[0] >= ' ') && (buffer[0] <= '~'))
+                 || (buffer[0] >= 0x80))) {
+                arg = _MKCHARACTER(buffer[0])/* *_CharacterTable[buffer[0]] */;
+                keySymString = NULL;
+            } else {
+                keySymString = XKeysymToString(keySym);
+                if (keySymString) {
+                    arg = __MKSTRING(keySymString);
+                }
+            }
+
+            if (arg == nil) {
+                /* happens sometimes (alt-graph on sun has no keysym) */
+                RETURN (false);
+            }
+
+            __ArrayInstPtr(eventArr)->a_element[2] = sym;
+
+            __ArrayInstPtr(eventArr)->a_element[3] = arg; __STORE(eventArr, arg);
+            __ArrayInstPtr(eventArr)->a_element[4] = t = __MKUINT(ke->keycode); __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(ke->state);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(ke->x);
+            __ArrayInstPtr(eventArr)->a_element[7] = __mkSmallInteger(ke->y);
+            __ArrayInstPtr(eventArr)->a_element[8] = __mkSmallInteger(ke->x_root);
+            __ArrayInstPtr(eventArr)->a_element[9] = __mkSmallInteger(ke->y_root);
+            __ArrayInstPtr(eventArr)->a_element[10] = t = __MKUINT(ke->time); __STORE(eventArr, t);
+            RETURN (true);
+
+        case ButtonPress:
+            sym = @symbol(buttonPress:button:state:x:y:rootX:rootY:time:);
+            goto buttonPressAndRelease;
+
+        case ButtonRelease:
+            sym = @symbol(buttonRelease:button:state:x:y:rootX:rootY:time:);
+            /* fall into */
+
+        buttonPressAndRelease:
+            __ArrayInstPtr(eventArr)->a_element[2] = sym;
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(be->button);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(ke->state);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(be->x);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(be->y);
+            __ArrayInstPtr(eventArr)->a_element[7] = __mkSmallInteger(be->x_root);
+            __ArrayInstPtr(eventArr)->a_element[8] = __mkSmallInteger(be->y_root);
+            __ArrayInstPtr(eventArr)->a_element[9] = t = __MKUINT(be->time); __STORE(eventArr, t);
+            RETURN (true);
+
+        case MotionNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(buttonMotion:state:x:y:rootX:rootY:time:);
+
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(me->state);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(me->x);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(me->y);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(me->x_root);
+            __ArrayInstPtr(eventArr)->a_element[7] = __mkSmallInteger(me->y_root);
+            __ArrayInstPtr(eventArr)->a_element[8] = t = __MKUINT(me->time); __STORE(eventArr, t);
+            RETURN (true);
+
+        case FocusIn:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(focusIn:mode:detail:);
+            goto focusInOut;
+
+        case FocusOut:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(focusOut:mode:detail:);
+            /* fall into */
+
+        focusInOut:
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(fe->mode);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(fe->detail);
+            RETURN (true);
+
+
+        case EnterNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(pointerEnter:x:y:rootX:rootY:state:mode:detail:time:);
+            goto enterLeave;
+
+        case LeaveNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(pointerLeave:x:y:rootX:rootY:state:mode:detail:time:);
+            /* fall into */
+
+        enterLeave:
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(ele->x);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(ele->y);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(ele->x_root);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(ele->y_root);
+            __ArrayInstPtr(eventArr)->a_element[7] = __mkSmallInteger(ele->state);
+            __ArrayInstPtr(eventArr)->a_element[8] = __mkSmallInteger(ele->mode);
+            __ArrayInstPtr(eventArr)->a_element[9] = __mkSmallInteger(ele->detail);
+            __ArrayInstPtr(eventArr)->a_element[10] = t = __MKUINT(ele->time); __STORE(eventArr, t);
+            RETURN (true);
+
+        case Expose:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(expose:x:y:width:height:count:);
+            goto expose;
+
+        case GraphicsExpose:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(graphicsExpose:x:y:width:height:count:);
+            /* fall into */
+
+        expose:
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(ee->x);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(ee->y);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(ee->width);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(ee->height);
+            __ArrayInstPtr(eventArr)->a_element[7] = __mkSmallInteger(ee->count);
+            RETURN (true);
+
+        case NoExpose:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(noExposeView:);
+            RETURN (true);
+
+        case VisibilityNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(visibilityNotify:state:);
+            switch (ve->state) {
+                case VisibilityUnobscured:
+                    __ArrayInstPtr(eventArr)->a_element[3] = @symbol(unobscured);
+                    break;
+                case VisibilityPartiallyObscured:
+                    __ArrayInstPtr(eventArr)->a_element[3] = @symbol(partiallyObscured);
+                    break;
+                case VisibilityFullyObscured:
+                    __ArrayInstPtr(eventArr)->a_element[3] = @symbol(fullyObscured);
+                    break;
+            }
+            RETURN (true);
+
+        case CreateNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(createWindow:x:y:width:height:);
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(cre->x);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(cre->y);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(cre->width);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(cre->height);
+            RETURN (true);
+
+        case DestroyNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(destroyedView:);
+            RETURN (true);
+
+        case UnmapNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(unmappedView:);
+            RETURN (true);
+
+        case MapNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(mappedView:);
+            RETURN (true);
+
+        case ConfigureNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(configure:x:y:width:height:above:);
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(ce->x);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(ce->y);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(ce->width);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(ce->height);
+            __ArrayInstPtr(eventArr)->a_element[7] = nil;
+            if (ce->above != None) {
+                __ArrayInstPtr(eventArr)->a_element[8] = t = __MKEXTERNALADDRESS(ce->above); __STORE(eventArr, t);
+            }
+            RETURN (true);
+
+        case GravityNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(gravityNotify:x:y:);
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(gre->x);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(gre->y);
+            RETURN (true);
+            break;
+
+        case ResizeRequest:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(resizeRequest:width:height:);
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(rr->width);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(rr->height);
+            RETURN (true);
+            break;
+
+        case ConfigureRequest:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(configureRequest:x:y:width:height:above:detail:);
+            __ArrayInstPtr(eventArr)->a_element[3] = __mkSmallInteger(cr->x);
+            __ArrayInstPtr(eventArr)->a_element[4] = __mkSmallInteger(cr->y);
+            __ArrayInstPtr(eventArr)->a_element[5] = __mkSmallInteger(cr->width);
+            __ArrayInstPtr(eventArr)->a_element[6] = __mkSmallInteger(cr->height);
+            __ArrayInstPtr(eventArr)->a_element[7] = nil;
+            if (cr->above != None) {
+                __ArrayInstPtr(eventArr)->a_element[7] = t = __MKEXTERNALADDRESS(cr->above); __STORE(eventArr, t);
+            }
+            switch (cr->detail) {
+                case Above:
+                    __ArrayInstPtr(eventArr)->a_element[8] = @symbol(above);
+                    break;
+                case Below:
+                    __ArrayInstPtr(eventArr)->a_element[8] = @symbol(below);
+                    break;
+                case TopIf:
+                    __ArrayInstPtr(eventArr)->a_element[8] = @symbol(topIf);
+                    break;
+                case BottomIf:
+                    __ArrayInstPtr(eventArr)->a_element[8] = @symbol(bottomIf);
+                    break;
+                case Opposite:
+                    __ArrayInstPtr(eventArr)->a_element[8] = @symbol(opposite);
+                    break;
+                default:
+                    __ArrayInstPtr(eventArr)->a_element[8] = nil;
+                    break;
+            }
+            RETURN (true);
+            break;
+
+        case CirculateNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(circulateNotify:place:);
+            goto circulate;
+
+        case CirculateRequest:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(circulateNotify:place:);
+            /* fall into */
+        circulate:
+            switch (cie->place) {
+                case PlaceOnTop:
+                    __ArrayInstPtr(eventArr)->a_element[3] = @symbol(placeOnTop);
+                    break;
+                case PlaceOnBottom:
+                    __ArrayInstPtr(eventArr)->a_element[3] = @symbol(placeOnBottom);
+                    break;
+                default:
+                    __ArrayInstPtr(eventArr)->a_element[3] = nil;
+                    break;
+            }
+            RETURN (true);
+            break;
+
+        case PropertyNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(propertyChange:atom:state:time:);
+            __ArrayInstPtr(eventArr)->a_element[3] = t = __MKUINT(pe->atom); __STORE(eventArr, t);
+            switch (pe->state) {
+                case PropertyNewValue:
+                    __ArrayInstPtr(eventArr)->a_element[4] = @symbol(newValue);
+                    break;
+                case PropertyDelete:
+                    __ArrayInstPtr(eventArr)->a_element[4] = @symbol(deleted);
+                    break;
+                default:
+                    __ArrayInstPtr(eventArr)->a_element[4] = nil;
+                    break;
+            }
+            __ArrayInstPtr(eventArr)->a_element[3] = t = __MKUINT(pe->time); __STORE(eventArr, t);
+            RETURN (true);
+            break;
+
+        case SelectionClear:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(propertyChange:atom:time:);
+            __ArrayInstPtr(eventArr)->a_element[3] = t = __MKUINT(sce->selection); __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[4] = t = __MKUINT(sce->time);      __STORE(eventArr, t);
+            RETURN (true);
+            break;
+
+        case SelectionRequest:
+            /*
+             * someone wants the selection
+             */
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(selectionRequest:requestor:selection:target:property:time:);
+            __ArrayInstPtr(eventArr)->a_element[3] = t = __MKUINT(ev->xselectionrequest.requestor); __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[4] = t = __MKUINT(ev->xselectionrequest.selection); __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[5] = t = __MKUINT(ev->xselectionrequest.target);    __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[6] = t = __MKUINT(ev->xselectionrequest.property);  __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[7] = t = __MKUINT(ev->xselectionrequest.time);      __STORE(eventArr, t);
+            RETURN (true);
+
+        case SelectionNotify:
+            /*
+             * returned selection value (answer from SelectionRequest)
+             */
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(selectionNotify:selection:target:property:time:);
+            __ArrayInstPtr(eventArr)->a_element[3] = t = __MKUINT(ev->xselectionrequest.selection); __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[4] = t = __MKUINT(ev->xselectionrequest.target);    __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[5] = t = __MKUINT(ev->xselectionrequest.property);  __STORE(eventArr, t);
+            __ArrayInstPtr(eventArr)->a_element[6] = t = __MKUINT(ev->xselectionrequest.time);      __STORE(eventArr, t);
+            RETURN (true);
+
+        case ColormapNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(colormapNotify:state:);
+            __ArrayInstPtr(eventArr)->a_element[3] = cme->state == ColormapInstalled ? true : false;
+            RETURN (true);
+            break;
+
+        case ClientMessage:
+            if (ev->xclient.message_type == (int) _AtomVal(__INST(protocolsAtom))) {
+                if ((ev->xclient.data.l[0] == (int) _AtomVal(__INST(quitAppAtom)))
+                 || (ev->xclient.data.l[0] == (int) _AtomVal(__INST(deleteWindowAtom)))) {
+                    __ArrayInstPtr(eventArr)->a_element[2] = @symbol(terminateView:);
+                    RETURN (true);
+                }
+                if (ev->xclient.data.l[0] == (int) _AtomVal(__INST(saveYourselfAtom))) {
+                    __ArrayInstPtr(eventArr)->a_element[2] = @symbol(saveAndTerminateView:);
+                    RETURN (true);
+                }
+            }
+            /*
+             * any other client message
+             */
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(clientMessage:type:format:data:);
+            __ArrayInstPtr(eventArr)->a_element[3] = __MKSMALLINT(ev->xclient.message_type);
+            __ArrayInstPtr(eventArr)->a_element[4] = __MKSMALLINT(ev->xclient.format);
+            __ArrayInstPtr(eventArr)->a_element[5] = t = __MKBYTEARRAY(ev->xclient.data, sizeof(ev->xclient.data)); __STORE(eventArr, t);
+            RETURN (true);
+            break;
+
+        case MappingNotify:
+            switch(mape->request) {
+                case MappingModifier:
+                    __ArrayInstPtr(eventArr)->a_element[2] = @symbol(mappingModifier:);
+                    break;
+                case MappingKeyboard:
+                    __ArrayInstPtr(eventArr)->a_element[2] = @symbol(mappingKeyboard:);
+                    break;
+                case MappingPointer:
+                    __ArrayInstPtr(eventArr)->a_element[2] = @symbol(mappingPointer:);
+                    break;
+                default:
+                    arg = nil;
+                    break;
+            }
+            RETURN (true);
+
+        case KeymapNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(keymapNotify:);
+            RETURN (true);
+            break;
+
+        case MapRequest:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(mapRequest:);
+            RETURN (true);
+
+        case ReparentNotify:
+            __ArrayInstPtr(eventArr)->a_element[2] = @symbol(reparentedView:);
+            break;
+
+
+    }
+#undef ae
+#undef ee
+#undef ke
+#undef be
+#undef ce
+#undef cr
+#undef cre
+#undef cle
+#undef gre
+#undef me
+#undef ewe
+#undef ele
+#undef lwe
+#undef de
+#undef mape
+#undef ve
+#undef fe
+#undef rr
+#undef pe
+#undef sce
+#undef cme
+%}.
+    ^ true
+!
+
 defaultEventMask
     "return a mask to enable some events by default."
 
@@ -4706,14 +5328,14 @@
      If the argument aMask is nonNil, only events for this eventMask are
      handled.
      WARNING: this may block to wait for an event - you better check for a 
-	      pending event before calling this."
+              pending event before calling this."
 
     (self getEventFor:aViewIdOrNil withMask:eventMask) ifTrue:[
-	AbortSignal handle:[:ex |
-	    ex return
-	] do:[
-	    self dispatchLastEvent.
-	]
+        AbortSignal handle:[:ex |
+            ex return
+        ] do:[
+            self newDispatchLastEvent.
+        ]
     ].
 
     "Modified: 19.8.1997 / 17:10:42 / cg"
@@ -5399,6 +6021,34 @@
     ^ true
 !
 
+dispatchLastEvent:evArray
+    |viewId view evTypeNr evType arguments|
+
+    viewId := evArray at:1.
+    viewId notNil ifTrue:[
+        viewId = lastId ifTrue:[
+            view := lastView
+        ] ifFalse:[
+            view := self viewFromId:viewId
+        ].
+    ].
+
+    evType := evArray at:3.
+
+    (self respondsTo:evType) ifTrue:[
+        arguments := evArray copyFrom:3 to:(3 + evType numArgs - 1).
+        arguments at:1 put:view.
+
+        self perform:evType withArguments:arguments.
+        ^ true.
+    ].
+'********** unhandled event:' errorPrintCR.
+evType errorPrintCR.
+'********** see newDispatchLastEvent' errorPrintCR.
+    ^ false
+
+!
+
 dispatchPendingEvents
     "central event handling method for modal operation.
      (i.e. this is now only used in the modal debugger)
@@ -5410,20 +6060,20 @@
 
     "interested in exposes only ?"
     dispatchingExpose notNil ifTrue:[
-	[self exposeEventPendingFor:dispatchingExpose withSync:false] whileTrue:[
-	    self dispatchExposeEventFor:dispatchingExpose
-	].
-	^ self
+        [self exposeEventPendingFor:dispatchingExpose withSync:false] whileTrue:[
+            self dispatchExposeEventFor:dispatchingExpose
+        ].
+        ^ self
     ].
 
     [self eventPendingWithSync:false] whileTrue:[
-	(self getEventFor:nil withMask:nil) ifTrue:[
-	    AbortSignal handle:[:ex |
-		ex return
-	    ] do:[
-		self dispatchLastEvent
-	    ]
-	].
+        (self getEventFor:nil withMask:nil) ifTrue:[
+            AbortSignal handle:[:ex |
+                ex return
+            ] do:[
+                self newDispatchLastEvent
+            ]
+        ].
     ]
 
     "Modified: 19.8.1997 / 17:11:18 / cg"
@@ -5733,6 +6383,16 @@
     "Created: 1.12.1995 / 16:28:23 / stefan"
 !
 
+newDispatchLastEvent
+    |arr|
+
+    arr := Array new:13.
+    self decomposeLastEventInto:arr.
+    (self dispatchLastEvent:arr) ifFalse:[
+        self dispatchLastEvent
+    ]
+!
+
 setEventMask:aMask in:aWindowId
     "tell X that we are only interested in events from aMask, which
      is the bitwise or of the eventMask bits (see 'eventMaskFor:')"
@@ -8208,6 +8868,14 @@
     altModifierMask := aSmallInteger
 !
 
+ctrlModifierMask
+    "return the Xlib mask bit for the control modifier key"
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(ControlMask));
+%}
+!
+
 metaModifierMask
     "return the mask (in motionEvents) for the meta-key modifier.
      Notice: ST/X may use the left ALT key as CMD/Meta key,
@@ -8320,6 +8988,14 @@
     "
 !
 
+shiftModifierMask
+    "return the Xlib mask bit for the shift modifier key"
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(ShiftMask));
+%}
+!
+
 stringFromKeycode:code
     "Get a KeySymbol (a smalltalk symbol) from the keycode."
 
@@ -10548,6 +11224,6 @@
 !XWorkstation class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.360 2000-07-10 16:50:02 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.361 2000-07-11 13:40:18 cg Exp $'
 ! !
 XWorkstation initialize!