forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			332 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			332 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			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 |