OSXOperatingSystem.st
changeset 21587 3ac571f08fbf
parent 21585 d2859242f3d7
child 21591 c89611bc4b5c
--- a/OSXOperatingSystem.st	Tue Feb 28 09:43:01 2017 +0100
+++ b/OSXOperatingSystem.st	Tue Feb 28 09:43:57 2017 +0100
@@ -15,7 +15,7 @@
 
 UnixOperatingSystem subclass:#OSXOperatingSystem
 	instanceVariableNames:''
-	classVariableNames:''
+	classVariableNames:'NSApp'
 	poolDictionaries:''
 	category:'OS-Unix'
 !
@@ -23,6 +23,8 @@
 !OSXOperatingSystem primitiveDefinitions!
 %{
 
+#undef NO_COCOA
+
 #ifndef __OSX__
 # define NO_QUARTZ
 # define NO_COCOA
@@ -60,6 +62,7 @@
 #include <ApplicationServices/ApplicationServices.h>
 #include <CoreFoundation/CoreFoundation.h>
 // #include <Foundation/Foundation.h>
+#include <CoreGraphics/CGEventTypes.h>
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -126,7 +129,7 @@
 #   define Processor __DEF_Processor
 #  endif
 #  ifdef __DEF_Class
-#   define Class __DEF_Class
+#   define STX_Class __DEF_Class
 #  endif
 #  ifdef __DEF_FixedPoint
 #   define FixedPoint __DEF_FixedPoint
@@ -143,7 +146,50 @@
 #  define INT STX_INT
 #  define UINT STX_UINT
 
-#endif // NP_COCOA
+typedef struct CMPoint {
+	double x;
+	double y;
+} CMPoint;
+
+typedef struct CMSize {
+	double width;
+	double height;
+} CMSize;
+
+typedef struct CMRect {
+	CMPoint origin;
+	CMSize size;
+} CMRect;
+
+typedef struct AppDel {
+	Class isa;
+
+	// Will be an NSWindow later.
+	id window;
+} AppDelegate;
+
+
+enum {
+	NSBorderlessWindowMask          = 0,
+	NSTitledWindowMask                      = 1 << 0,
+	NSClosableWindowMask            = 1 << 1,
+	NSMiniaturizableWindowMask      = 1 << 2,
+	NSResizableWindowMask           = 1 << 3,
+};
+
+typedef id(*CMacsSimpleMessage)(id, SEL);
+typedef void(*CMacsVoidMessage)(id, SEL);
+typedef void(*CMacsVoidMessage1)(id, SEL, void *);
+typedef id(*CMacsRectMessage1)(id, SEL, CMRect);
+typedef id(*CMacsWindowInitMessage)(id, SEL, CMRect, int, int, bool);
+
+extern CMacsSimpleMessage cmacs_simple_msgSend;
+extern CMacsVoidMessage cmacs_void_msgSend;
+extern CMacsVoidMessage1 cmacs_void_msgSend1;
+extern CMacsRectMessage1 cmacs_rect_msgSend1;
+extern CMacsWindowInitMessage cmacs_window_init_msgSend;
+
+#endif // NO_COCOA
 
 %}
 ! !
@@ -170,6 +216,27 @@
     return event;
 }
 
+BOOL
+AppDel_didFinishLaunching(AppDelegate *self, SEL _cmd, id notification) {
+//    self->window = cmacs_simple_msgSend((id)objc_getClass("NSWindow"), sel_getUid("alloc"));
+//
+//    /// Create an instance of the window.
+//    self->window = cmacs_window_init_msgSend(self->window, sel_getUid("initWithContentRect:styleMask:backing:defer:"), (CMRect){0,0,1024,460}, (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask), 0, false);
+//
+//    /// Create an instance of our view class.
+//    ///
+//    /// Relies on the view having declared a constructor that allocates a class pair for it.
+//    id view = cmacs_rect_msgSend1(cmacs_simple_msgSend((id)objc_getClass("View"), sel_getUid("alloc")), sel_getUid("initWithFrame:"), (CMRect){ 0, 0, 320, 480 });
+//
+//    // here we simply add the view to the window.
+//    cmacs_void_msgSend1(self->window, sel_getUid("setContentView:"), view);
+//    cmacs_simple_msgSend(self->window, sel_getUid("becomeFirstResponder"));
+//
+//    // Shows our window in the bottom-left hand corner of the screen.
+//    cmacs_void_msgSend1(self->window, sel_getUid("makeKeyAndOrderFront:"), self);
+    return YES;
+}
+
 #endif // NO_COCOA
 
 %}
@@ -210,44 +277,43 @@
 
 !OSXOperatingSystem class methodsFor:'cocoa - events'!
 
-generateButtonEvent:button down:down x:px y:py
+generateButtonEvent:button down:down x:screenX y:screenY
+    "synthesize and send a button event to the screen"
 %{
 #ifndef NO_COCOA
-# include <CoreGraphics/CGEventTypes.h>
-
-    if (__bothSmallInteger(px, py)
+    if (__bothSmallInteger(screenX, screenY)
      && __isSmallInteger(button)) {
-        CGPoint pt;
-        pt.x = __intVal(px);
-        pt.y = __intVal(py);
+	CGPoint pt;
+	pt.x = __intVal(screenX);
+	pt.y = __intVal(screenY);
+
+	CGEventType evType;
+	CGMouseButton evButton = __intVal(button);
 
-        CGEventType evType;
-        CGMouseButton evButton = __intVal(button);
-        
-        switch (evButton) {
-            case 1:
-                evType = (down == true) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp;
-                evButton = 0;
-                break;
-            case 2:
-                evType = (down == true) ? kCGEventRightMouseDown : kCGEventRightMouseUp;
-                evButton = 1;
-                break;
-            case 3:
-                evType = (down == true) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
-                evButton = 2;
-                break;
-            default:
-                evType = (down == true) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
-                evButton = __intVal(button) - 1;
-                break;
-        }
-        
-        CGEventRef theEvent = CGEventCreateMouseEvent(NULL, evType, pt, evButton);
-        CGEventSetType(theEvent, evType);
-        CGEventPost(kCGHIDEventTap, theEvent);
-        CFRelease(theEvent);
-        RETURN(self);
+	switch (evButton) {
+	    case 1:
+		evType = (down == true) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp;
+		evButton = 0;
+		break;
+	    case 2:
+		evType = (down == true) ? kCGEventRightMouseDown : kCGEventRightMouseUp;
+		evButton = 1;
+		break;
+	    case 3:
+		evType = (down == true) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
+		evButton = 2;
+		break;
+	    default:
+		evType = (down == true) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
+		evButton = __intVal(button) - 1;
+		break;
+	}
+
+	CGEventRef theEvent = CGEventCreateMouseEvent(NULL, evType, pt, evButton);
+	CGEventSetType(theEvent, evType);
+	CGEventPost(kCGHIDEventTap, theEvent);
+	CFRelease(theEvent);
+	RETURN(self);
     }
 #endif // NO_COCOA
 %}.
@@ -274,23 +340,77 @@
     // Create an event tap. We are interested in key presses.
     eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
     eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
-                                eventMask, NULL, myCGEventCallback);
+				eventMask, NULL, myCGEventCallback);
     if (!eventTap) {
-        fprintf(stderr, "failed to create event tap\n");
-    } else{
-        fprintf(stderr, "ok\n");
+	fprintf(stderr, "failed to create event tap\n");
+    } else {
+	fprintf(stderr, "ok\n");
+
+	// Create a run loop source.
+	runLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, eventTap, 0);
+	// Enable the event tap.
+	CGEventTapEnable(eventTap, true);
     }
 
-    // Create a run loop source.
-    runLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, eventTap, 0);
-    // Enable the event tap.
-    CGEventTapEnable(eventTap, true);
-
 #endif // NO_COCOA
 %}.
     self primitiveFailed
 
     "Modified: / 28-02-2017 / 01:05:04 / cg"
+!
+
+getNSApp
+%{
+#ifndef NO_COCOA
+    Class AppDelClass = NULL;
+    id NSApp = NULL;
+
+    AppDelClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
+    class_addMethod(AppDelClass, sel_getUid("applicationDidFinishLaunching:"), (IMP)AppDel_didFinishLaunching, "i@:@");
+    objc_registerClassPair(AppDelClass);
+
+    NSApp = objc_msgSend((id)objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
+    if (NSApp == NULL) {
+	fprintf(stderr,"OSX: Failed to initialize NSApplication.\n");
+	RETURN(false);
+    }
+    @global(NSApp) = __MKEXTERNALADDRESS(NSApp);
+
+    id appDelObj = objc_msgSend((id)objc_getClass("AppDelegate"), sel_getUid("alloc"));
+    appDelObj = objc_msgSend(appDelObj, sel_getUid("init"));
+
+    objc_msgSend(NSApp, sel_getUid("setDelegate:"), appDelObj);
+    RETURN(true);
+#endif // NO_COCOA
+%}.
+    self primitiveFailed
+
+    "
+     self getNSApp
+    "
+
+    "Modified (comment): / 28-02-2017 / 01:35:31 / cg"
+!
+
+finishLaunching
+    NSApp isNil ifTrue:[
+	self getNSApp
+    ].
+%{
+#ifndef NO_COCOA
+    id NSApp = __externalAddressVal(@global(NSApp));
+
+    objc_msgSend(NSApp, sel_getUid("finishLaunching"));
+    RETURN(self);
+#endif // NO_COCOA
+%}.
+    self primitiveFailed
+
+    "
+     self finishLaunching
+    "
+
+    "Modified (comment): / 28-02-2017 / 01:35:31 / cg"
 ! !
 
 !OSXOperatingSystem class methodsFor:'dummy shell operations'!
@@ -453,72 +573,77 @@
 !
 
 getFrameBufferImage:displayNr in:aRectangleOrNil
-    "returns the framebuffer as an image object"
+    "returns the frameBuffer (if rect-arg is nil)
+     or part of the framebuffer (if non-nil) as an image object"
 
-    |rx ry rwidth rheight bytesPerPixel bytesPerRow address pixels depth pad img|
+    |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_QUARTZ
     CGImageRef image_ref;
     CGDirectDisplayID displayID = CGMainDisplayID();
-    
+
+    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 = 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 = CFDataGetBytePtr(dataref);
 
-        pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * c_bytesPerPixel);
+	pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * c_bytesPerPixel);
 
-        if (c_bytesPerPixel == 4) {
-            int row;
-            unsigned char *srcRowPtr = c_pixels;
-            unsigned char *dstRowPtr = __byteArrayVal(pixels);
-            
-            for (row=c_height; row>0; row--) {
-                int col;
-                unsigned int *pixSrcPtr = (int*)srcRowPtr;
-                unsigned int *pixDstPtr = (int*)dstRowPtr;
-                
-                // swap abgr to argb
-                for (col=c_width; col>0;col--) {
-                    unsigned int pix = *pixSrcPtr++;
+	if (c_bytesPerPixel == 4) {
+	    int row;
+	    unsigned char *srcRowPtr = c_pixels;
+	    unsigned char *dstRowPtr = __byteArrayVal(pixels);
+
+	    for (row=c_height; row>0; row--) {
+		int col;
+		unsigned int *pixSrcPtr = (int*)srcRowPtr;
+		unsigned int *pixDstPtr = (int*)dstRowPtr;
+
+		// swap abgr to argb
+		for (col=c_width; col>0;col--) {
+		    unsigned int pix = *pixSrcPtr++;
 
-                    pix = ((pix >> 16) & 0x0000FF)|((pix << 16) & 0xFF0000)|(pix & 0x00FF00);
-                    *pixDstPtr++ = pix;
-                }
-                dstRowPtr += c_width * c_bytesPerPixel;
-                srcRowPtr += c_bytesPerRow;
-            }
-        } else {
-        }
-        CFRelease(dataref);
-        CGImageRelease(image_ref);
+		    pix = ((pix >> 16) & 0x0000FF)|((pix << 16) & 0xFF0000)|(pix & 0x00FF00);
+		    *pixDstPtr++ = pix;
+		}
+		dstRowPtr += c_width * c_bytesPerPixel;
+		srcRowPtr += c_bytesPerRow;
+	    }
+	    ok = true;
+	} else {
+	    // to be determined what we get...
+	    ok = false;
+	}
+	CFRelease(dataref);
+	CGImageRelease(image_ref);
 
-        rwidth = __MKUINT( c_width );
-        rheight = __MKUINT( c_height );
-        bytesPerPixel = __MKUINT( c_bytesPerPixel );
-        bytesPerRow = __MKUINT( c_bytesPerRow );
+	rwidth = __MKUINT( c_width );
+	rheight = __MKUINT( c_height );
+	bytesPerPixel = __MKUINT( c_bytesPerPixel );
+	bytesPerRow = __MKUINT( c_bytesPerRow );
     }
 
     // the following is no longer supported by apple
@@ -534,21 +659,21 @@
     //    rwidth = __MKUINT( CGDisplayPixelsWide(targetDisplay) );
     //    rheight = __MKUINT( CGDisplayPixelsHigh(targetDisplay) );
     //
-    
+
 #endif // NO_QUARTZ
 
 %}.
-    rwidth isNil ifTrue:[
-        ^ self primitiveFailed
+    (ok not or:[rwidth isNil]) ifTrue:[
+	^ self primitiveFailed
     ].
     depth := bytesPerPixel * 8.
 
-    "/ Transcript printf:'w:%d h:%d bpp:%d depth:%d bpr: %d\n' 
+    "/ Transcript printf:'w:%d h:%d bpp:%d depth:%d bpr: %d\n'
     "/            withAll:{ rwidth . rheight . bytesPerPixel . depth . bytesPerRow}.
 
     ( #(16 32) 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.
@@ -576,4 +701,3 @@
 version_CVS
     ^ '$Header$'
 ! !
-