OSXOperatingSystem.st
changeset 24047 df6ad32114b1
parent 24028 cda4ff7bb993
child 24069 6f4f9e93ca51
--- a/OSXOperatingSystem.st	Wed Apr 03 18:17:17 2019 +0200
+++ b/OSXOperatingSystem.st	Thu Apr 04 00:24:02 2019 +0200
@@ -34,6 +34,7 @@
 # define NO_QUARTZ
 # define NO_COCOA
 # define NO_CARBON
+# define NO_COREGRAPHICS
 #endif
 
 // #include <mach/clock.h>
@@ -73,6 +74,7 @@
 # include <ApplicationServices/ApplicationServices.h>
 # include <CoreFoundation/CoreFoundation.h>
 // #include <Foundation/Foundation.h>
+# include <CoreGraphics/CGGeometry.h>
 
 // #include <CoreGraphics/CGEventTypes.h>
 
@@ -211,19 +213,29 @@
 
 #ifndef NO_COCOA
 
+struct ev {
+    struct ev* nextEvent;
+    CGEventType type;
+    CGKeyCode keycode;
+    int x,y;
+    int button;
+};
+static struct ev *nextRecordedEvent = NULL;
+static struct ev *lastRecordedEvent = NULL;
+
 CGEventRef
 myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
 		  CGEventRef event, void *refcon)
 {
-    // Paranoid sanity check.
-    if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
-	return event;
-
-    // The incoming keycode.
-    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
-
-    //Keypress code goes here.
-
+    if ((type == kCGEventKeyDown) || (type == kCGEventKeyUp)) {
+	// The incoming keycode.
+	CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
+    }
+    if (type == kCGEventMouseMoved) {
+	// loc = [NSEvent mouseLocation]
+	// int x = loc.x;
+	// int y = loc.y;
+    }
     // We must return the event for it to be useful.
     return event;
 }
@@ -396,7 +408,7 @@
 !
 
 generateMouseMoveEventX:screenX y:screenY
-    "synthesize and send a mosue move event to the screen"
+    "synthesize and send a mouse move event to the screen"
 %{
 #ifndef NO_COCOA
     if (__bothSmallInteger(screenX, screenY)) {
@@ -491,7 +503,10 @@
     CFRunLoopSourceRef runLoopSource;
 
     // Create an event tap. We are interested in key presses.
-    eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
+    // sigh: a global event tap requires root privileges
+    eventMask = ((1 << kCGEventKeyDown)
+		| (1 << kCGEventKeyUp)
+		| (1 << kCGEventMouseMoved));
     eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
 				eventMask, NULL, myCGEventCallback);
     if (!eventTap) {
@@ -721,10 +736,10 @@
     |rx ry rwidth rheight bytesPerPixel bytesPerRow address pixels depth pad img ok|
 
     aRectangleOrNil notNil ifTrue:[
-        rx := aRectangleOrNil left.
-        ry := aRectangleOrNil top.
-        rwidth := aRectangleOrNil width.
-        rheight := aRectangleOrNil height.
+	rx := aRectangleOrNil left.
+	ry := aRectangleOrNil top.
+	rwidth := aRectangleOrNil width.
+	rheight := aRectangleOrNil height.
     ].
 %{
 #ifndef NO_COCOA
@@ -733,82 +748,82 @@
 
     ok = false;
     if (rx == nil) {
-        image_ref  = CGDisplayCreateImage(displayID);
+	image_ref  = CGDisplayCreateImage(displayID);
     } else {
-        CGRect rect;
-        rect.origin.x = (CGFloat)__intVal(rx);
-        rect.origin.y = (CGFloat)__intVal(ry);
-        rect.size.width = (CGFloat)__intVal(rwidth);
-        rect.size.height = (CGFloat)__intVal(rheight);
-        image_ref  = CGDisplayCreateImageForRect(displayID, rect);
+	CGRect rect;
+	rect.origin.x = (CGFloat)__intVal(rx);
+	rect.origin.y = (CGFloat)__intVal(ry);
+	rect.size.width = (CGFloat)__intVal(rwidth);
+	rect.size.height = (CGFloat)__intVal(rheight);
+	image_ref  = CGDisplayCreateImageForRect(displayID, rect);
     }
 
     if (image_ref != NULL) {
-        CGDataProviderRef provider = CGImageGetDataProvider(image_ref);
-        CFDataRef dataref = CGDataProviderCopyData(provider);
-        size_t c_width = CGImageGetWidth(image_ref);
-        size_t c_height = CGImageGetHeight(image_ref);
-        size_t c_bytesPerRow = CGImageGetBytesPerRow(image_ref);
-        size_t c_bytesPerPixel = CGImageGetBitsPerPixel(image_ref) / 8;
-        unsigned char *c_pixels = (unsigned char *)CFDataGetBytePtr(dataref);
+	CGDataProviderRef provider = CGImageGetDataProvider(image_ref);
+	CFDataRef dataref = CGDataProviderCopyData(provider);
+	size_t c_width = CGImageGetWidth(image_ref);
+	size_t c_height = CGImageGetHeight(image_ref);
+	size_t c_bytesPerRow = CGImageGetBytesPerRow(image_ref);
+	size_t c_bytesPerPixel = CGImageGetBitsPerPixel(image_ref) / 8;
+	unsigned char *c_pixels = (unsigned char *)CFDataGetBytePtr(dataref);
 
-        if (c_bytesPerPixel == 4) {
-            int row;
-            pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * 3);
-            unsigned char *srcRowPtr = c_pixels;
-            unsigned char *dstRowPtr = __byteArrayVal(pixels);
+	if (c_bytesPerPixel == 4) {
+	    int row;
+	    pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * 3);
+	    unsigned char *srcRowPtr = c_pixels;
+	    unsigned char *dstRowPtr = __byteArrayVal(pixels);
 
-            for (row=c_height; row>0; row--) {
-                int col = c_width;
-                unsigned int *pixSrcPtr = (int*)srcRowPtr;
-                unsigned char *pixDstPtr = dstRowPtr;
+	    for (row=c_height; row>0; row--) {
+		int col = c_width;
+		unsigned int *pixSrcPtr = (int*)srcRowPtr;
+		unsigned char *pixDstPtr = dstRowPtr;
 
-                // convert abgr to rgb
+		// convert abgr to rgb
 #if (__POINTER_SIZE__ == 8) && defined(__LSBFIRST__)
-                for (; col > 2; col -= 2) {
-                    // pick 2 pixels
-                    unsigned INT pix12 = ((unsigned INT*)pixSrcPtr)[0];
-                    pixSrcPtr += 2;
-                    // a2 r2 g2 b2 a1 r1 g1 b1 => r1..g1..b1..r2..g2..b2
-                    pixDstPtr[0] = (pix12 >> 16) & 0xFF;
-                    pixDstPtr[1] = (pix12 >> 8) & 0xFF;
-                    pixDstPtr[2] = pix12 & 0xFF;
-                    pixDstPtr[3] = (pix12 >> 48) & 0xFF;
-                    pixDstPtr[4] = (pix12 >> 40) & 0xFF;
-                    pixDstPtr[5] = (pix12 >> 32) & 0xFF;
-                    pixDstPtr += 6;
-                }
+		for (; col > 2; col -= 2) {
+		    // pick 2 pixels
+		    unsigned INT pix12 = ((unsigned INT*)pixSrcPtr)[0];
+		    pixSrcPtr += 2;
+		    // a2 r2 g2 b2 a1 r1 g1 b1 => r1..g1..b1..r2..g2..b2
+		    pixDstPtr[0] = (pix12 >> 16) & 0xFF;
+		    pixDstPtr[1] = (pix12 >> 8) & 0xFF;
+		    pixDstPtr[2] = pix12 & 0xFF;
+		    pixDstPtr[3] = (pix12 >> 48) & 0xFF;
+		    pixDstPtr[4] = (pix12 >> 40) & 0xFF;
+		    pixDstPtr[5] = (pix12 >> 32) & 0xFF;
+		    pixDstPtr += 6;
+		}
 #endif
 
-                for (; col>0;col--) {
-                    unsigned int pix = *pixSrcPtr++;
+		for (; col>0;col--) {
+		    unsigned int pix = *pixSrcPtr++;
 #if 0
-                    pix = ((pix >> 16) & 0x0000FF)|((pix << 16) & 0xFF0000)|(pix & 0x00FF00);
-                    pixDstPtr[0] = (pix >> 0);
-                    pixDstPtr[1] = (pix >> 8);
-                    pixDstPtr[2] = (pix >> 16);
+		    pix = ((pix >> 16) & 0x0000FF)|((pix << 16) & 0xFF0000)|(pix & 0x00FF00);
+		    pixDstPtr[0] = (pix >> 0);
+		    pixDstPtr[1] = (pix >> 8);
+		    pixDstPtr[2] = (pix >> 16);
 #else
-                    pixDstPtr[0] = (pix >> 16) & 0xFF;
-                    pixDstPtr[1] = (pix >> 8) & 0xFF;
-                    pixDstPtr[2] = pix & 0xFF;
+		    pixDstPtr[0] = (pix >> 16) & 0xFF;
+		    pixDstPtr[1] = (pix >> 8) & 0xFF;
+		    pixDstPtr[2] = pix & 0xFF;
 #endif
-                    pixDstPtr += 3;
-                }
-                dstRowPtr += c_width * 3;
-                srcRowPtr += c_bytesPerRow;
-            }
-            bytesPerPixel = __MKSMALLINT(3);
-            bytesPerRow = __MKSMALLINT( c_width*3 );
-            ok = true;
-        } else {
-            // to be determined what we get...
-            ok = false;
-        }
-        CFRelease(dataref);
-        CGImageRelease(image_ref);
+		    pixDstPtr += 3;
+		}
+		dstRowPtr += c_width * 3;
+		srcRowPtr += c_bytesPerRow;
+	    }
+	    bytesPerPixel = __MKSMALLINT(3);
+	    bytesPerRow = __MKSMALLINT( c_width*3 );
+	    ok = true;
+	} else {
+	    // to be determined what we get...
+	    ok = false;
+	}
+	CFRelease(dataref);
+	CGImageRelease(image_ref);
 
-        rwidth = __MKUINT( c_width );
-        rheight = __MKUINT( c_height );
+	rwidth = __MKUINT( c_width );
+	rheight = __MKUINT( c_height );
     }
 
     // the following is no longer supported by apple
@@ -829,7 +844,7 @@
 
 %}.
     (ok not or:[rwidth isNil]) ifTrue:[
-        ^ self primitiveFailed
+	^ self primitiveFailed
     ].
     depth := bytesPerPixel * 8.
 
@@ -837,22 +852,22 @@
     "/            withAll:{ rwidth . rheight . bytesPerPixel . depth . bytesPerRow}.
 
     ( #(24) includes:depth) ifFalse:[
-        "/ check what we get here...
-        ^ self primitiveFailed:'unsupported depth'
+	"/ check what we get here...
+	^ self primitiveFailed:'unsupported depth'
     ].
 
     img := Image extent:(rwidth @ rheight) depth:depth bits:pixels.
     depth == 24 ifTrue:[
-        img bitsPerSample:#[8 8 8].
-        img samplesPerPixel:3.
-        img photometric:#rgb.
+	img bitsPerSample:#[8 8 8].
+	img samplesPerPixel:3.
+	img photometric:#rgb.
     ] ifFalse:[
-        depth == 16 ifTrue:[
-            "/ to be determined...
-            img bitsPerSample:#[5 5 5].
-            img samplesPerPixel:3.
-            img photometric:#rgb.
-        ].
+	depth == 16 ifTrue:[
+	    "/ to be determined...
+	    img bitsPerSample:#[5 5 5].
+	    img samplesPerPixel:3.
+	    img photometric:#rgb.
+	].
     ].
     ^ img
 
@@ -868,6 +883,22 @@
     "Modified: / 01-04-2019 / 00:39:22 / Claus Gittinger"
 !
 
+getMousePosition
+    |xLoc yLoc|
+
+%{
+#ifndef NO_COREGRAPHICS
+    CGEventRef event = CGEventCreate(NULL);
+    CGPoint loc = CGEventGetLocation(event);
+    CFRelease(event);
+
+    xLoc = __MKFLOAT(loc.x);
+    yLoc = __MKFLOAT(loc.y);
+#endif // NO_COREGRAPHICS
+%}.
+    ^ xLoc @ yLoc
+!
+
 getScreenBounds:displayNr
     "returns the bounds of the screen.
      This is needed, because the dimension of the XQuartz screen does not include the dock."
@@ -988,14 +1019,14 @@
     map add:( 'default' -> nil ).
     VoiceMapping := map.
     ^ VoiceMapping
-    
+
     "on OSX, this could be:
-        ^ {
-            'male' -> 'Alex' .
-            'female' -> 'Fiona' .
-            'computer' -> 'Zarvox' .
-            'default' -> 'Fiona'
-        }
+	^ {
+	    'male' -> 'Alex' .
+	    'female' -> 'Fiona' .
+	    'computer' -> 'Zarvox' .
+	    'default' -> 'Fiona'
+	}
     "
 
     "
@@ -1020,8 +1051,8 @@
 
     |seconds millis nanos|
 %{
-// all of the experiments below only return 1us resolution
-// on my machine. Not sure if that has to do with the OSX version (high sierra)
+// all of the experiments below only provide 1us resolution on my machine
+// Not sure if that has to do with the OSX version (high sierra)
 // therefore, it is disabled, and we fall back to the inherited method,
 // which returns microsecond resolution nanos anyway.
 #if 0
@@ -1095,4 +1126,3 @@
 version_CVS
     ^ '$Header$'
 ! !
-