|
- #if defined(OS_DARWIN)
-
- // https://stackoverflow.com/questions/4356441/mac-os-cocoa-draw-a-simple-pixel-on-a-canvas
- // http://cocoadevcentral.com/d/intro_to_quartz/
- // Modified based on
- // https://github.com/CodaFi/C-Macs
-
- // Obj-c runtime doc:
- // https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc
-
- #include <math.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #define OBJC_OLD_DISPATCH_PROTOTYPES 1
-
- #include <ApplicationServices/ApplicationServices.h>
- #include <Carbon/Carbon.h>
- #include <CoreGraphics/CGBase.h>
- #include <CoreGraphics/CGGeometry.h>
- #include <CoreVideo/CVDisplayLink.h>
- #include <mach/mach_time.h>
- #include <objc/NSObjCRuntime.h>
- #include <objc/message.h>
- #include <objc/runtime.h>
-
- #include "image.h"
-
- #include "sww/app.h"
- #include "window_private.h"
-
- typedef CGRect NSRect;
- typedef CGPoint NSPoint;
- typedef CGSize NSSize;
-
- typedef void NSWindow;
- typedef void NSWindowController;
- typedef void NSApplication;
- typedef void NSEvent;
- typedef void NSScreen;
- typedef void NSColor;
- typedef void NSCursor;
- typedef void NSPasteboard;
- typedef void NSOpenGLContext;
- typedef void NSOpenGLPixelFormat;
- typedef void NSDraggingInfo;
- typedef void NSImageRep;
- typedef void NSGraphicsContext;
- typedef void NSBitmapImageRep;
- typedef void NSMenu;
- typedef void NSMenuItem;
- typedef void NSImage;
- typedef void NSView;
- typedef void NSViewController;
- typedef void NSAutoreleasePool;
- typedef void NSFontManager;
- typedef void NSTextField;
- typedef void NSProcessInfo;
- typedef void NSButton;
- typedef void NSComboBox;
- typedef void NSSlider;
- typedef void NSProgressIndicator;
- typedef void NSSavePanel;
- typedef void NSOpenPanel;
- typedef void NSColorPanel;
- typedef void NSBundle;
- typedef void NSNotification;
- typedef void NSNotificationCenter;
- typedef void CALayer;
- #ifndef __OBJC__
- typedef void NSDictionary;
- typedef void NSURL;
- typedef void NSFont;
- typedef void NSDate;
- typedef void NSString;
- typedef void NSArray;
- typedef void NSThread;
- #endif
-
- typedef const char* NSPasteboardType;
- typedef unsigned long NSUInteger;
- typedef long NSInteger;
- typedef NSInteger NSModalResponse;
-
- #ifdef __arm64__
- /* ARM just uses objc_msgSend */
- #define abi_objc_msgSend_stret objc_msgSend
- #define abi_objc_msgSend_fpret objc_msgSend
- #else /* __i386__ */
- /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id
- * respectively */
- #define abi_objc_msgSend_stret objc_msgSend_stret
- #define abi_objc_msgSend_fpret objc_msgSend_fpret
- #endif
-
- #define objc_msgSend_bool ((BOOL(*)(id, SEL))objc_msgSend)
- #define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend)
- #define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend)
- #define objc_msgSend_uint ((NSUInteger(*)(id, SEL))objc_msgSend)
- #define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend)
- #define objc_msgSend_bool_void ((BOOL(*)(id, SEL))objc_msgSend)
- #define objc_msgSend_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend)
- #define objc_msgSend_id ((id(*)(id, SEL))objc_msgSend)
- #define objc_msgSend_id_id ((id(*)(id, SEL, id))objc_msgSend)
- #define objc_msgSend_id_bool ((BOOL(*)(id, SEL, id))objc_msgSend)
- #define objc_msgSend_int ((id(*)(id, SEL, int))objc_msgSend)
- #define objc_msgSend_arr ((id(*)(id, SEL, int))objc_msgSend)
- #define objc_msgSend_ptr ((id(*)(id, SEL, void*))objc_msgSend)
- #define objc_msgSend_class ((id(*)(Class, SEL))objc_msgSend)
- #define objc_msgSend_class_char ((id(*)(Class, SEL, char*))objc_msgSend)
-
- #define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))
-
- #define GetInstanceVar(inst, name) _GetInstanceVar((void*)(inst), name)
- #define SetInstanceVar(inst, name, data) \
- object_setInstanceVariable((void*)(inst), name, (void*)(data))
-
- static inline void* _GetInstanceVar(void* instance, const char* name)
- {
- void* data = NULL;
- object_getInstanceVariable(instance, name, (void**)(&data));
- return data;
- }
-
- static inline void NSRelease(id obj)
- {
- objc_msgSend_void(obj, sel_registerName("release"));
- }
-
- #define release NSRelease
-
- static inline NSString* NSString_stringWithUTF8String(const char* str)
- {
- return ((id(*)(id, SEL, const char*))objc_msgSend)(
- (id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);
- }
-
- static inline const char* NSString_toUTF8String(NSString* str)
- {
- return ((const char* (*)(id, SEL))objc_msgSend)(str, sel_registerName("UTF8String"));
- }
-
- static void RegisterMethodForClassWithNameImpl(const char* class_name, const char* register_name,
- void* function)
- {
- Class selected_class;
-
- if (strcmp(class_name, "NSView") == 0) {
- selected_class = objc_getClass("ViewClass");
- } else if (strcmp(class_name, "NSWindow") == 0) {
- selected_class = objc_getClass("WindowClass");
- } else {
- selected_class = objc_getClass(class_name);
- }
-
- class_addMethod(selected_class, sel_registerName(register_name), (IMP)function, 0);
- }
-
- /* Header for the array. */
- typedef struct NSArrayHeader
- {
- size_t count;
- /* TODO(EimaMei): Add a `type_width` later on. */
- } NSArrayHeader;
-
- /* Gets the header of the Array. */
- #define ARRAY_HEADER(s) ((NSArrayHeader*)s - 1)
-
- void* Array_InitReserve(size_t sizeof_element, size_t count)
- {
- NSArrayHeader* ptr = (NSArrayHeader*)malloc(sizeof(NSArrayHeader) + (sizeof_element * count));
- void* array = ptr + sizeof(NSArrayHeader);
-
- NSArrayHeader* header = ARRAY_HEADER(array);
- header->count = count;
-
- return array;
- }
-
- #define Array_Length(array) (ARRAY_HEADER(array)->count)
- #define RegisterMethodForClass(clsname, func) \
- RegisterMethodForClassWithNameImpl(clsname, #func ":", func)
- /* Creates an Objective-C method (SEL) from a regular C function with the option
- * to set the register name.*/
- #define RegisterMethodForClassWithName(class_name, register_name, function) \
- RegisterMethodForClassWithNameImpl(class_name, register_name ":", function)
-
- unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* image_rep)
- {
- return ((unsigned char* (*)(id, SEL))objc_msgSend)(image_rep, sel_registerName("bitmapData"));
- }
-
- #define NS_ENUM(type, name) \
- type name; \
- enum
-
- typedef NSUInteger NSBitmapFormat;
- enum
- {
- NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.)
- NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied
- NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer
-
- NSBitmapFormatSixteenBitLittleEndian = 1 << 8,
- NSBitmapFormatThirtyTwoBitLittleEndian = 1 << 9,
- NSBitmapFormatSixteenBitBigEndian = 1 << 10,
- NSBitmapFormatThirtyTwoBitBigEndian = 1 << 11
- };
-
- NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width,
- NSInteger height, NSInteger bps,
- NSInteger spp, bool alpha, bool isPlanar,
- const char* colorSpaceName,
- NSBitmapFormat bitmapFormat,
- NSInteger rowBytes, NSInteger pixelBits)
- {
- void* func = sel_registerName(
- "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:"
- "bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:"
- "colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
-
- return (NSBitmapImageRep*)((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger,
- NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger,
- NSInteger))objc_msgSend)(
- NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp,
- alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes,
- pixelBits);
- }
-
- NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
- {
- void* nsclass = objc_getClass("NSColor");
- void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");
- return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(nsclass, func, red,
- green, blue, alpha);
- }
-
- NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint)
- {
- void* func = sel_registerName("initWithImage:hotSpot:");
- void* nsclass = objc_getClass("NSCursor");
-
- return (NSCursor*)((id(*)(id, SEL, id, NSPoint))objc_msgSend)(NSAlloc(nsclass), func, newImage,
- aPoint);
- }
-
- void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep)
- {
- void* func = sel_registerName("addRepresentation:");
- objc_msgSend_void_id(image, func, imageRep);
- }
-
- NSImage* NSImage_initWithSize(NSSize size)
- {
- void* func = sel_registerName("initWithSize:");
- return ((id(*)(id, SEL, NSSize))objc_msgSend)(NSAlloc((id)objc_getClass("NSImage")), func,
- size);
- }
-
- typedef NSInteger NSOpenGLContextParameter;
- enum
- {
- NSOpenGLContextParameterSwapInterval =
- 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */
- NSOpenGLContextParametectxaceOrder =
- 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */
- NSOpenGLContextParametectxaceOpacity =
- 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */
- NSOpenGLContextParametectxaceBackingSize =
- 304, /* 2 params. Width/height of surface backing size */
- NSOpenGLContextParameterReclaimResources = 308, /* 0 params. */
- NSOpenGLContextParameterCurrentRendererID =
- 309, /* 1 param. Retrieves the current renderer ID */
- NSOpenGLContextParameterGPUVertexProcessing =
- 310, /* 1 param. Currently processing vertices with GPU (get) */
- NSOpenGLContextParameterGPUFragmentProcessing =
- 311, /* 1 param. Currently processing fragments with GPU (get) */
- NSOpenGLContextParameterHasDrawable =
- 314, /* 1 param. Boolean returned if drawable is attached */
- NSOpenGLContextParameterMPSwapsInFlight =
- 315, /* 1 param. Max number of swaps queued by the MP GL engine */
-
- NSOpenGLContextParameterSwapRectangle =
- 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */
- NSOpenGLContextParameterSwapRectangleEnable = 201, /* Enable or disable the swap rectangle */
- NSOpenGLContextParameterRasterizationEnable = 221, /* Enable or disable all rasterization */
- NSOpenGLContextParameterStateValidation =
- 301, /* Validate state for multi-screen functionality */
- NSOpenGLContextParametectxaceSurfaceVolatile = 306, /* 1 param. Surface volatile state */
- };
-
- NSString** CStrToNSStringArray(char** strs, size_t len)
- {
- static NSString* nstrs[6];
- size_t i;
- for (i = 0; i < len; i++)
- nstrs[i] = NSString_stringWithUTF8String(strs[i]);
-
- return nstrs;
- }
-
- const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType)
- {
- void* func = sel_registerName("stringForType:");
- return (const char*)NSString_toUTF8String(((id(*)(id, SEL, const char*))objc_msgSend)(
- pasteboard, func, NSString_stringWithUTF8String(dataType)));
- }
-
- void NSRetain(id obj)
- {
- objc_msgSend_void(obj, sel_registerName("retain"));
- }
-
- typedef enum NSApplicationActivationPolicy
- {
- NSApplicationActivationPolicyRegular,
- NSApplicationActivationPolicyAccessory,
- NSApplicationActivationPolicyProhibited
- } NSApplicationActivationPolicy;
-
- typedef uint32_t NSBackingStoreType;
- enum
- {
- NSBackingStoreRetained = 0,
- NSBackingStoreNonretained = 1,
- NSBackingStoreBuffered = 2
- };
-
- typedef uint32_t NSWindowStyleMask;
- enum
- {
- NSWindowStyleMaskBorderless = 0,
- NSWindowStyleMaskTitled = 1 << 0,
- NSWindowStyleMaskClosable = 1 << 1,
- NSWindowStyleMaskMiniaturizable = 1 << 2,
- NSWindowStyleMaskResizable = 1 << 3,
- NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */
- NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,
- NSWindowStyleMaskFullScreen = 1 << 14,
- NSWindowStyleMaskFullSizeContentView = 1 << 15,
- NSWindowStyleMaskUtilityWindow = 1 << 4,
- NSWindowStyleMaskDocModalWindow = 1 << 6,
- NSWindowStyleMaskNonactivatingPanel = 1 << 7,
- NSWindowStyleMaskHUDWindow = 1 << 13
- };
-
- void* NSArray_objectAtIndex(NSArray* array, NSUInteger index)
- {
- void* func = sel_registerName("objectAtIndex:");
- return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);
- }
-
- void* NSWindow_contentView(NSWindow* window)
- {
- void* func = sel_registerName("contentView");
- return objc_msgSend_id(window, func);
- }
-
- // Defined the magic numbers for Obj-C enums here
- // #define NSApplicationActivationPolicyRegular ((int)0)
- #define NSEventTypeKeyDown ((int)10)
- #define NSEventTypeKeyUp ((int)11)
- #define NSEventTypeFlagsChanged ((int)12)
- #define NSEventTypeScrollWheel ((int)22)
-
- #define SWW_VIEW_CLASS_NAME "swwClass"
-
- /// A reference to NSApp. Always a good idea, seeing has he's probably the most
- /// helpful thing in CocoaLand
- extern id NSApp;
- extern id const NSDefaultRunLoopMode;
-
- typedef struct AppDelegate AppDelegate;
-
- struct AppDelegate
- {
- Class isa;
- id window;
- };
-
- enum
- {
- NSBorderlessWindowMask = 0,
- NSTitledWindowMask = 1 << 0,
- NSClosableWindowMask = 1 << 1,
- NSMiniaturizableWindowMask = 1 << 2,
- NSResizableWindowMask = 1 << 3
- };
-
- typedef struct swwApp swwApp;
-
- /* classes */
- enum
- {
- kNSApplicationClass = 0,
- kNSWindowClass,
- kNSValueClass,
- kNSEventClass,
- kNSDateClass,
- kNSViewClass,
- kNSScreenClass,
- kNSColorClass,
- kNSCursorClass,
- kNSStringClass,
- kNSImageClass,
- kNSImageRepClass,
- kNSGraphicsContextClass,
- kNSBitmapImageRepClass,
- kNSAutoReleasePoolClass,
- kNSArrayClass,
- kNSThreadClass,
- kNSWindowControllerClass,
- kNSClassMax
- };
-
- struct swwApp
- {
- id instance;
- int should_exit;
- int window_count;
-
- // Some key are called *modifier keys* and are not detected by regular key
- // events in Cocoa. Instead, they will trigger a flags changed event.
- // https://developer.apple.com/documentation/appkit/nseventtype/nseventtypeflagschanged?language=objc
- //
- // We have to:
- // 1. check [event modifierFlags] to retrieve the key code,
- // 2. maintain the press/released events on our own.
- char keys[swwKeycode_NUM];
- char buttons[swwButton_NUM];
-
- void* ns_classes[];
- };
-
- swwApp g_app = {NULL, 0, 0, {0}, {0}};
-
- struct swwWindow
- {
- id window;
- id view;
- swwImage* surface;
-
- /* common data */
- swwWindowCallback callbacks;
- void* userdata;
- };
-
- const char swwViewClassName[] = "swwGuiView";
-
- void UpdateLayer(id self, SEL _)
- {
- swwWindow* win = (swwWindow*)GetInstanceVar(self, "win");
- int32_t width = win->surface->width;
- int32_t height = win->surface->height;
- uint8_t* data_ptr = NULL;
- if (gui->fast_gui) {
- data_ptr = reinterpret_cast<uint8_t*>(gui->fast_buf);
- } else {
- auto& img = gui->canvas->img;
- auto& data = gui->img_data;
- data_ptr = data.data();
- for (int j = 0; j < height; j++) {
- for (int i = 0; i < width; i++) {
- int index = 4 * (i + j * width);
- auto pixel = img[i][height - j - 1];
- data[index++] = (uint8_t)(clamp((int32_t)(pixel[0] * 255.f), 0, 255));
- data[index++] = (uint8_t)(clamp((int32_t)(pixel[1] * 255.f), 0, 255));
- data[index++] = (uint8_t)(clamp((int32_t)(pixel[2] * 255.f), 0, 255));
- data[index++] = 255; // alpha
- }
- }
- }
-
- CGDataProviderRef provider =
- CGDataProviderCreateWithData(NULL, data_ptr, gui->img_data_length, NULL);
- CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
- CGImageRef image = CGImageCreate(width, height, 8, 32, width * 4, colorspace,
- kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
- provider, nullptr, true, kCGRenderingIntentDefault);
- // Profiling showed that CGContextDrawImage can be rather slow (~50ms per
- // frame!), so we instead set the image as the content of the view's layer.
- // See also:
- // * slow CGContextDrawImage: https://stackoverflow.com/a/7599794/12003165
- // * CALayer + CGImage: https://stackoverflow.com/a/48310419/12003165
- // * profiling:
- // https://github.com/taichi-dev/taichi/issues/489#issuecomment-589955458
- call(call(gui->view, "layer"), "setContents:", image);
- CGImageRelease(image);
- CGDataProviderRelease(provider);
- CGColorSpaceRelease(colorspace);
- }
-
- Class ViewClass;
- Class AppDelClass;
-
- __attribute__((constructor)) static void initView()
- {
- ViewClass = objc_allocateClassPair((Class)objc_getClass("NSView"), swwViewClassName, 0);
- // There are two ways to update NSView's content, either via "drawRect:" or
- // "UpdateLayer". Updating via layer can be a lot faster, so we use this
- // method. See also:
- // https://developer.apple.com/documentation/appkit/nsview/1483461-wantsupdatelayer?language=objc
- // https://stackoverflow.com/a/51899686/12003165
- //
- // Also, it should be noted that if NSView's layer is enabled (via
- // [view setWantsLyaer:YES]), but "drawRect:" is used, then the content is
- // drawn and cleared rapidly, causing a flickering screen. It seems that the
- // view itself and the underlying layer were overwriting each other's content.
- // https://stackoverflow.com/a/11321521/12003165
- class_addMethod(ViewClass, sel_getUid("updateLayer" /* no colon */), (IMP)UpdateLayer, "v@:");
-
- // Append a property to store the swwWindow instance(swwWindow *)
- // Reference: https://southpeak.github.io/2014/10/25/objective-c-runtime-1/
- const char* property_name = "winhdl";
- const char* ivar_name = "_winhdl";
-
- objc_registerClassPair(ViewClass);
-
- AppDelClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
- Protocol* WinDelProtocol = objc_getProtocol("NSWindowDelegate");
- class_addMethod(AppDelClass, sel_getUid("windowShouldClose:"), (IMP)windowShouldClose, "c@:@");
- class_addProtocol(AppDelClass, WinDelProtocol);
- objc_registerClassPair(AppDelClass);
- }
-
- typedef struct CMPoint
- {
- double x;
- double y;
- } CMPoint;
-
- typedef struct CMSize
- {
- double width;
- double height;
- } CMSize;
-
- typedef struct CMRect
- {
- CMPoint origin;
- CMSize size;
- } CMRect;
-
- void swwApp_Initialize()
- {
- objc_msgSend((id)objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
- assert(NSApp != NULL && "Failed to initialized NSApplication.");
-
- // I finally found how to bring the NSWindow to the front and to handle
- // keyboard events in these posts:
- // https://stackoverflow.com/a/11010614/12003165
- // http://www.cocoawithlove.com/2010/09/minimalist-cocoa-programming.html
- //
- // The problem was that, a Cocoa app without NIB files (app bundle,
- // info.plist, whatever the meta files are) by default has a policy of
- // NSApplicationActivationPolicyProhibited.
- // (https://developer.apple.com/documentation/appkit/nsapplicationactivationpolicy/nsapplicationactivationpolicyprohibited?language=objc)
- objc_msgSend(NSApp, sel_getUid("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
- // This doesn't seem necessary, but in case there's some weird bug causing the
- // Window not to be brought to the front, try enable this.
- // https://stackoverflow.com/a/7460187/12003165
- // objc_msgSend(NSApp, "activateIgnoringOtherApps:", YES);
- g_app.instance = objc_msgSend((id)objc_getClass("AppDelegate"), sel_getUid("alloc"));
- g_app.instance = objc_msgSend(g_app.instance, sel_getUid("init"));
- objc_msgSend(NSApp, sel_getUid("setDelegate:"), g_app.instance);
- }
-
- void swwApp_Cleanup()
- {}
-
- int swwApp_ShouldExit()
- {
- return g_app.should_exit;
- }
-
- void swwApp_PostQuitEvent()
- {
- g_app.should_exit = 1;
- }
-
- void swwApp_PollEventWithTimeout(float timeout)
- {}
-
- void swwApp_PollEvent()
- {}
-
- int swwApp_IsKeyPressed(swwKeycode key)
- {}
-
- int swwApp_IsButtonPressed(swwButton btn)
- {}
-
- swwWindow* swwWindow_Create(const char* title, uint32_t width, uint32_t height)
- {
- swwWindow* o = (swwWindow*)malloc(sizeof(swwWindow));
-
- o->surface = swwImage_Create(width, height, 4);
- o->window = objc_msgSend((id)objc_getClass("NSWindow"), sel_getUid("alloc"));
- CGRect rect = (CGRect){{0, 0}, {(CGFloat)width, (CGFloat)height}};
- objc_msgSend(o->window, sel_getUid("initWithContentRect:styleMask:backing:defer:"), rect,
- (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
- | NSMiniaturizableWindowMask),
- 0, 0);
- o->view = objc_msgSend(objc_msgSend((id)objc_getClass("View"), sel_getUid("alloc")),
- sel_getUid("initWithFrame:"), rect);
- // gui_from_id[view] = this;
- // Needed by NSWindowDelegate
- // gui_from_id[window] = this;
- // Use layer to speed up the draw
- // https://developer.apple.com/documentation/appkit/nsview/1483695-wantslayer?language=objc
- objc_msgSend(o->view, sel_getUid("setWantsLayer:"), 1);
- objc_msgSend(o->window, sel_getUid("setDelegate:"), g_app.instance);
- objc_msgSend(o->window, sel_getUid("setContentView:"), o->view);
- objc_msgSend(o->window, sel_getUid("becomeFirstResponder"));
- objc_msgSend(o->window, sel_getUid("setAcceptsMouseMovedEvents:"), 1);
- objc_msgSend(o->window, sel_getUid("makeKeyAndOrderFront:"), o->window);
-
- // Associate the swwWindow object to the Cocoa Window instance
- SetInstanceVar(o->window, "win", o);
-
- // if (fullscreen)
- // {
- // objc_msgSend(o->window, sel_getUid("toggleFullScreen:"));
- // }
-
- return o;
- }
-
- void swwWindow_Destroy(swwWindow* o)
- {
- swwImage_Destroy(o->surface);
- free(o);
- }
-
- void swwWindow_Present(swwWindow* o)
- {}
-
- uint8_t* swwWindow_LockBuffer(swwWindow* o)
- {}
-
- void swwWindow_UnlockBufferAndPresent(swwWindow* o)
- {}
-
- void swwWindow_SetCallback(swwWindow* o, const swwWindowCallback* callback)
- {}
-
- void swwWindow_SetUserData(swwWindow* o, void* userdata)
- {}
-
- void* swwWindow_GetUserData(swwWindow* o)
- {}
-
- void swwWindow_QueryCursor(swwWindow* o, float* x, float* y)
- {}
-
- extern void NSRectFill(CMRect aRect);
-
- /// This is a strong reference to the class of our custom view,
- /// In case we need it in the future.
- Class ViewClass;
-
- /// This is a simple -drawRect implementation for our class. We could have
- /// used a NSTextField or something of that sort instead, but I felt that this
- /// stuck with the C-based mentality of the application.
- void View_drawRect(id self, SEL _cmd, CMRect rect)
- {
- // make a red objc_msgSend object with its convenience method
- id red = objc_msgSend((id)objc_getClass("NSColor"), sel_getUid("redColor"));
-
- // fill target rect with red, because this is it!
- CMRect rect1 = (CMRect){21, 21, 210, 210};
- objc_msgSend(red, sel_getUid("set"));
- NSRectFill(rect1);
- }
-
- /// Once again we use the (constructor) attribute. generally speaking,
- /// having many of these is a very bad idea, but in a small application
- /// like this, it really shouldn't be that big of an issue.
- __attribute__((constructor)) static void initView()
- {
- /// Once again, just like the app delegate, we tell the runtime to
- /// create a new class, this time a subclass of 'UIView' and named 'View'.
- ViewClass = objc_allocateClassPair((Class)objc_getClass("NSView"), "View", 0);
-
- /// and again, we tell the runtime to add a function called -drawRect:
- /// to our custom view. Note that there is an error in the type-specification
- /// of this method, as I do not know the @encode sequence of 'CGRect' off
- /// of the top of my head. As a result, there is a chance that the rect
- /// parameter of the method may not get passed properly.
- class_addMethod(ViewClass, sel_getUid("drawRect:"), (IMP)View_drawRect, "v@:");
-
- /// And again, we tell the runtime that this class is now valid to be used.
- /// At this point, the application should run and display the screenshot shown
- /// below.
- objc_registerClassPair(ViewClass);
- }
-
- // This is a strong reference to the class of the AppDelegate
- // (same as [AppDelegate class])
- Class AppDelClass;
-
- BOOL AppDel_didFinishLaunching(AppDelegate* self, SEL _cmd, id notification)
- {
- // Create an instance of the window.
- self->window = objc_msgSend((id)objc_getClass("NSWindow"), sel_getUid("alloc"));
-
- objc_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 = objc_msgSend(objc_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.
- objc_msgSend(self->window, sel_getUid("setContentView:"), view);
- objc_msgSend(self->window, sel_getUid("becomeFirstResponder"));
-
- // Shows our window in the bottom-left hand corner of the screen.
- objc_msgSend(self->window, sel_getUid("makeKeyAndOrderFront:"), self);
- return YES;
- }
-
- static void CreateAppDelegate()
- {
- AppDelClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
- class_addMethod(AppDelClass, sel_getUid("applicationDidFinishLaunching:"),
- (IMP)AppDel_didFinishLaunching, "i@:@");
- objc_registerClassPair(AppDelClass);
- }
-
- void RunApplication(void)
- {
- objc_msgSend((id)objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
-
- if (NSApp == NULL) {
- fprintf(stderr, "Failed to initialized NSApplication... terminating...\n");
- return;
- }
-
- 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);
- objc_msgSend(NSApp, sel_getUid("run"));
- }
-
- void swwWindow_GetSize(swwWindow* o, uint32_t* width, uint32_t* height)
- {
- *width = o->surface->width;
- *height = o->surface->height;
- }
-
- swwImage* swwWindow_GetSurface(swwWindow* o)
- {
- return o->surface;
- }
-
- void swwWindow_SetTitle(swwWindow* o, const char* title)
- {
- (void)o;
- (void)title;
- }
-
- /*
- void resize(count_t width, count_t height)
- {
- count_t stride = calculate_stride(width + _extra_pixels);
- count_t size = stride * height;
-
- if (size > _allocated_width) //< size, actually
- {
- uint8_t *memory = new uint8_t[size];
-
- _allocated_width = size;
- swap(_memory, memory);
- delete []memory;
- }
- _width = width;
- _height = height;
- _stride = stride;
- }
-
- void blit(CGContextRef context, int x, int y, count_t width, count_t height)
- const
- {
- count_t stride = calculate_stride(_width + _extra_pixels);
- count_t size = stride * height;
- size_t component_bits = _bpp == bpp32 ? 8 : _bpp == bpp16 ? 5 : 8;
- int format = _bpp == bpp32 ? kCGImageAlphaNoneSkipFirst : kCGImageAlphaNone;
-
- CGDataProviderRef provider = ::CGDataProviderCreateWithData(0, _memory,
- size, 0); CGImageRef image = ::CGImageCreate(width, height, component_bits,
- _bpp, stride, CGColorSpaceCreateDeviceRGB(), format, provider, NULL, FALSE,
- kCGRenderingIntentDefault);
- ::CGDataProviderRelease(provider);
-
- CGRect destination = { { CGFloat(x), CGFloat(y) }, { CGFloat(width),
- CGFloat(height) } };
-
- ::CGContextDrawImage(context, destination, image);
- ::CGImageRelease(image);
- }
-
- int main(int argc, char ** argv)
- {
- CreateAppDelegate();
- RunApplication();
- return EXIT_SUCCESS;
- }
- */
-
- #endif /* OS_DARWIN */
|