Added first version of Mac implementation
This commit is contained in:
parent
1bc99c1547
commit
4d50ed3fe2
63
include/MiniFB.h
Normal file
63
include/MiniFB.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef _MINIFB_H_
|
||||
#define _MINIFB_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
MFB_KEY_ESC = 0x18,
|
||||
MFB_KEY_A = 0x41,
|
||||
MFB_KEY_B = 0x42,
|
||||
MFB_KEY_C = 0x43,
|
||||
MFB_KEY_D = 0x44,
|
||||
MFB_KEY_E = 0x45,
|
||||
MFB_KEY_F = 0x46,
|
||||
MFB_KEY_G = 0x47,
|
||||
MFB_KEY_H = 0x48,
|
||||
MFB_KEY_I = 0x49,
|
||||
MFB_KEY_J = 0x4A,
|
||||
MFB_KEY_K = 0x4B,
|
||||
MFB_KEY_L = 0x4C,
|
||||
MFB_KEY_M = 0x4D,
|
||||
MFB_KEY_N = 0x4E,
|
||||
MFB_KEY_O = 0x4F,
|
||||
MFB_KEY_P = 0x50,
|
||||
MFB_KEY_Q = 0x51,
|
||||
MFB_KEY_R = 0x52,
|
||||
MFB_KEY_S = 0x53,
|
||||
MFB_KEY_T = 0x54,
|
||||
MFB_KEY_U = 0x55,
|
||||
MFB_KEY_V = 0x56,
|
||||
MFB_KEY_W = 0x57,
|
||||
MFB_KEY_X = 0x58,
|
||||
MFB_KEY_Y = 0x59,
|
||||
MFB_KEY_Z = 0x5A,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MFB_RGB(r, g, b) (((unsigned int)r) << 16) | (((unsigned int)g) << 8) | b
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create a window
|
||||
int mfb_open(const char* name, int width, int height);
|
||||
|
||||
// Update the display. Input buffer is assumed to be a 32-bit buffer of the size given in the open call
|
||||
// Will return -1 on error, 0 if no key has been pressed otherwise the key code matching the keycode enum
|
||||
int mfb_update(void* buffer);
|
||||
|
||||
// Close the window
|
||||
void mfb_close();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
97
src/macosx/MiniFB.m
Normal file
97
src/macosx/MiniFB.m
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
#include "OSXWindow.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <unistd.h>
|
||||
#include <MiniFB.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* g_updateBuffer = 0;
|
||||
int g_width = 0;
|
||||
int g_height = 0;
|
||||
static NSWindow* window_;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_open(const char* name, int width, int height)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
unsigned int styles = NSResizableWindowMask | NSClosableWindowMask | NSTitledWindowMask;
|
||||
|
||||
NSRect rectangle = NSMakeRect(0, 0, width, height);
|
||||
window_ = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO];
|
||||
|
||||
if (!window_)
|
||||
return 0;
|
||||
|
||||
[window_ setTitle:[NSString stringWithUTF8String:name]];
|
||||
[window_ setReleasedWhenClosed:NO];
|
||||
[window_ performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:YES];
|
||||
|
||||
[window_ center];
|
||||
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
||||
[pool drain];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mfb_close()
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (window_)
|
||||
[window_ close];
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int updateEvents()
|
||||
{
|
||||
int state = 0;
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if (event)
|
||||
{
|
||||
switch ([event type])
|
||||
{
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
{
|
||||
state = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
default :
|
||||
{
|
||||
[NSApp sendEvent:event];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[pool release];
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_update(void* buffer)
|
||||
{
|
||||
g_updateBuffer = buffer;
|
||||
int state = updateEvents();
|
||||
[[window_ contentView] setNeedsDisplay:YES];
|
||||
return state;
|
||||
}
|
10
src/macosx/OSXWindow.h
Normal file
10
src/macosx/OSXWindow.h
Normal file
@ -0,0 +1,10 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
// @class OSXWindowFrameView;
|
||||
|
||||
@interface OSXWindow : NSWindow
|
||||
{
|
||||
NSView* childContentView;
|
||||
}
|
||||
|
||||
@end
|
136
src/macosx/OSXWindow.m
Normal file
136
src/macosx/OSXWindow.m
Normal file
@ -0,0 +1,136 @@
|
||||
#import "OSXWindow.h"
|
||||
#import "OSXWindowFrameView.h"
|
||||
|
||||
@implementation OSXWindow
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (id)initWithContentRect:(NSRect)contentRect
|
||||
styleMask:(NSUInteger)windowStyle
|
||||
backing:(NSBackingStoreType)bufferingType
|
||||
defer:(BOOL)deferCreation
|
||||
{
|
||||
self = [super
|
||||
initWithContentRect:contentRect
|
||||
styleMask:windowStyle
|
||||
backing:bufferingType
|
||||
defer:deferCreation];
|
||||
if (self)
|
||||
{
|
||||
[self setOpaque:YES];
|
||||
[self setBackgroundColor:[NSColor clearColor]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(mainWindowChanged:)
|
||||
name:NSWindowDidBecomeMainNotification
|
||||
object:self];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(mainWindowChanged:)
|
||||
name:NSWindowDidResignMainNotification
|
||||
object:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)setContentSize:(NSSize)newSize
|
||||
{
|
||||
NSSize sizeDelta = newSize;
|
||||
NSSize childBoundsSize = [childContentView bounds].size;
|
||||
sizeDelta.width -= childBoundsSize.width;
|
||||
sizeDelta.height -= childBoundsSize.height;
|
||||
|
||||
OSXWindowFrameView *frameView = [super contentView];
|
||||
NSSize newFrameSize = [frameView bounds].size;
|
||||
newFrameSize.width += sizeDelta.width;
|
||||
newFrameSize.height += sizeDelta.height;
|
||||
|
||||
[super setContentSize:newFrameSize];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)mainWindowChanged:(NSNotification *)aNotification
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)setContentView:(NSView *)aView
|
||||
{
|
||||
if ([childContentView isEqualTo:aView])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSRect bounds = [self frame];
|
||||
bounds.origin = NSZeroPoint;
|
||||
|
||||
OSXWindowFrameView *frameView = [super contentView];
|
||||
if (!frameView)
|
||||
{
|
||||
frameView = [[[OSXWindowFrameView alloc] initWithFrame:bounds] autorelease];
|
||||
|
||||
[super setContentView:frameView];
|
||||
}
|
||||
|
||||
if (childContentView)
|
||||
{
|
||||
[childContentView removeFromSuperview];
|
||||
}
|
||||
childContentView = aView;
|
||||
[childContentView setFrame:[self contentRectForFrameRect:bounds]];
|
||||
[childContentView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[frameView addSubview:childContentView];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (NSView *)contentView
|
||||
{
|
||||
return childContentView;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (BOOL)canBecomeKeyWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (BOOL)canBecomeMainWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (NSRect)contentRectForFrameRect:(NSRect)windowFrame
|
||||
{
|
||||
windowFrame.origin = NSZeroPoint;
|
||||
return NSInsetRect(windowFrame, 0, 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+ (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle
|
||||
{
|
||||
return NSInsetRect(windowContentRect, 0, 0);
|
||||
}
|
||||
|
||||
@end
|
8
src/macosx/OSXWindowFrameView.h
Normal file
8
src/macosx/OSXWindowFrameView.h
Normal file
@ -0,0 +1,8 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface OSXWindowFrameView : NSView
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
50
src/macosx/OSXWindowFrameView.m
Normal file
50
src/macosx/OSXWindowFrameView.m
Normal file
@ -0,0 +1,50 @@
|
||||
#import "OSXWindowFrameView.h"
|
||||
|
||||
@implementation OSXWindowFrameView
|
||||
|
||||
extern void* g_updateBuffer;
|
||||
extern int g_width;
|
||||
extern int g_height;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (NSRect)resizeRect
|
||||
{
|
||||
const CGFloat resizeBoxSize = 16.0;
|
||||
const CGFloat contentViewPadding = 5.5;
|
||||
|
||||
NSRect contentViewRect = [[self window] contentRectForFrameRect:[[self window] frame]];
|
||||
NSRect resizeRect = NSMakeRect(
|
||||
NSMaxX(contentViewRect) + contentViewPadding,
|
||||
NSMinY(contentViewRect) - resizeBoxSize - contentViewPadding,
|
||||
resizeBoxSize,
|
||||
resizeBoxSize);
|
||||
|
||||
return resizeRect;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
if (!g_updateBuffer)
|
||||
return;
|
||||
|
||||
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||
|
||||
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, g_updateBuffer, g_width * g_height * 4, NULL);
|
||||
|
||||
CGImageRef img = CGImageCreate(g_width, g_height, 8, 32, g_width * 4, space, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
|
||||
provider, NULL, false, kCGRenderingIntentDefault);
|
||||
|
||||
CGColorSpaceRelease(space);
|
||||
CGDataProviderRelease(provider);
|
||||
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, g_width, g_height), img);
|
||||
|
||||
CGImageRelease(img);
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user