XWorkstation.st
changeset 8837 2a3224010cb0
parent 8806 2870952bfd4d
child 8858 1a64faf25e1b
--- a/XWorkstation.st	Wed Oct 16 15:45:12 2019 +0200
+++ b/XWorkstation.st	Thu Oct 17 16:46:34 2019 +0200
@@ -7210,11 +7210,16 @@
 !
 
 sendKeyOrButtonEvent:typeSymbol x:xPos y:yPos keyOrButton:keySymCodeOrButtonNr state:stateMask toViewId:targetId useXTest:useXTestBoolean
-    "send a keyPress/Release or buttonPress/Release event to some (possibly alien) view.
-     TypeSymbol must be one of: #keyPress, #keyRelease, #buttonPress , #buttonRelease.
+    "send a keyPress/Release or buttonPress/Release/Motion event to some (possibly alien) view.
+     TypeSymbol must be one of:
+	#keyPress, #keyRelease,
+	#buttonPress , #buttonRelease,
+	#motionNotify.
      For buttonEvents, the keySymCodeOrButtonNr must be the buttons number (1, 2 ...);
      for key events, it can be either a symbol (as listed in X's keySyms)
-     or a numeric keysym code. If state is nil, the modifier bits (shift & control)
+     or a numeric keysym code;
+     for motion events, it must be the buttonStateMask.
+     If state is nil, the modifier bits (shift & control)
      are computed from the keyboardMap - if non-nil, these are passed as modifierbits.
      The non-nil case is the lowlevel entry, where state must include any shift/ctrl information
      (not very user friendly)"
@@ -7242,13 +7247,12 @@
 	KeySym keySym, *syms;
 	int screen = __intVal(__INST(screen));
 	int nSyms;
-	int isButtonEvent = 0, isKeyEvent = 0;
+	int isButtonEvent = 0, isKeyEvent = 0, isMotionEvent = 0;
 
 	if ((typeSymbol == @symbol(keyPress))
 	 || (typeSymbol == @symbol(keyRelease))) {
 	    isKeyEvent = 1;
-	    ev.xany.type = (typeSymbol == @symbol(keyPress))
-				? KeyPress : KeyRelease;
+	    ev.xany.type = (typeSymbol == @symbol(keyPress)) ? KeyPress : KeyRelease;
 	    if (__isStringLike(keySymCodeOrButtonNr)) {
 		keySym = XStringToKeysym(__stringVal(keySymCodeOrButtonNr));
 	    } else {
@@ -7288,22 +7292,21 @@
 		    XFree(syms);
 		}
 	    }
+	} else if ((typeSymbol == @symbol(buttonPress))
+		|| (typeSymbol == @symbol(buttonRelease))) {
+	    isButtonEvent = 1;
+	    ev.xany.type = (typeSymbol == @symbol(buttonPress)) ? ButtonPress : ButtonRelease;
+	    if (__isSmallInteger(keySymCodeOrButtonNr)) {
+		ev.xbutton.button = __intVal(keySymCodeOrButtonNr);
+	    } else {
+		ev.xbutton.button = 1;
+	    }
+	} else if (typeSymbol == @symbol(motionNotify)) {
+	    isMotionEvent = 1;
+	    ev.xany.type = MotionNotify;
 	} else {
-	    if ((typeSymbol == @symbol(buttonPress))
-	     || (typeSymbol == @symbol(buttonRelease))) {
-		isButtonEvent = 1;
-		ev.xany.type = (typeSymbol == @symbol(buttonPress))
-				? ButtonPress : ButtonRelease;
-
-		if (__isSmallInteger(keySymCodeOrButtonNr)) {
-		    ev.xbutton.button = __intVal(keySymCodeOrButtonNr);
-		} else {
-		    ev.xbutton.button = 1;
-		}
-	    } else {
-		DPRINTF(("invalid sendEvent typeSymbol\n"));
-		RETURN (false);
-	    }
+	    DPRINTF(("invalid sendEvent typeSymbol\n"));
+	    RETURN (false);
 	}
 
 	if (__isExternalAddress(targetId)) {
@@ -7325,6 +7328,8 @@
 	if (useXTestBoolean == true) {
 	    if (isButtonEvent) {
 		XTestFakeButtonEvent(dpy, ev.xbutton.button, ev.xany.type == ButtonPress, CurrentTime);
+	    } else if (isMotionEvent) {
+		XTestFakeMotionEvent(dpy, -1, __intVal(xPos), __intVal(yPos), CurrentTime);
 	    } else {
 		XTestFakeKeyEvent(dpy, ev.xkey.keycode, ev.xany.type == KeyPress, CurrentTime);
 	    }