From 41ca10496fd7b295acd23f8462c388dd03999344 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Mon, 30 Jul 2018 15:14:49 -0400 Subject: Move graphical programs out of bin I wonder when the last time was something needed -ledit... --- gfx/cocoa.m | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 gfx/cocoa.m (limited to 'gfx/cocoa.m') diff --git a/gfx/cocoa.m b/gfx/cocoa.m new file mode 100644 index 00000000..6c0f0d66 --- /dev/null +++ b/gfx/cocoa.m @@ -0,0 +1,162 @@ +/* Copyright (c) 2018, Curtis McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#import +#import +#import +#import +#import +#import + +#import "gfx.h" + +#define UNUSED __attribute__((unused)) + +@interface BufferView : NSView { + size_t bufSize; + uint32_t *buf; + CGColorSpaceRef colorSpace; + CGDataProviderRef dataProvider; +} +@end + +@implementation BufferView +- (instancetype) initWithFrame: (NSRect) frameRect { + colorSpace = CGColorSpaceCreateDeviceRGB(); + return [super initWithFrame: frameRect]; +} + +- (void) setWindowTitle { + [[self window] setTitle: [NSString stringWithUTF8String: status()]]; +} + +- (void) draw { + draw(buf, [self frame].size.width, [self frame].size.height); + [self setNeedsDisplay: YES]; +} + +- (void) setFrameSize: (NSSize) newSize { + [super setFrameSize: newSize]; + size_t newBufSize = 4 * newSize.width * newSize.height; + if (newBufSize > bufSize) { + bufSize = newBufSize; + buf = malloc(bufSize); + if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize); + CGDataProviderRelease(dataProvider); + dataProvider = CGDataProviderCreateWithData(NULL, buf, bufSize, NULL); + } + [self draw]; +} + +- (void) drawRect: (NSRect) UNUSED dirtyRect { + NSSize size = [self frame].size; + CGContextRef ctx = [[NSGraphicsContext currentContext] CGContext]; + CGImageRef image = CGImageCreate( + size.width, size.height, + 8, 32, 4 * size.width, + colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, + dataProvider, + NULL, false, kCGRenderingIntentDefault + ); + CGContextDrawImage(ctx, [self frame], image); + CGImageRelease(image); +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (void) keyDown: (NSEvent *) event { + char in; + BOOL converted = [ + [event characters] + getBytes: &in + maxLength: 1 + usedLength: NULL + encoding: NSASCIIStringEncoding + options: 0 + range: NSMakeRange(0, 1) + remainingRange: NULL + ]; + if (converted) { + if (!input(in)) { + [NSApp terminate: self]; + } + [self draw]; + [self setWindowTitle]; + } +} +@end + +@interface Delegate : NSObject +@end + +@implementation Delegate +- (BOOL) applicationShouldTerminateAfterLastWindowClosed: + (NSApplication *) UNUSED sender { + return YES; +} +@end + +int main(int argc, char *argv[]) { + int error = init(argc, argv); + if (error) return error; + + [NSApplication sharedApplication]; + [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; + [NSApp setDelegate: [Delegate new]]; + + NSString *name = [[NSProcessInfo processInfo] processName]; + NSMenu *menu = [NSMenu new]; + [ + menu + addItemWithTitle: @"Close Window" + action: @selector(performClose:) + keyEquivalent: @"w" + ]; + [menu addItem: [NSMenuItem separatorItem]]; + [ + menu + addItemWithTitle: [@"Quit " stringByAppendingString: name] + action: @selector(terminate:) + keyEquivalent: @"q" + ]; + NSMenuItem *menuItem = [NSMenuItem new]; + [menuItem setSubmenu: menu]; + [NSApp setMainMenu: [NSMenu new]]; + [[NSApp mainMenu] addItem: menuItem]; + + NSUInteger style = NSTitledWindowMask + | NSClosableWindowMask + | NSMiniaturizableWindowMask + | NSResizableWindowMask; + NSWindow *window = [ + [NSWindow alloc] + initWithContentRect: NSMakeRect(0, 0, 800, 600) + styleMask: style + backing: NSBackingStoreBuffered + defer: YES + ]; + [window center]; + + BufferView *view = [[BufferView alloc] initWithFrame: [window frame]]; + [window setContentView: view]; + [view setWindowTitle]; + + [window makeKeyAndOrderFront: nil]; + [NSApp activateIgnoringOtherApps: YES]; + [NSApp run]; +} -- cgit 1.4.1