XWorkstation.st
changeset 382 92200ee9f558
parent 378 5d3c20a3bf7f
child 386 f9a80cac659e
--- a/XWorkstation.st	Fri Jan 26 13:09:47 1996 +0100
+++ b/XWorkstation.st	Fri Jan 26 13:49:01 1996 +0100
@@ -454,6 +454,12 @@
     ^ nil
 !
 
+controlMask
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(ControlMask));
+%}
+!
+
 defaultEventMask
     "return a mask to enable some events by default."
 
@@ -533,6 +539,12 @@
     "
 !
 
+shiftMask
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(ShiftMask));
+%}
+!
+
 translatePoint:aPoint from:windowId1 to:windowId2
     "given a point in window1, return the coordinate in window2.
      This expects a device coordinate (relative to the first views origin)
@@ -2420,7 +2432,7 @@
     }
 fail: ;
     if (mustFree)
-        free(points);
+	free(points);
 %}.
     "badGC, badDrawable or coordinates not integer"
     self primitiveFailed
@@ -2728,8 +2740,8 @@
 	RETURN ( self );
 
 fail: ;
-        if (mustFree)
-            free(points);
+	if (mustFree)
+	    free(points);
     }
 %}.
     "badGC, badDrawable or coordinates not integer"
@@ -2869,6 +2881,178 @@
     ^ false
 ! !
 
+!XWorkstation methodsFor:'event sending'!
+
+simulateKeyboardInput:aCharacterOrString inViewId:viewId
+    "send input to some other view, by simulating keyPress/keyRelease
+     events. Notice: not all alien views allow this kind of synthetic input;
+     some simply ignore it."
+
+    |shifted control code state|
+
+    aCharacterOrString isString ifTrue:[
+	aCharacterOrString do:[:char |
+	    self simulateKeyboardInput:char inViewId:viewId
+	].
+	^ self
+    ].
+
+    shifted := false.
+    control := false.
+    code := aCharacterOrString asciiValue.
+
+    (aCharacterOrString between:$A and:$Z) ifTrue:[
+	"/ shifted
+	shifted := true
+    ] ifFalse:[
+	(aCharacterOrString between:$a and:$z) ifTrue:[
+	    "/ unshifted alpha
+	    code := code - $a asciiValue + $A asciiValue
+	]
+    ].
+
+    shifted ifTrue:[
+	state := self shiftMask
+    ] ifFalse:[
+	state := 0
+    ].
+    control ifTrue:[
+	state := state bitOr:(self controlMask)
+    ].
+
+    self sendKeyEvent:#keyPress x:0 y:0 key:code state:state toViewId:viewId.
+    self sendKeyEvent:#keyRelease x:0 y:0 key:code state:state toViewId:viewId
+
+    "
+      sending input to some (possibly alien) view:
+
+      |point id|
+
+      point :=  Display pointFromUser.
+      id := Display viewIdFromPoint:point.
+      Display simulateKeyboardInput:'hello' inViewId:id
+    "
+!
+
+sendKeyEvent:typeSymbol x:xPos y:yPos key:keySymCode state:stateMask toViewId:targetId
+    "send a keyPress/keyRelease event to some (possibly alien) view.
+     TypeSymbol must be one of: #keyPress / #keyRelease.
+     keySymCode can be either a symbol (as listen in X's keySyms or a numeric keysym)
+     This is the lowlevel entry, where state must include any shift/ctrl information
+     (not very user friendly)"
+
+%{  /* NOCONTEXT */
+    Display *dpy = myDpy;
+    int type;
+
+    if (ISCONNECTED
+     && __isSmallInteger(xPos) && __isSmallInteger(yPos)
+     && __isSmallInteger(keySymCode) && __isSmallInteger(stateMask)
+     && (__isExternalAddress(targetId) || __isInteger(targetId))) {
+	XEvent ev;
+	Window target;
+	Status result;
+	KeySym keySym;
+	int screen = _intVal(_INST(screen));
+
+	ev.xkey.x = __intVal(xPos);
+	ev.xkey.y = __intVal(yPos);
+	if (__isSymbol(keySymCode)) {
+	    keySym = XStringToKeysym(__stringVal(keySymCode));
+	} else {
+	    keySym = (KeySym) __intVal(keySymCode);
+	}
+	ev.xkey.keycode = XKeysymToKeycode(dpy, keySym);
+	ev.xkey.state = __intVal(stateMask);
+	ev.xkey.time = CurrentTime;
+
+	if (typeSymbol == @symbol(keyPress))
+	    ev.xkey.type = KeyPress;
+	else if (typeSymbol == @symbol(keyRelease))
+	    ev.xkey.type = KeyRelease;
+	else {
+	    DPRINTF(("invalid sendEvent typeSymbol\n"));
+	    RETURN (false);
+	}
+
+	if (__isExternalAddress(targetId)) {
+	    target = _WindowVal(targetId);
+	} else {
+	    target = (Window) __longIntVal(targetId);
+	}
+	ev.xkey.window = target;
+	ev.xkey.same_screen = 1;
+	ev.xkey.subwindow = 0;
+	ev.xkey.root = RootWindow(myDpy, screen);
+
+	result = XSendEvent(dpy, target, False, 0 , &ev);
+	if ((result == BadValue) || (result == BadWindow)) {
+	    DPRINTF(("bad status\n"));
+	    RETURN ( false )
+	}
+	RETURN (true)
+    }
+%}.
+    self primitiveFailed.
+    ^ false
+!
+
+sendButtonEvent:typeSymbol x:xPos y:yPos button:buttonNr state:stateMask toViewId:targetId
+    "send a buttonPress/buttonRelease event to some (possibly alien) view.
+     TypeSymbol must be one of: #buttonPress / #buttonRelease.
+     This is the lowlevel entry, where state must include any shift/ctrl information
+     (not very user friendly)"
+
+%{  /* NOCONTEXT */
+    Display *dpy = myDpy;
+    int type;
+
+    if (ISCONNECTED
+     && __isSmallInteger(xPos) && __isSmallInteger(yPos)
+     && __isSmallInteger(buttonNr) && __isSmallInteger(stateMask)
+     && (__isExternalAddress(targetId) || __isInteger(targetId))) {
+	XEvent ev;
+	Window target;
+	Status result;
+	int screen = _intVal(_INST(screen));
+
+	ev.xbutton.x = __intVal(xPos);
+	ev.xbutton.y = __intVal(yPos);
+	ev.xbutton.button = __intVal(buttonNr);
+	ev.xbutton.state = __intVal(stateMask);
+	ev.xbutton.time = CurrentTime;
+
+	if (typeSymbol == @symbol(buttonPress))
+	    ev.xbutton.type = ButtonPress;
+	else if (typeSymbol == @symbol(buttonRelease))
+	    ev.xbutton.type = ButtonRelease;
+	else {
+	    DPRINTF(("invalid sendEvent typeSymbol\n"));
+	    RETURN (false);
+	}
+
+	if (__isExternalAddress(targetId)) {
+	    target = _WindowVal(targetId);
+	} else {
+	    target = (Window) __longIntVal(targetId);
+	}
+	ev.xbutton.window = target;
+	ev.xbutton.same_screen = 1;
+	ev.xbutton.subwindow = 0;
+	ev.xbutton.root = RootWindow(myDpy, screen);
+
+	result = XSendEvent(dpy, target, False, 0 , &ev);
+	if ((result == BadValue) || (result == BadWindow)) {
+	    DPRINTF(("bad status\n"));
+	    RETURN ( false )
+	}
+	RETURN (true)
+    }
+%}.
+    self primitiveFailed.
+    ^ false
+! !
+
 !XWorkstation methodsFor:'event handling'!
 
 dispatchEventFor:aViewIdOrNil withMask:eventMask
@@ -6350,12 +6534,13 @@
 	result = XSendEvent(dpy, requestor, False, 0 , &ev);
 	if ((result == BadValue) || (result == BadWindow)) {
 	    DPRINTF(("bad status\n"));
+	    RETURN (false);
 	}
-	RETURN (self )
-    }
-%}
-.
-    self primitiveFailed
+	RETURN (true)
+    }
+%}.
+    self primitiveFailed.
+    ^ false
 !
 
 setLengthProperty:propertyID value:aNumber for:aWindowID
@@ -7103,6 +7288,6 @@
 !XWorkstation class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.101 1996-01-24 22:05:18 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.102 1996-01-26 12:49:01 ah Exp $'
 ! !
 XWorkstation initialize!