332 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
#import "BasicOpenGLView.h"
 | 
						|
 | 
						|
#import <Cocoa/Cocoa.h>
 | 
						|
 | 
						|
#include <kinc/backend/HIDManager.h>
 | 
						|
#include <kinc/graphics4/graphics.h>
 | 
						|
#include <kinc/input/keyboard.h>
 | 
						|
#include <kinc/log.h>
 | 
						|
#include <kinc/system.h>
 | 
						|
#include <kinc/window.h>
 | 
						|
 | 
						|
#include "windowdata.h"
 | 
						|
 | 
						|
#include <kinc/backend/windowdata.h>
 | 
						|
 | 
						|
bool withAutoreleasepool(bool (*f)(void)) {
 | 
						|
	@autoreleasepool {
 | 
						|
		return f();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
extern const char *macgetresourcepath(void);
 | 
						|
 | 
						|
const char *macgetresourcepath(void) {
 | 
						|
	return [[[NSBundle mainBundle] resourcePath] cStringUsingEncoding:NSUTF8StringEncoding];
 | 
						|
}
 | 
						|
 | 
						|
@interface KincApplication : NSApplication {
 | 
						|
}
 | 
						|
- (void)terminate:(id)sender;
 | 
						|
@end
 | 
						|
 | 
						|
@interface KincAppDelegate : NSObject <NSWindowDelegate> {
 | 
						|
}
 | 
						|
- (void)windowWillClose:(NSNotification *)notification;
 | 
						|
- (void)windowDidResize:(NSNotification *)notification;
 | 
						|
- (void)windowWillMiniaturize:(NSNotification *)notification;
 | 
						|
- (void)windowDidDeminiaturize:(NSNotification *)notification;
 | 
						|
- (void)windowDidResignMain:(NSNotification *)notification;
 | 
						|
- (void)windowDidBecomeMain:(NSNotification *)notification;
 | 
						|
@end
 | 
						|
 | 
						|
static NSApplication *myapp;
 | 
						|
static NSWindow *window;
 | 
						|
static BasicOpenGLView *view;
 | 
						|
static KincAppDelegate *delegate;
 | 
						|
static struct HIDManager *hidManager;
 | 
						|
 | 
						|
/*struct KoreWindow : public KoreWindowBase {
 | 
						|
    NSWindow* handle;
 | 
						|
    BasicOpenGLView* view;
 | 
						|
 | 
						|
    KoreWindow(NSWindow* handle, BasicOpenGLView* view, int x, int y, int width, int height)
 | 
						|
        : KoreWindowBase(x, y, width, height), handle(handle), view(view) {
 | 
						|
        ::view = view;
 | 
						|
    }
 | 
						|
};*/
 | 
						|
 | 
						|
#ifdef KINC_METAL
 | 
						|
CAMetalLayer *getMetalLayer(void) {
 | 
						|
	return [view metalLayer];
 | 
						|
}
 | 
						|
 | 
						|
id getMetalDevice(void) {
 | 
						|
	return [view metalDevice];
 | 
						|
}
 | 
						|
 | 
						|
id getMetalLibrary(void) {
 | 
						|
	return [view metalLibrary];
 | 
						|
}
 | 
						|
 | 
						|
id getMetalQueue(void) {
 | 
						|
	return [view metalQueue];
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
bool kinc_internal_handle_messages(void) {
 | 
						|
	NSEvent *event = [myapp nextEventMatchingMask:NSAnyEventMask
 | 
						|
	                                    untilDate:[NSDate distantPast]
 | 
						|
	                                       inMode:NSDefaultRunLoopMode
 | 
						|
	                                      dequeue:YES]; // distantPast: non-blocking
 | 
						|
	if (event != nil) {
 | 
						|
		[myapp sendEvent:event];
 | 
						|
		[myapp updateWindows];
 | 
						|
	}
 | 
						|
 | 
						|
	// Sleep for a frame to limit the calls when the window is not visible.
 | 
						|
	if (!window.visible) {
 | 
						|
		[NSThread sleepForTimeInterval:1.0 / 60];
 | 
						|
	}
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void swapBuffersMac(int windowId) {
 | 
						|
#ifndef KINC_METAL
 | 
						|
	[windows[windowId].view switchBuffers];
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static int createWindow(kinc_window_options_t *options) {
 | 
						|
	int width = options->width / [[NSScreen mainScreen] backingScaleFactor];
 | 
						|
	int height = options->height / [[NSScreen mainScreen] backingScaleFactor];
 | 
						|
	int styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable;
 | 
						|
	if ((options->window_features & KINC_WINDOW_FEATURE_RESIZEABLE) || (options->window_features & KINC_WINDOW_FEATURE_MAXIMIZABLE)) {
 | 
						|
		styleMask |= NSWindowStyleMaskResizable;
 | 
						|
	}
 | 
						|
	if (options->window_features & KINC_WINDOW_FEATURE_MINIMIZABLE) {
 | 
						|
		styleMask |= NSWindowStyleMaskMiniaturizable;
 | 
						|
	}
 | 
						|
 | 
						|
	view = [[BasicOpenGLView alloc] initWithFrame:NSMakeRect(0, 0, width, height)];
 | 
						|
	[view registerForDraggedTypes:[NSArray arrayWithObjects:NSURLPboardType, nil]];
 | 
						|
	window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height) styleMask:styleMask backing:NSBackingStoreBuffered defer:TRUE];
 | 
						|
	delegate = [KincAppDelegate alloc];
 | 
						|
	[window setDelegate:delegate];
 | 
						|
	[window setTitle:[NSString stringWithCString:options->title encoding:NSUTF8StringEncoding]];
 | 
						|
	[window setAcceptsMouseMovedEvents:YES];
 | 
						|
	[[window contentView] addSubview:view];
 | 
						|
	[window center];
 | 
						|
 | 
						|
	windows[windowCounter].handle = window;
 | 
						|
	windows[windowCounter].view = view;
 | 
						|
 | 
						|
	[window makeKeyAndOrderFront:nil];
 | 
						|
 | 
						|
	if (options->mode == KINC_WINDOW_MODE_FULLSCREEN || options->mode == KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
 | 
						|
		[window toggleFullScreen:nil];
 | 
						|
		windows[windowCounter].fullscreen = true;
 | 
						|
	}
 | 
						|
 | 
						|
	return windowCounter++;
 | 
						|
}
 | 
						|
 | 
						|
int kinc_count_windows(void) {
 | 
						|
	return windowCounter;
 | 
						|
}
 | 
						|
 | 
						|
void kinc_window_change_window_mode(int window_index, kinc_window_mode_t mode) {
 | 
						|
	switch (mode) {
 | 
						|
	case KINC_WINDOW_MODE_WINDOW:
 | 
						|
		if (windows[window_index].fullscreen) {
 | 
						|
			[window toggleFullScreen:nil];
 | 
						|
			windows[window_index].fullscreen = false;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case KINC_WINDOW_MODE_FULLSCREEN:
 | 
						|
	case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
 | 
						|
		if (!windows[window_index].fullscreen) {
 | 
						|
			[window toggleFullScreen:nil];
 | 
						|
			windows[window_index].fullscreen = true;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void kinc_window_set_close_callback(int window, bool (*callback)(void *), void *data) {
 | 
						|
	windows[window].closeCallback = callback;
 | 
						|
	windows[window].closeCallbackData = data;
 | 
						|
}
 | 
						|
 | 
						|
static void addMenubar(void) {
 | 
						|
	NSString *appName = [[NSProcessInfo processInfo] processName];
 | 
						|
 | 
						|
	NSMenu *appMenu = [NSMenu new];
 | 
						|
	NSString *quitTitle = [@"Quit " stringByAppendingString:appName];
 | 
						|
	NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle:quitTitle action:@selector(terminate:) keyEquivalent:@"q"];
 | 
						|
	[appMenu addItem:quitMenuItem];
 | 
						|
 | 
						|
	NSMenuItem *appMenuItem = [NSMenuItem new];
 | 
						|
	[appMenuItem setSubmenu:appMenu];
 | 
						|
 | 
						|
	NSMenu *menubar = [NSMenu new];
 | 
						|
	[menubar addItem:appMenuItem];
 | 
						|
	[NSApp setMainMenu:menubar];
 | 
						|
}
 | 
						|
 | 
						|
#ifdef KINC_KONG
 | 
						|
void kong_init(void);
 | 
						|
#endif
 | 
						|
 | 
						|
int kinc_init(const char *name, int width, int height, kinc_window_options_t *win, kinc_framebuffer_options_t *frame) {
 | 
						|
	@autoreleasepool {
 | 
						|
		myapp = [KincApplication sharedApplication];
 | 
						|
		[myapp finishLaunching];
 | 
						|
		[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
 | 
						|
		NSApp.activationPolicy = NSApplicationActivationPolicyRegular;
 | 
						|
 | 
						|
		hidManager = (struct HIDManager *)malloc(sizeof(struct HIDManager));
 | 
						|
		HIDManager_init(hidManager);
 | 
						|
		addMenubar();
 | 
						|
	}
 | 
						|
 | 
						|
	// System::_init(name, width, height, &win, &frame);
 | 
						|
	kinc_window_options_t defaultWindowOptions;
 | 
						|
	if (win == NULL) {
 | 
						|
		kinc_window_options_set_defaults(&defaultWindowOptions);
 | 
						|
		win = &defaultWindowOptions;
 | 
						|
	}
 | 
						|
 | 
						|
	kinc_framebuffer_options_t defaultFramebufferOptions;
 | 
						|
	if (frame == NULL) {
 | 
						|
		kinc_framebuffer_options_set_defaults(&defaultFramebufferOptions);
 | 
						|
		frame = &defaultFramebufferOptions;
 | 
						|
	}
 | 
						|
 | 
						|
	win->width = width;
 | 
						|
	win->height = height;
 | 
						|
	if (win->title == NULL) {
 | 
						|
		win->title = name;
 | 
						|
	}
 | 
						|
 | 
						|
	int windowId = createWindow(win);
 | 
						|
	kinc_g4_internal_init();
 | 
						|
	kinc_g4_internal_init_window(windowId, frame->depth_bits, frame->stencil_bits, true);
 | 
						|
 | 
						|
#ifdef KINC_KONG
 | 
						|
	kong_init();
 | 
						|
#endif
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int kinc_window_width(int window_index) {
 | 
						|
	NSWindow *window = windows[window_index].handle;
 | 
						|
	float scale = [window backingScaleFactor];
 | 
						|
	return [[window contentView] frame].size.width * scale;
 | 
						|
}
 | 
						|
 | 
						|
int kinc_window_height(int window_index) {
 | 
						|
	NSWindow *window = windows[window_index].handle;
 | 
						|
	float scale = [window backingScaleFactor];
 | 
						|
	return [[window contentView] frame].size.height * scale;
 | 
						|
}
 | 
						|
 | 
						|
NSWindow *kinc_get_mac_window_handle(int window_index) {
 | 
						|
	return windows[window_index].handle;
 | 
						|
}
 | 
						|
 | 
						|
void kinc_load_url(const char *url) {
 | 
						|
	[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithUTF8String:url]]];
 | 
						|
}
 | 
						|
 | 
						|
static char language[3];
 | 
						|
 | 
						|
const char *kinc_language(void) {
 | 
						|
	NSString *nsstr = [[NSLocale preferredLanguages] objectAtIndex:0];
 | 
						|
	const char *lang = [nsstr UTF8String];
 | 
						|
	language[0] = lang[0];
 | 
						|
	language[1] = lang[1];
 | 
						|
	language[2] = 0;
 | 
						|
	return language;
 | 
						|
}
 | 
						|
 | 
						|
void kinc_internal_shutdown(void) {}
 | 
						|
 | 
						|
static const char *getSavePath(void) {
 | 
						|
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
 | 
						|
	NSString *resolvedPath = [paths objectAtIndex:0];
 | 
						|
	NSString *appName = [NSString stringWithUTF8String:kinc_application_name()];
 | 
						|
	resolvedPath = [resolvedPath stringByAppendingPathComponent:appName];
 | 
						|
 | 
						|
	NSFileManager *fileMgr = [[NSFileManager alloc] init];
 | 
						|
 | 
						|
	NSError *error;
 | 
						|
	[fileMgr createDirectoryAtPath:resolvedPath withIntermediateDirectories:YES attributes:nil error:&error];
 | 
						|
 | 
						|
	resolvedPath = [resolvedPath stringByAppendingString:@"/"];
 | 
						|
	return [resolvedPath cStringUsingEncoding:NSUTF8StringEncoding];
 | 
						|
}
 | 
						|
 | 
						|
const char *kinc_internal_save_path(void) {
 | 
						|
	return getSavePath();
 | 
						|
}
 | 
						|
 | 
						|
#ifndef KINC_NO_MAIN
 | 
						|
int main(int argc, char **argv) {
 | 
						|
	return kickstart(argc, argv);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
@implementation KincApplication
 | 
						|
 | 
						|
- (void)terminate:(id)sender {
 | 
						|
	kinc_stop();
 | 
						|
}
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
@implementation KincAppDelegate
 | 
						|
- (BOOL)windowShouldClose:(NSWindow *)sender {
 | 
						|
	if (windows[0].closeCallback != NULL) {
 | 
						|
		if (windows[0].closeCallback(windows[0].closeCallbackData)) {
 | 
						|
			return YES;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
			return NO;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return YES;
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowWillClose:(NSNotification *)notification {
 | 
						|
	kinc_stop();
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowDidResize:(NSNotification *)notification {
 | 
						|
	NSWindow *window = [notification object];
 | 
						|
	NSSize size = [[window contentView] frame].size;
 | 
						|
	[view resize:size];
 | 
						|
	if (windows[0].resizeCallback != NULL) {
 | 
						|
		windows[0].resizeCallback(size.width, size.height, windows[0].resizeCallbackData);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowWillMiniaturize:(NSNotification *)notification {
 | 
						|
	kinc_internal_background_callback();
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowDidDeminiaturize:(NSNotification *)notification {
 | 
						|
	kinc_internal_foreground_callback();
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowDidResignMain:(NSNotification *)notification {
 | 
						|
	kinc_internal_pause_callback();
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowDidBecomeMain:(NSNotification *)notification {
 | 
						|
	kinc_internal_resume_callback();
 | 
						|
}
 | 
						|
 | 
						|
@end
 |