Move mac-ui into src/

This commit is contained in:
Adam Ierymenko 2015-05-08 12:35:41 -07:00
parent a40192a40b
commit 8594e17f2b
63 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,18 @@
//
// AppDelegate.h
// MacGap
//
// Created by Alex MacCaw on 08/01/2012.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "Classes/ContentView.h"
#import "WindowController.h"
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (retain, nonatomic) WindowController *windowController;
@end

View file

@ -0,0 +1,145 @@
//
// AppDelegate.m
// MacGap
//
// Created by Alex MacCaw on 08/01/2012.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "AppDelegate.h"
#include <sys/stat.h>
#include <sys/types.h>
@implementation AppDelegate
@synthesize windowController;
- (void) applicationWillFinishLaunching:(NSNotification *)aNotification
{
}
-(BOOL)applicationShouldHandleReopen:(NSApplication*)application
hasVisibleWindows:(BOOL)visibleWindows{
if(!visibleWindows){
[self.windowController.window makeKeyAndOrderFront: nil];
}
return YES;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
return YES;
}
- (void) applicationDidFinishLaunching:(NSNotification *)aNotification {
char buf[16384],userAuthTokenPath[4096];
FILE *pf = fopen("/Library/Application Support/ZeroTier/One/zerotier-one.port","r");
long port = 9993; // default
if (pf) {
long n = fread(buf,1,sizeof(buf)-1,pf);
if (n > 0) {
buf[n] = (char)0;
port = strtol(buf,(char **)0,10);
}
fclose(pf);
}
char url[16384];
memset(url,0,sizeof(url));
const char *homeDir = getenv("HOME");
if (homeDir) {
snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir);
pf = fopen(userAuthTokenPath,"r");
if (pf) {
long n = fread(buf,1,sizeof(buf)-1,pf);
if (n > 0) {
buf[n] = (char)0;
snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf);
}
fclose(pf);
}
}
if (!url[0]) {
// Create authorization reference
OSStatus status;
AuthorizationRef authorizationRef;
// AuthorizationCreate and pass NULL as the initial
// AuthorizationRights set so that the AuthorizationRef gets created
// successfully, and then later call AuthorizationCopyRights to
// determine or extend the allowable rights.
// http://developer.apple.com/qa/qa2001/qa1172.html
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
if (status != errAuthorizationSuccess)
{
NSLog(@"Error Creating Initial Authorization: %d", status);
return;
}
// kAuthorizationRightExecute == "system.privilege.admin"
AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
AuthorizationRights rights = {1, &right};
AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
// Call AuthorizationCopyRights to determine or extend the allowable rights.
status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL);
if (status != errAuthorizationSuccess)
{
NSLog(@"Copy Rights Unsuccessful: %d", status);
return;
}
// use rm tool with -rf
char *tool = "/bin/cat";
char *args[] = {"/Library/Application Support/ZeroTier/One/authtoken.secret", NULL};
FILE *pipe = NULL;
status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
if (status != errAuthorizationSuccess)
{
NSLog(@"Error: %d", status);
}
if (pipe) {
long n = (long)fread(buf,1,sizeof(buf)-1,pipe);
if (n > 0) {
buf[n] = (char)0;
snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf);
if (homeDir) {
snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier",homeDir);
mkdir(userAuthTokenPath,0755);
snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One",homeDir);
mkdir(userAuthTokenPath,0755);
snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir);
pf = fopen(userAuthTokenPath,"w");
if (pf) {
fwrite(buf,1,strlen(buf),pf);
fclose(pf);
chmod(userAuthTokenPath,0600);
}
}
}
fclose(pipe);
}
// The only way to guarantee that a credential acquired when you
// request a right is not shared with other authorization instances is
// to destroy the credential. To do so, call the AuthorizationFree
// function with the flag kAuthorizationFlagDestroyRights.
// http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html
status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights);
}
NSString *urlStr = [[NSString alloc] initWithCString:url];
self.windowController = [[WindowController alloc] initWithURL: urlStr];
[self.windowController showWindow: [NSApplication sharedApplication].delegate];
self.windowController.contentView.webView.alphaValue = 1.0;
self.windowController.contentView.alphaValue = 1.0;
[self.windowController showWindow:self];
}
@end

View file

@ -0,0 +1,20 @@
//
// CallbackDelegate.h
// MacGap
//
// Created by Joe Hildebrand on 1/10/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "Command.h"
@interface CallbackDelegate : Command {
}
@property JSObjectRef callback;
- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback;
- (id) call;
- (id) callWithParams:(id)firstOrNil, ... NS_REQUIRES_NIL_TERMINATION;
@end

View file

@ -0,0 +1,168 @@
//
// CallbackDelegate.m
// MacGap
//
// Created by Joe Hildebrand on 1/10/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "CallbackDelegate.h"
#import <JavaScriptCore/JavaScript.h>
@implementation CallbackDelegate
@synthesize callback;
- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback
{
if (!aCallback)
return nil;
if ([aCallback isKindOfClass:[WebUndefined class]])
return nil;
self = [super initWithContext:aContext];
if (!self)
return nil;
callback = [aCallback JSObject];
JSValueProtect(context, callback);
return self;
}
- (void) dealloc
{
if (callback)
{
JSValueUnprotect(context, callback);
callback = nil;
}
}
- (id) objectFromValue:(JSValueRef)val
{
JSStringRef jstr;
NSString *rets;
switch(JSValueGetType(context, val))
{
case kJSTypeUndefined:
case kJSTypeNull:
return nil;
case kJSTypeBoolean:
return [NSNumber numberWithBool:JSValueToBoolean(context, val)];
case kJSTypeNumber:
return [NSNumber numberWithDouble:JSValueToNumber(context, val, NULL)];
case kJSTypeString:
jstr = JSValueToStringCopy(context, val, NULL);
size_t sz = JSStringGetMaximumUTF8CStringSize(jstr);
char *buf = (char*)malloc(sz);
JSStringGetUTF8CString(jstr, buf, sz);
rets = [NSString stringWithUTF8String:buf];
free(buf);
return rets;
case kJSTypeObject:
// TODO: dictionary or something
return nil;
default:
NSAssert(false, @"Invalid JavaScript type");
return nil;
}
}
- (JSValueRef) valueFromObject:(id)obj
{
JSValueRef val = nil;
if (!obj)
{
val = JSValueMakeNull(context);
}
else if ([obj isKindOfClass:[NSString class]])
{
JSStringRef jstr = JSStringCreateWithUTF8CString([obj UTF8String]);
val = JSValueMakeString(context, jstr);
JSStringRelease(jstr);
}
else if ([obj isKindOfClass:[NSNumber class]])
{
val = JSValueMakeNumber(context, [obj doubleValue]);
}
else if ([obj isKindOfClass:[NSDictionary class]])
{
JSObjectRef o = JSObjectMake(context, NULL, NULL);
for (NSString *key in obj)
{
JSStringRef kstr = JSStringCreateWithUTF8CString([key UTF8String]);
JSValueRef v = [self valueFromObject:[obj objectForKey:key]];
JSObjectSetProperty(context, o, kstr, v, kJSPropertyAttributeNone, NULL);
JSStringRelease(kstr);
}
val = o;
}
else if ([obj isKindOfClass:[NSArray class]])
{
NSUInteger pcount = [obj count];
JSValueRef jsArgs[pcount];
NSUInteger i=0;
for (id v in obj)
{
jsArgs[i++] = [self valueFromObject:v];
}
val = JSObjectMakeArray(context, pcount, jsArgs, NULL);
}
else if ([obj isKindOfClass:[NSDate class]])
{
NSTimeInterval secs = [obj timeIntervalSince1970];
JSValueRef jsArgs[1];
// call the Date(milliseconds) constructor in JS
jsArgs[0] = JSValueMakeNumber(context, secs * 1000.0);
val = JSObjectMakeDate(context, 1, jsArgs, NULL);
}
else
{
NSLog(@"Warning: unknown object type for: %@", obj);
val = JSValueMakeUndefined(context);
}
return val;
}
- (id) call
{
NSAssert(callback, @"Callback required");
if (!JSObjectIsFunction(context, callback))
return nil;
JSValueRef jsArgs[0];
JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, 0, jsArgs, NULL);
return [self objectFromValue:ret];
}
- (id) callWithParams:(id)firstOrNil, ...
{
NSAssert(callback, @"Callback required");
if (!JSObjectIsFunction(context, callback))
return nil;
NSUInteger pcount = 0;
id p;
va_list args;
va_start(args, firstOrNil);
for (p=firstOrNil; p; p=va_arg(args, id))
{
pcount++;
}
va_end(args);
JSValueRef jsArgs[pcount];
NSUInteger j = 0;
va_start(args, firstOrNil);
for (p=firstOrNil; p; p=va_arg(args, id))
{
jsArgs[j++] = [self valueFromObject:p];
}
va_end(args);
JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, j, jsArgs, NULL);
return [self objectFromValue:ret];
}
@end

View file

@ -0,0 +1,21 @@
#import <Foundation/Foundation.h>
#import "WindowController.h"
@interface App : NSObject {
}
@property (nonatomic, retain) WebView *webView;
- (id) initWithWebView:(WebView *)view;
- (void) terminate;
- (void) activate;
- (void) hide;
- (void) unhide;
- (void) beep;
- (void) bounce;
- (void) setCustomUserAgent:(NSString *)userAgentString;
- (NSNumber*) systemIdleTime;
@end

View file

@ -0,0 +1,128 @@
#import "App.h"
#import "JSEventHelper.h"
@implementation App
@synthesize webView;
- (id) initWithWebView:(WebView *) view{
self = [super init];
if (self) {
self.webView = view;
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
selector: @selector(receiveSleepNotification:)
name: NSWorkspaceWillSleepNotification object: NULL];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
selector: @selector(receiveWakeNotification:)
name: NSWorkspaceDidWakeNotification object: NULL];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
selector: @selector(receiveActivateNotification:)
name: NSWorkspaceDidActivateApplicationNotification object: NULL];
}
return self;
}
- (void) terminate {
[NSApp terminate:nil];
}
- (void) activate {
[NSApp activateIgnoringOtherApps:YES];
}
- (void) hide {
[NSApp hide:nil];
}
- (void) unhide {
[NSApp unhide:nil];
}
- (void)beep {
NSBeep();
}
- (void) bounce {
[NSApp requestUserAttention:NSInformationalRequest];
}
- (void)setCustomUserAgent:(NSString *)userAgentString {
[self.webView setCustomUserAgent: userAgentString];
}
- (void) open:(NSString*)url {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]];
}
- (void) launch:(NSString *)name {
[[NSWorkspace sharedWorkspace] launchApplication:name];
}
- (void)receiveSleepNotification:(NSNotification*)note{
[JSEventHelper triggerEvent:@"sleep" forWebView:self.webView];
}
- (void) receiveWakeNotification:(NSNotification*)note{
[JSEventHelper triggerEvent:@"wake" forWebView:self.webView];
}
- (void) receiveActivateNotification:(NSNotification*)notification{
NSDictionary* userInfo = [notification userInfo];
NSRunningApplication* runningApplication = [userInfo objectForKey:NSWorkspaceApplicationKey];
if (runningApplication) {
NSMutableDictionary* applicationDidGetFocusDict = [[NSMutableDictionary alloc] initWithCapacity:2];
[applicationDidGetFocusDict setObject:runningApplication.localizedName
forKey:@"localizedName"];
[applicationDidGetFocusDict setObject:[runningApplication.bundleURL absoluteString]
forKey:@"bundleURL"];
[JSEventHelper triggerEvent:@"appActivated" withArgs:applicationDidGetFocusDict forWebView:self.webView];
}
}
/*
To get the elapsed time since the previous input eventkeyboard, mouse, or tabletspecify kCGAnyInputEventType.
*/
- (NSNumber*)systemIdleTime {
CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
return [NSNumber numberWithDouble:timeSinceLastEvent];
}
+ (NSString*) webScriptNameForSelector:(SEL)selector
{
id result = nil;
if (selector == @selector(open:)) {
result = @"open";
} else if (selector == @selector(launch:)) {
result = @"launch";
} else if (selector == @selector(setCustomUserAgent:)) {
result = @"setCustomUserAgent";
} else if (selector == @selector(systemIdleTime)) {
result = @"systemIdleTime";
}
return result;
}
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return NO;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
@end

View file

@ -0,0 +1,18 @@
//
// Command.h
// MacGap
//
// Created by Joe Hildebrand on 1/10/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <Webkit/WebScriptObject.h>
@interface Command : NSObject {
JSContextRef context;
}
- (id) initWithContext:(JSContextRef)aContext;
@end

View file

@ -0,0 +1,28 @@
//
// Command.m
// MacGap
//
// Created by Joe Hildebrand on 1/10/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "Command.h"
#import <JavaScriptCore/JSContextRef.h>
@implementation Command
- (id) initWithContext:(JSContextRef)aContext {
self = [super init];
if (!self)
return nil;
context = aContext;
JSGlobalContextRetain((JSGlobalContextRef)context);
return self;
}
- (void)dealloc
{
if (context)
JSGlobalContextRelease((JSGlobalContextRef)context);
}
@end

View file

@ -0,0 +1,11 @@
#import <Foundation/Foundation.h>
@interface Dock : NSObject {
}
- (void) setBadge:(NSString*)value;
- (NSString *) badge;
@property (readwrite, copy) NSString *badge;
@end

View file

@ -0,0 +1,31 @@
#import "Dock.h"
@implementation Dock
@synthesize badge;
- (void) setBadge:(NSString *)value
{
NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
[tile setBadgeLabel:value];
}
- (NSString *) badge
{
NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
return [tile badgeLabel];
}
#pragma mark WebScripting Protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return NO;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return NO;
}
@end

View file

@ -0,0 +1,31 @@
//
// MenuItemProxy.h
// MacGap
//
// Created by Joe Hildebrand on 1/15/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "Command.h"
#import "CallbackDelegate.h"
@class MenuProxy;
@interface MenuItemProxy : Command {
NSMenuItem *item;
CallbackDelegate *callback;
}
+ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem;
- (MenuProxy*)addSubmenu;
- (void) remove;
- (void) setCallback:(WebScriptObject*)aCallback;
- (void) setKey:(NSString*)keyCommand;
- (void) setTitle:(NSString*)title;
- (void) enable;
- (void) disable;
- (MenuProxy*)submenu;
@end

View file

@ -0,0 +1,150 @@
//
// MenuItemProxy.m
// MacGap
//
// Created by Joe Hildebrand on 1/15/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "MenuItemProxy.h"
#import "MenuProxy.h"
@implementation MenuItemProxy
- (id) initWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem
{
NSAssert(anItem, @"anItem required");
self = [super initWithContext:aContext];
if (!self)
return nil;
item = anItem;
item.representedObject = self;
return self;
}
+ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem
{
MenuItemProxy *proxy = [anItem representedObject];
if (proxy)
{
NSLog(@"MIP Cache hit");
NSAssert([proxy class] == [MenuItemProxy class], @"Bad proxy");
return proxy;
}
return [[MenuItemProxy alloc] initWithContext:aContext andMenuItem:anItem];
}
- (NSString*) description
{
return [item description];
}
- (MenuProxy*)addSubmenu
{
NSMenu *s = [item submenu];
if (!s)
{
s = [[NSMenu alloc] initWithTitle:@"FFFFFFOOOOO"];
[item setSubmenu:s];
}
return [MenuProxy proxyWithContext:context andMenu:s];
}
- (void) remove
{
NSMenu *menu = [item menu];
[menu removeItem:item];
}
- (void)callCallback:(id)sender
{
[callback callWithParams:[sender title], nil];
}
- (void) setCallback:(WebScriptObject*)aCallback
{
NSAssert(item, @"item required");
callback = [[CallbackDelegate alloc] initWithContext:context forCallback:aCallback];
[item setAction:@selector(callCallback:)];
[item setTarget:self];
}
- (void)setKey:(NSString*)keyCommand
{
NSString *aKey = [MenuProxy getKeyFromString:keyCommand];
[item setKeyEquivalent:aKey];
NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand];
[item setKeyEquivalentModifierMask:modifiers];
}
- (void) setTitle:(NSString*)title
{
[item setTitle:title];
}
- (MenuProxy*)submenu;
{
// TODO: make this work as a property
NSMenu *s = [item submenu];
if (!s)
return nil;
return [MenuProxy proxyWithContext:context andMenu:s];
}
- (void) enable
{
[item setEnabled:YES];
}
- (void) disable
{
[item setEnabled:NO];
}
#pragma mark WebScripting protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return [self webScriptNameForSelector:selector] == nil;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector
{
id result = nil;
if (selector == @selector(addSubmenu)) {
result = @"addSubmenu";
}
else if (selector == @selector(remove)) {
result = @"remove";
}
else if (selector == @selector(setCallback:)) {
result = @"setCallback";
}
else if (selector == @selector(setKey:)) {
result = @"setKey";
}
else if (selector == @selector(setTitle:)) {
result = @"setTitle";
}
else if (selector == @selector(submenu)) {
result = @"submenu";
}
else if (selector == @selector(enable)) {
result = @"enable";
}
else if (selector == @selector(disable)) {
result = @"disable";
}
return result;
}
@end

View file

@ -0,0 +1,31 @@
//
// MenuProxy.h
// MacGap
//
// Created by Joe Hildebrand on 1/14/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "Command.h"
@class MenuItemProxy;
@interface MenuProxy : Command {
NSMenu *menu;
}
+ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu;
- (MenuItemProxy*)addItemWithTitle:(NSString*)title
keyEquivalent:(NSString*)aKey
callback:(WebScriptObject*)aCallback
atIndex:(NSInteger)index;
- (MenuItemProxy*)addSeparator;
- (MenuItemProxy*)itemForKey:(id)key;
- (MenuProxy*)removeItem:(id)key;
+ (NSString*)getKeyFromString:(NSString*)keyCommand;
+ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand;
@end

View file

@ -0,0 +1,233 @@
//
// MenuProxy.m
// MacGap
//
// Created by Joe Hildebrand on 1/14/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import <objc/runtime.h>
#import <JavaScriptCore/JavaScript.h>
#import "MenuProxy.h"
#import "MenuItemProxy.h"
static char REPRESENTED_OBJECT;
@interface NSMenu (represented)
@property (strong) id representedObject;
@end
@implementation NSMenu (represented)
- (id) representedObject
{
return objc_getAssociatedObject(self, &REPRESENTED_OBJECT);
}
- (void) setRepresentedObject:(id)representedObject
{
objc_setAssociatedObject(self,
&REPRESENTED_OBJECT,
representedObject,
OBJC_ASSOCIATION_RETAIN);
}
@end
@implementation MenuProxy
- (id) initWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu
{
self = [super initWithContext:aContext];
if (!self)
return nil;
menu = aMenu;
menu.representedObject = self;
return self;
}
+ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu
{
// singleton-ish.
MenuProxy *ret = [aMenu representedObject];
if (ret)
{
NSLog(@"MP cache hit");
return ret;
}
return [[MenuProxy alloc] initWithContext:aContext andMenu:aMenu];
}
- (void) dealloc
{
menu.representedObject = nil;
}
- (NSString*) description
{
return [menu description];
}
static BOOL isNullish(id o)
{
if (!o)
return YES;
if ([o isKindOfClass:[WebUndefined class]])
return YES;
return NO;
}
- (MenuItemProxy*)addItemWithTitle:(NSString*)title
keyEquivalent:(NSString*)keyCommand
callback:(WebScriptObject*)aCallback
atIndex:(NSInteger)index
{
if (isNullish(title))
title = @"";
NSString *aKey = [MenuProxy getKeyFromString:keyCommand];
NSMenuItem *item = nil;
if(index) {
item = [menu insertItemWithTitle:title action:nil keyEquivalent:aKey atIndex:index ];
} else {
item = [menu addItemWithTitle:title action:nil keyEquivalent:aKey ];
}
// Set the modifiers.
NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand];
[item setKeyEquivalentModifierMask:modifiers];
if(!menu.supermenu) {
NSMenu *s = [[NSMenu alloc] initWithTitle:title];
[item setSubmenu:s];
}
MenuItemProxy *mip = [MenuItemProxy proxyWithContext:context andMenuItem:item];
if (!isNullish(aCallback))
[mip setCallback:aCallback];
return mip;
}
+ (NSString*)getKeyFromString:(NSString*)keyCommand {
if (isNullish(keyCommand))
keyCommand = @"";
// Obtain the key (if there are modifiers, it will be the last character).
NSString *aKey = @"";
if ([keyCommand length] > 0) {
aKey = [keyCommand substringFromIndex:[keyCommand length] - 1];
}
return aKey;
}
+ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand {
// aKeys may optionally specify one or more modifiers.
NSUInteger modifiers = 0;
if ([keyCommand rangeOfString:@"caps"].location != NSNotFound) modifiers += NSAlphaShiftKeyMask;
if ([keyCommand rangeOfString:@"shift"].location != NSNotFound) modifiers += NSShiftKeyMask;
if ([keyCommand rangeOfString:@"cmd"].location != NSNotFound) modifiers += NSCommandKeyMask;
if ([keyCommand rangeOfString:@"ctrl"].location != NSNotFound) modifiers += NSControlKeyMask;
if ([keyCommand rangeOfString:@"opt"].location != NSNotFound) modifiers += NSAlternateKeyMask;
if ([keyCommand rangeOfString:@"alt"].location != NSNotFound) modifiers += NSAlternateKeyMask;
return modifiers;
}
- (MenuItemProxy*)addSeparator
{
NSMenuItem *sep = [NSMenuItem separatorItem];
[menu addItem:sep];
return [MenuItemProxy proxyWithContext:context andMenuItem:sep];
}
- (MenuItemProxy*)itemForKey:(id)key
{
if (isNullish(key))
return nil;
NSMenuItem *item = nil;
if ([key isKindOfClass:[NSNumber class]])
{
item = [menu itemAtIndex:[key intValue]];
}
else if ([key isKindOfClass:[NSString class]])
{
item = [menu itemWithTitle:key];
if (!item)
{
// Try again, with ... appended. e.g. "Save..."
item = [menu itemWithTitle:
[key stringByAppendingString:@"\u2026"]];
}
}
if (!item)
return nil;
return [MenuItemProxy proxyWithContext:context andMenuItem:item];
}
- (MenuProxy*)removeItem:(id)key
{
if (isNullish(key))
return nil;
NSMenuItem *item = nil;
if ([key isKindOfClass:[NSNumber class]])
{
item = [menu itemAtIndex:[key intValue]];
}
else if ([key isKindOfClass:[NSString class]])
{
item = [menu itemWithTitle:key];
if (!item)
{
// Try again, with ... appended. e.g. "Save..."
item = [menu itemWithTitle:
[key stringByAppendingString:@"\u2026"]];
}
}
if (!item)
return nil;
[menu removeItem:item];
return [MenuProxy proxyWithContext:context andMenu:menu];
}
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return [self webScriptNameForSelector:selector] == nil;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector
{
id result = nil;
if (selector == @selector(addItemWithTitle:keyEquivalent:callback:atIndex:)) {
result = @"addItem";
}
else if (selector == @selector(addSeparator)) {
result = @"addSeparator";
}
else if (selector == @selector(itemForKey:)) {
result = @"getItem";
}
else if (selector == @selector(removeItem:)) {
result = @"removeMenu";
}
return result;
}
@end

View file

@ -0,0 +1,26 @@
//
// Notice.h
// MacGap
//
// Created by Christian Sullivan on 7/26/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "WindowController.h"
#define APP_NOTICE_NOTIFICATION @"Notice"
@interface Notice : NSObject <NSUserNotificationCenterDelegate> {
}
@property (nonatomic, retain) WebView *webView;
- (id) initWithWebView:(WebView *)view;
- (void) notify:(NSDictionary*)message;
- (void) close:(NSString*)notificationId;
+ (BOOL) available;
@end

View file

@ -0,0 +1,108 @@
//
// Notice.m
// MacGap
//
// Created by Christian Sullivan on 7/26/12.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "Notice.h"
#import "JSEventHelper.h"
@implementation Notice
- (id) initWithWebView:(WebView*)view
{
if(self = [super init]) {
self.webView = view;
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
}
return self;
}
- (void) notify:(NSDictionary *)message {
NSUserNotification *notification = [[NSUserNotification alloc] init];
[notification setTitle:[message valueForKey:@"title"]];
[notification setInformativeText:[message valueForKey:@"content"]];
[notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]];
BOOL playSound = true; // optional parameter, false only when {sound: false}
@try {
NSNumber *s = [message valueForKey:@"sound"];
if ([[s className] isEqual: @"__NSCFBoolean"]) {
playSound = [s boolValue];
}
}
@catch (NSException *exception) {
}
if (playSound) {
[notification setSoundName:NSUserNotificationDefaultSoundName];
}
NSString *id = @""; // optional, needed for close
@try {
id = [message valueForKey:@"id"];
}
@catch (NSException *exception) {
}
[notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:id, @"id", nil]];
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
[center scheduleNotification:notification];
}
// close all notifications with id == notificationId or close all notifications if notificationId == "*"
- (void) close:(NSString*)notificationId {
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
for(NSUserNotification * deliveredNote in center.deliveredNotifications) {
if ([notificationId isEqualToString:@"*"] || [deliveredNote.userInfo[@"id"] isEqualToString:notificationId]) {
[center removeDeliveredNotification: deliveredNote];
}
}
}
+ (BOOL) available {
if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)])
return YES;
return NO;
}
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSString *notificationId = [notification.userInfo valueForKey:@"id"];
[JSEventHelper triggerEvent:@"macgap.notify.activated" forDetail:notificationId forWebView:self.webView];
}
#pragma mark WebScripting Protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
BOOL result = YES;
if (selector == @selector(notify:))
result = NO;
if (selector == @selector(close:))
result = NO;
return result;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector
{
id result = nil;
if (selector == @selector(notify:)) {
result = @"notify";
}
if (selector == @selector(close:)) {
result = @"close";
}
return result;
}
// right now exclude all properties (eg keys)
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
@end

View file

@ -0,0 +1,21 @@
#import <Foundation/Foundation.h>
@interface Path : NSObject {
}
- (NSString *) application;
- (NSString *) resource;
- (NSString *) documents;
- (NSString *) library;
- (NSString *) home;
- (NSString *) temp;
@property (readonly,copy) NSString* application;
@property (readonly,copy) NSString* resource;
@property (readonly,copy) NSString* documents;
@property (readonly,copy) NSString* library;
@property (readonly,copy) NSString* home;
@property (readonly,copy) NSString* temp;
@end

View file

@ -0,0 +1,53 @@
#import "Path.h"
@implementation Path
@synthesize application;
@synthesize resource;
@synthesize documents;
@synthesize library;
@synthesize home;
@synthesize temp;
- (NSString *)application {
return [[NSBundle mainBundle] bundlePath];
}
- (NSString *)resource {
return [[NSBundle mainBundle] resourcePath];
}
- (NSString *)documents {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [paths objectAtIndex:0];
}
- (NSString *)library {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSLog( @"%@", paths );
return [paths objectAtIndex:0];
}
- (NSString *)home {
return NSHomeDirectory();
}
- (NSString *)temp {
return NSTemporaryDirectory();
}
#pragma mark WebScripting Protocol
/* checks whether a selector is acceptable to be called from JavaScript */
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return NO;
}
// right now exclude all properties (eg keys)
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return NO;
}
@end

View file

@ -0,0 +1,17 @@
#import <Cocoa/Cocoa.h>
#import "Command.h"
#import "CallbackDelegate.h"
@interface Sound : Command {
}
// pending callbacks for sounds being played, to keep
// ARC from freeing them too early
@property (nonatomic, strong) NSMutableSet *pending;
- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback;
- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback;
@end

View file

@ -0,0 +1,97 @@
#import "Sound.h"
@interface PlayDelegate : CallbackDelegate <NSSoundDelegate> {
}
@property (nonatomic, weak) Sound *sound;
- (id) initWithContext:(JSContextRef)aContext
forCallback:(WebScriptObject*)aCallback
withSound:(Sound*)aSound;
@end
@implementation PlayDelegate
@synthesize sound;
- (id) initWithContext:(JSContextRef)aContext
forCallback:(WebScriptObject*)aCallback
withSound:(Sound*)aSound
{
self = [super initWithContext:aContext forCallback:aCallback];
if (!self)
return nil;
sound = aSound;
return self;
}
- (void)sound:(NSSound *)aSound didFinishPlaying:(BOOL)finishedPlaying {
[self callWithParams:[aSound name], nil];
[sound.pending removeObject:self];
}
@end
@implementation Sound
@synthesize pending;
- (id) initWithContext:(JSContextRef)aContext {
self = [super initWithContext:aContext];
if (!self) {
return nil;
}
pending = [NSMutableSet new];
return self;
}
- (void) playSound:(NSSound*)sound onComplete:(WebScriptObject*)callback {
if (callback != (id)[WebUndefined undefined]) {
PlayDelegate *d = [[PlayDelegate alloc] initWithContext:context
forCallback:callback
withSound:self];
[pending addObject:d];
[sound setDelegate:d];
}
[sound play];
}
- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback {
NSURL* fileUrl = [NSURL fileURLWithPath:[[Utils sharedInstance] pathForResource:file]];
DebugNSLog(@"Sound file:%@", [fileUrl description]);
NSSound* sound = [[NSSound alloc] initWithContentsOfURL:fileUrl byReference:YES];
[self playSound:sound onComplete:callback];
}
- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback {
NSSound *systemSound = [NSSound soundNamed:name];
[self playSound:systemSound onComplete:callback];
}
#pragma mark WebScripting Protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
return [self webScriptNameForSelector:selector] == nil;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name {
return YES;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector {
id result = nil;
if (selector == @selector(play:onComplete:)) {
result = @"play";
}
else if (selector == @selector(playSystem:onComplete:)) {
result = @"playSystem";
}
return result;
}
@end

View file

@ -0,0 +1,43 @@
//
// UserDefaults.h
// MacGap
//
// Created by Jeff Hanbury on 16/04/2014.
// Copyright (c) 2014 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "WindowController.h"
@interface UserDefaults : NSObject
@property (nonatomic, retain) WebView *webView;
- (id) initWithWebView:(WebView *)view;
- (NSString*) getMyDefaults;
- (NSDictionary*) myDefaultsDictionary;
- (void) removeObjectForKey:(NSString*)key;
- (NSArray*) getUserDefaultsKeys;
- (NSString*) addPrefix:(NSString*)key;
- (void) setString:(NSString*)key withValue:(NSString*)value;
- (NSString*) getString:(NSString*)key;
- (void) setInteger:(NSString*)key withValue:(NSString*)value;
- (NSNumber*) getInteger:(NSString*)key;
- (void) setBool:(NSString*)key withValue:(NSString*)value;
- (NSNumber*) getBool:(NSString*)key;
- (void) setFloat:(NSString*)key withValue:(NSString*)value;
- (NSNumber*) getFloat:(NSString*)key;
// Could also be implemented:
// setObject:forKey:
// setDouble:forKey:
// setURL:forKey:
@end

View file

@ -0,0 +1,211 @@
//
// UserDefaults.m
// MacGap
//
// Created by Jeff Hanbury on 16/04/2014.
// Copyright (c) 2014 Twitter. All rights reserved.
//
#import "UserDefaults.h"
#import "JSEventHelper.h"
@interface UserDefaults() {
}
-(void) setupNotificationCenter;
@end
@implementation UserDefaults
- (id) initWithWebView:(WebView *) view{
self = [super init];
if (self) {
self.webView = view;
[self setupNotificationCenter];
}
return self;
}
-(void) setupNotificationCenter{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(defaultsChanged:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
- (void)defaultsChanged:(NSNotification *)notification {
NSDictionary* returnDict = [self myDefaultsDictionary];
[JSEventHelper triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView];
}
- (NSString*) getMyDefaults {
NSDictionary* myDefaults = [self myDefaultsDictionary];
return [[Utils sharedInstance] convertDictionaryToJSON:myDefaults];
}
- (NSDictionary*) myDefaultsDictionary {
NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init];
// Get the user defaults.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Build up a dictionary containing just the items beginning with our
// prefix.
for (NSString* key in [self getUserDefaultsKeys]) {
if ([key hasPrefix:prefix]) {
id val = [defaults valueForKey:key];
[returnDict setObject:val forKey:key];
}
}
return returnDict;
}
- (NSArray*) getUserDefaultsKeys {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
return [[prefs dictionaryRepresentation] allKeys];
}
- (void) removeObjectForKey:(NSString*)key {
NSString* prefixedKey;
prefixedKey = [self addPrefix:key];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
// Check we have a standard prefix for JS-modified keys, for security purposes.
// If not, add it. This stops JavaScript from ever being able to modify keys
// it did not create.
- (NSString*) addPrefix:(NSString*)key {
NSString* prefix;
prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
if (![key hasPrefix:prefix]) {
key = [prefix stringByAppendingString:key];
}
return key;
}
// String
- (void) setString:(NSString*)key withValue:(NSString*)value {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString* prefixedKey;
prefixedKey = [self addPrefix:key];
[prefs setObject:value forKey:prefixedKey];
}
- (NSString*) getString:(NSString *)key {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
return [prefs stringForKey:key];
}
// All the following must convert their type to NSNumber for JavaScript.
// Integer
- (void) setInteger:(NSString*)key withValue:(NSString*)value {
NSString* prefixedKey;
prefixedKey = [self addPrefix:key];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSInteger myInt = [value intValue];
[prefs setInteger:myInt forKey:prefixedKey];
}
- (NSNumber*) getInteger:(NSString *)key {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
return [NSNumber numberWithInteger:[prefs integerForKey:key]];
}
// Boolean
- (void) setBool:(NSString*)key withValue:(NSString*)value {
NSString* prefixedKey;
prefixedKey = [self addPrefix:key];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
BOOL myBool = [value boolValue];
[prefs setBool:myBool forKey:prefixedKey];
}
- (NSNumber*) getBool:(NSString *)key {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
return [NSNumber numberWithBool:[prefs boolForKey:key]];
}
// Float
- (void) setFloat:(NSString*)key withValue:(NSString*)value {
NSString* prefixedKey;
prefixedKey = [self addPrefix:key];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
float myFloat = [value floatValue];
[prefs setFloat:myFloat forKey:prefixedKey];
}
- (NSNumber*) getFloat:(NSString *)key {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
return [NSNumber numberWithFloat:[prefs floatForKey:key]];
}
#pragma mark WebScripting Protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
return NO;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector {
id result = nil;
if (selector == @selector(getMyDefaults)) {
result = @"getMyDefaults";
}
if (selector == @selector(removeObjectForKey:)) {
result = @"removeObjectForKey";
}
else if (selector == @selector(setString:withValue:)) {
result = @"setString";
} else if (selector == @selector(getString:)) {
result = @"getString";
}
else if (selector == @selector(setInteger:withValue:)) {
result = @"setInteger";
} else if (selector == @selector(getInteger:)) {
result = @"getInteger";
}
else if (selector == @selector(setBool:withValue:)) {
result = @"setBool";
} else if (selector == @selector(getBool:)) {
result = @"getBool";
}
else if (selector == @selector(setFloat:withValue:)) {
result = @"setFloat";
} else if (selector == @selector(getFloat:)) {
result = @"getFloat";
}
return result;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name {
return NO;
}
@end

View file

@ -0,0 +1,9 @@
@interface Fonts : NSObject {
}
- (NSArray*) availableFonts;
- (NSArray*) availableFontFamilies;
- (NSArray*) availableMembersOfFontFamily:(NSString*)fontFamily;
- (CGFloat) defaultLineHeightForFont:(NSString *)theFontName ofSize:(CGFloat)theFontSize;
@end

View file

@ -0,0 +1,48 @@
#import "fonts.h"
@implementation Fonts
- (NSArray*) availableFonts {
return [[NSFontManager sharedFontManager] availableFonts];
}
- (NSArray*) availableFontFamilies {
return [[NSFontManager sharedFontManager] availableFontFamilies];
}
- (NSArray*) availableMembersOfFontFamily:(NSString *)fontFamily {
return [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily];
}
- (CGFloat) defaultLineHeightForFont:(NSString*)theFontName ofSize:(CGFloat)theFontSize {
NSFont *theFont = [NSFont fontWithName:theFontName size:theFontSize];
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
return [lm defaultLineHeightForFont:theFont];
}
#pragma mark WebScripting Protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
return NO;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector {
id result = nil;
if (selector == @selector(availableMembersOfFontFamily:)) {
result = @"availableMembersOfFontFamily";
} else if (selector == @selector(defaultLineHeightForFont:ofSize:)) {
result = @"defaultLineHeightForFont";
}
return result;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name {
return NO;
}
@end

View file

@ -0,0 +1,7 @@
// Application constants
#define kStartPage @"http://127.0.0.1:9993/"
#define kStartFolder @"."
#define kWebScriptNamespace @"macgap"

View file

@ -0,0 +1,15 @@
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
@class WebViewDelegate;
@interface ContentView : NSView {
IBOutlet WebView* webView;
WebViewDelegate* delegate;
}
@property (retain) WebView* webView;
@property (retain) WebViewDelegate* delegate;
@property (strong) IBOutlet NSMenu *mainMenu;
@end

View file

@ -0,0 +1,68 @@
#import "ContentView.h"
#import "WebViewDelegate.h"
#import "AppDelegate.h"
#import "JSEventHelper.h"
@interface WebPreferences (WebPreferencesPrivate)
- (void)_setLocalStorageDatabasePath:(NSString *)path;
- (void) setLocalStorageEnabled: (BOOL) localStorageEnabled;
- (void) setDatabasesEnabled:(BOOL)databasesEnabled;
- (void) setDeveloperExtrasEnabled:(BOOL)developerExtrasEnabled;
- (void) setWebGLEnabled:(BOOL)webGLEnabled;
- (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled;
@end
@implementation ContentView
@synthesize webView, delegate, mainMenu;
- (void) awakeFromNib
{
WebPreferences *webPrefs = [WebPreferences standardPreferences];
NSString *cappBundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
NSString *applicationSupportFile = [@"~/Library/Application Support/" stringByExpandingTildeInPath];
NSString *savePath = [NSString pathWithComponents:[NSArray arrayWithObjects:applicationSupportFile, cappBundleName, @"LocalStorage", nil]];
[webPrefs _setLocalStorageDatabasePath:savePath];
[webPrefs setLocalStorageEnabled:YES];
[webPrefs setDatabasesEnabled:YES];
[webPrefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]];
[webPrefs setOfflineWebApplicationCacheEnabled:YES];
[webPrefs setWebGLEnabled:YES];
[self.webView setPreferences:webPrefs];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage
sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
[self.webView setApplicationNameForUserAgent: @"MacGap"];
self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]];
[self.webView setFrameLoadDelegate:self.delegate];
[self.webView setUIDelegate:self.delegate];
[self.webView setResourceLoadDelegate:self.delegate];
[self.webView setDownloadDelegate:self.delegate];
[self.webView setPolicyDelegate:self.delegate];
[self.webView setDrawsBackground:NO];
[self.webView setShouldCloseWithWindow:NO];
[self.webView setGroupName:@"MacGap"];
}
- (void) windowResized:(NSNotification*)notification;
{
NSWindow* window = (NSWindow*)notification.object;
NSSize size = [window frame].size;
DebugNSLog(@"window width = %f, window height = %f", size.width, size.height);
bool isFullScreen = (window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask;
int titleBarHeight = isFullScreen ? 0 : [[Utils sharedInstance] titleBarHeight:window];
[self.webView setFrame:NSMakeRect(0, 0, size.width, size.height - titleBarHeight)];
[JSEventHelper triggerEvent:@"orientationchange" forWebView:self.webView];
}
@end

View file

@ -0,0 +1,20 @@
//
// Helper.h
// MacGap
//
// Created by Liam Kaufman Simpkins on 12-01-22.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "WindowController.h"
@interface JSEventHelper : NSObject
+ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView;
+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView;
+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView;
+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView;
+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView;
@end

View file

@ -0,0 +1,41 @@
//
// Helper.m
// MacGap
//
// Created by Liam Kaufman Simpkins on 12-01-22.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import "JSEventHelper.h"
@implementation JSEventHelper
+ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView {
[self triggerEvent:event withArgs:[NSMutableDictionary dictionary] forObject:@"document" forWebView:webView];
}
+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView {
[self triggerEvent:event withArgs:args forObject:@"document" forWebView:webView];
}
+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView {
// Convert args Dictionary to JSON.
NSString* jsonString = [[Utils sharedInstance] convertDictionaryToJSON:args];
// Create the event JavaScript and run it.
NSString * str = [NSString stringWithFormat:@"var e = document.createEvent('Events'); e.initEvent('%@', true, false); e.data=%@; %@.dispatchEvent(e); ", event, jsonString, objName];
[webView stringByEvaluatingJavaScriptFromString:str];
}
+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView {
[self triggerEvent:event forDetail:detail forObject:@"document" forWebView:webView];
}
+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView {
NSString *detailEscaped = [detail stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
NSString *str = [NSString stringWithFormat:@"var e = new CustomEvent('%@', { 'detail': decodeURIComponent(\"%@\") }); %@.dispatchEvent(e); ", event, detailEscaped, objName];
[webView stringByEvaluatingJavaScriptFromString:str];
}
@end

View file

@ -0,0 +1,20 @@
#import <Foundation/Foundation.h>
#import <Webkit/WebScriptObject.h>
#define DEG_EPS 0.001
#define fequal(a,b) (fabs((a) - (b)) < DEG_EPS)
#define fequalzero(a) (fabs(a) < DEG_EPS)
@class LoadingView;
@interface Utils : NSObject {
}
- (float) titleBarHeight:(NSWindow*)aWindow;
- (NSString*) pathForResource:(NSString*)resourcepath;
- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict;
- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray;
+ (Utils*) sharedInstance;
@end

View file

@ -0,0 +1,93 @@
#import "Utils.h"
#import <Webkit/WebScriptObject.h>
static Utils* sharedInstance = nil;
@implementation Utils
- (float) titleBarHeight:(NSWindow*)aWindow
{
NSRect frame = [aWindow frame];
NSRect contentRect = [NSWindow contentRectForFrameRect: frame
styleMask: NSTitledWindowMask];
return (frame.size.height - contentRect.size.height);
}
- (NSString*) pathForResource:(NSString*)resourcepath
{
NSBundle * mainBundle = [NSBundle mainBundle];
NSMutableArray *directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]];
NSString *filename = [directoryParts lastObject];
[directoryParts removeLastObject];
NSString *directoryStr = [NSString stringWithFormat:@"%@/%@", kStartFolder, [directoryParts componentsJoinedByString:@"/"]];
return [mainBundle pathForResource:filename
ofType:@""
inDirectory:directoryStr];
}
- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict {
// Convert defaults Dictionary to JSON.
NSError *error;
NSData *jsonData = [NSJSONSerialization
dataWithJSONObject:dict
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
NSString *jsonString;
if (! jsonData) {
NSLog(@"Got an error converting to JSON: %@", error);
}
else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return jsonString;
}
// Convert JavaScript array (arrives as a WebScriptObject) into an NSArray of strings.
- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray {
NSInteger count = [[jsArray valueForKey:@"length"] integerValue];
NSMutableArray *args = [NSMutableArray array];
for (int i = 0; i < count; i++) {
NSString *item = [jsArray webScriptValueAtIndex:i];
if ([item isKindOfClass:[NSString class]]) {
[args addObject:item];
}
}
return args;
}
#pragma mark -
#pragma mark Singleton methods
+ (Utils*) sharedInstance
{
@synchronized(self)
{
if (sharedInstance == nil){
sharedInstance = [[Utils alloc] init];
}
}
return sharedInstance;
}
+ (id) allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [super allocWithZone:zone];
return sharedInstance; // assignment and return on first allocation
}
}
return nil; // on subsequent allocation attempts return nil
}
- (id) copyWithZone:(NSZone *)zone
{
return self;
}
@end

View file

@ -0,0 +1,49 @@
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
@class Sound;
@class Dock;
@class Growl;
@class Notice;
@class Path;
@class App;
@class Window;
@class Clipboard;
@class Fonts;
@class MenuProxy;
@class UserDefaults;
@class WindowController;
@interface WebViewDelegate : NSObject {
Sound* sound;
Dock* dock;
Growl* growl;
Notice* notice;
Path* path;
App* app;
Window* window;
Clipboard* clipboard;
Fonts* fonts;
NSMenu *mainMenu;
UserDefaults* userDefaults;
}
@property (nonatomic, retain) Sound* sound;
@property (nonatomic, retain) Dock* dock;
@property (nonatomic, retain) Growl* growl;
@property (nonatomic, retain) Notice* notice;
@property (nonatomic, retain) Path* path;
@property (nonatomic, retain) App* app;
@property (nonatomic, retain) Window* window;
@property (nonatomic, retain) Clipboard* clipboard;
@property (nonatomic, retain) Fonts* fonts;
@property (nonatomic, retain) MenuProxy* menu;
@property (nonatomic, retain) UserDefaults* userDefaults;
@property (nonatomic, retain) WindowController *requestedWindow;
- (id) initWithMenu:(NSMenu*)menu;
@end

View file

@ -0,0 +1,206 @@
#import "WebViewDelegate.h"
#import "Sound.h"
#import "Dock.h"
#import "Notice.h"
#import "Path.h"
#import "App.h"
#import "Window.h"
#import "WindowController.h"
#import "Clipboard.h"
#import "Fonts.h"
#import "MenuProxy.h"
#import "UserDefaults.h"
@implementation WebViewDelegate
@synthesize sound;
@synthesize dock;
@synthesize growl;
@synthesize notice;
@synthesize path;
@synthesize app;
@synthesize window;
@synthesize requestedWindow;
@synthesize clipboard;
@synthesize fonts;
@synthesize menu;
@synthesize userDefaults;
- (id) initWithMenu:(NSMenu*)aMenu
{
self = [super init];
if (!self)
return nil;
mainMenu = aMenu;
return self;
}
- (void) webView:(WebView*)webView didClearWindowObject:(WebScriptObject*)windowScriptObject forFrame:(WebFrame *)frame
{
JSContextRef context = [frame globalContext];
if (self.sound == nil) { self.sound = [[Sound alloc] initWithContext:context]; }
if (self.dock == nil) { self.dock = [Dock new]; }
if (self.path == nil) { self.path = [Path new]; }
if (self.clipboard == nil) { self.clipboard = [Clipboard new]; }
if (self.fonts == nil) { self.fonts = [Fonts new]; }
if (self.notice == nil && [Notice available] == YES) {
self.notice = [[Notice alloc] initWithWebView:webView];
}
if (self.app == nil) {
self.app = [[App alloc] initWithWebView:webView];
}
if (self.window == nil) {
self.window = [[Window alloc] initWithWebView:webView];
}
if (self.menu == nil) {
self.menu = [MenuProxy proxyWithContext:context andMenu:mainMenu];
}
if (self.userDefaults == nil) {
self.userDefaults = [[UserDefaults alloc] initWithWebView:webView];
}
[windowScriptObject setValue:self forKey:kWebScriptNamespace];
}
- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles{
NSOpenPanel * openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
[openDlg setCanChooseDirectories:NO];
[openDlg beginWithCompletionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
NSArray * files = [[openDlg URLs] valueForKey: @"relativePath"];
[resultListener chooseFilenames: files];
} else {
[resultListener cancel];
}
}];
}
- (void) webView:(WebView*)webView addMessageToConsole:(NSDictionary*)message
{
if (![message isKindOfClass:[NSDictionary class]]) {
return;
}
NSLog(@"JavaScript console: %@:%@: %@",
[[message objectForKey:@"sourceURL"] lastPathComponent], // could be nil
[message objectForKey:@"lineNumber"],
[message objectForKey:@"message"]);
}
- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
{
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:@"OK"];
[alert setMessageText:message];
[alert setAlertStyle:NSWarningAlertStyle];
[alert runModal];
}
- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
{
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:@"Yes"];
[alert addButtonWithTitle:@"No"];
[alert setMessageText:message];
[alert setAlertStyle:NSWarningAlertStyle];
if ([alert runModal] == NSAlertFirstButtonReturn)
return YES;
else
return NO;
}
/*
By default the size of a database is set to 0 [1]. When a database is being created
it calls this delegate method to get an increase in quota size - or call an error.
PS this method is defined in WebUIDelegatePrivate and may make it difficult, but
not impossible [2], to get an app accepted into the mac app store.
Further reading:
[1] http://stackoverflow.com/questions/353808/implementing-a-webview-database-quota-delegate
[2] http://stackoverflow.com/questions/4527905/how-do-i-enable-local-storage-in-my-webkit-based-application/4608549#4608549
*/
- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier
{
static const unsigned long long defaultQuota = 5 * 1024 * 1024;
if ([origin respondsToSelector: @selector(setQuota:)]) {
[origin performSelector:@selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]];
} else {
NSLog(@"could not increase quota for %lld", defaultQuota);
}
}
- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
{
NSMutableArray *webViewMenuItems = [defaultMenuItems mutableCopy];
if (webViewMenuItems)
{
NSEnumerator *itemEnumerator = [defaultMenuItems objectEnumerator];
NSMenuItem *menuItem = nil;
while ((menuItem = [itemEnumerator nextObject]))
{
NSInteger tag = [menuItem tag];
switch (tag)
{
case WebMenuItemTagOpenLinkInNewWindow:
case WebMenuItemTagDownloadLinkToDisk:
case WebMenuItemTagCopyLinkToClipboard:
case WebMenuItemTagOpenImageInNewWindow:
case WebMenuItemTagDownloadImageToDisk:
case WebMenuItemTagCopyImageToClipboard:
case WebMenuItemTagOpenFrameInNewWindow:
case WebMenuItemTagGoBack:
case WebMenuItemTagGoForward:
case WebMenuItemTagStop:
case WebMenuItemTagOpenWithDefaultApplication:
case WebMenuItemTagReload:
[webViewMenuItems removeObjectIdenticalTo: menuItem];
}
}
}
return webViewMenuItems;
}
- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request{
requestedWindow = [[WindowController alloc] initWithRequest:request];
return requestedWindow.contentView.webView;
}
- (void)webViewShow:(WebView *)sender{
[requestedWindow showWindow:sender];
}
- (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener
{
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
[listener ignore];
}
#pragma mark WebScripting protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return YES;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return NO;
}
@end

View file

@ -0,0 +1,23 @@
#import <Foundation/Foundation.h>
#import "WindowController.h"
@interface Window : NSObject{
CGRect _oldRestoreFrame;
}
@property (retain, nonatomic) WindowController *windowController;
@property (nonatomic, retain) WebView *webView;
- (id) initWithWebView:(WebView *)view;
- (void) open:(NSDictionary *)properties;
- (void) move:(NSDictionary *)properties;
- (void) resize:(NSDictionary *) properties;
- (Boolean) isMaximized;
- (CGFloat) getX;
- (CGFloat) getY;
- (void) maximize;
- (void) restore;
- (void) toggleFullscreen;
@end

View file

@ -0,0 +1,94 @@
#import "Window.h"
@implementation Window
@synthesize windowController, webView;
- (id) initWithWebView:(WebView*)view
{
if(self = [super init]) {
self.webView = view;
}
return self;
}
- (void) open:(NSDictionary *)properties
{
self.windowController = [[WindowController alloc] initWithURL:[properties valueForKey:@"url"]];
[self.windowController showWindow: [NSApplication sharedApplication].delegate];
[self.windowController.window makeKeyWindow];
}
- (void) minimize {
[[NSApp mainWindow] miniaturize:[NSApp mainWindow]];
}
- (void) toggleFullscreen {
[[NSApp mainWindow] toggleFullScreen:[NSApp mainWindow]];
}
- (void) maximize {
CGRect a = [NSApp mainWindow].frame;
_oldRestoreFrame = CGRectMake(a.origin.x, a.origin.y, a.size.width, a.size.height);
[[NSApp mainWindow] setFrame:[[NSScreen mainScreen] visibleFrame] display:YES];
}
- (Boolean) isMaximized {
NSRect a = [NSApp mainWindow].frame;
NSRect b = [[NSScreen mainScreen] visibleFrame];
return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height;
}
- (CGFloat) getX {
NSRect frame = [self.webView window].frame;
return frame.origin.x;
}
- (CGFloat) getY {
NSRect frame = [self.webView window].frame;
return frame.origin.y;
}
- (void) move:(NSDictionary *)properties
{
NSRect frame = [self.webView window].frame;
frame.origin.x = [[properties valueForKey:@"x"] doubleValue];
frame.origin.y = [[properties valueForKey:@"y"] doubleValue];
[[self.webView window] setFrame:frame display:YES];
}
- (void) resize:(NSDictionary *) properties
{
NSRect frame = [self.webView window].frame;
frame.size.width = [[properties valueForKey:@"width"] doubleValue];
frame.size.height = [[properties valueForKey:@"height"] doubleValue];
[[self.webView window] setFrame:frame display:YES];
}
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return NO;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector{
id result = nil;
if (selector == @selector(open:)) {
result = @"open";
}else if (selector == @selector(move:)){
result = @"move";
}else if (selector == @selector(resize:)){
result = @"resize";
}
return result;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
@end

View file

@ -0,0 +1,10 @@
#import <Foundation/Foundation.h>
@interface Clipboard : NSObject {
}
- (void) copy:(NSString*)text;
- (NSString *) paste;
@end

View file

@ -0,0 +1,51 @@
//
// clipboard.m
// MacGap
//
// Created by David Zorychta on 2013-07-22.
// Copyright (c) 2013 Twitter. All rights reserved.
//
#import "Clipboard.h"
@implementation Clipboard
- (void) copy:(NSString*)text {
[[NSPasteboard generalPasteboard] clearContents];
[[NSPasteboard generalPasteboard] setString:text forType:NSStringPboardType];
}
- (NSString *) paste {
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
NSDictionary *options = [NSDictionary dictionary];
BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options];
if (ok) {
NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
return (NSString *) [objectsToPaste objectAtIndex:0];
}
return @"";
}
+ (NSString*) webScriptNameForSelector:(SEL)selector
{
id result = nil;
if (selector == @selector(copy:)) {
result = @"copy";
}
return result;
}
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
return NO;
}
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
@end

View file

@ -0,0 +1,63 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "application16x16.png",
"scale" : "1x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "application32x32.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "application128x128.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "application256x256.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "application512x512.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>ZeroTier One</string>
<key>CFBundleIdentifier</key>
<string>com.zerotier.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>ZeroTier One</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View file

@ -0,0 +1,15 @@
//
// Prefix header for all source files of the 'MacGap' target in the 'MacGap' project
//
#ifdef __OBJC__
#ifdef _DEBUG
#define DebugNSLog(format, ...) NSLog(format, ## __VA_ARGS__)
#else
#define DebugNSLog(format, ...)
#endif
#import <Cocoa/Cocoa.h>
#import "Constants.h"
#import "Utils.h"
#endif

View file

@ -0,0 +1,13 @@
#import <Cocoa/Cocoa.h>
#import "ContentView.h"
@interface WindowController : NSWindowController {
}
- (id) initWithURL:(NSString *) url;
- (id) initWithRequest: (NSURLRequest *)request;
@property (retain) NSURL * url;
@property (retain) IBOutlet ContentView *contentView;
@end

View file

@ -0,0 +1,54 @@
#import "WindowController.h"
@interface WindowController() {
}
-(void) notificationCenter;
@end
@implementation WindowController
@synthesize contentView, url;
- (id) initWithURL:(NSString *) relativeURL{
self = [super initWithWindowNibName:@"Window"];
self.url = [NSURL URLWithString:relativeURL relativeToURL:[[NSBundle mainBundle] resourceURL]];
[self.window setFrameAutosaveName:@"MacGapWindow"];
[self notificationCenter];
return self;
}
-(id) initWithRequest: (NSURLRequest *)request{
self = [super initWithWindowNibName:@"Window"];
[self notificationCenter];
[[self.contentView.webView mainFrame] loadRequest:request];
return self;
}
-(void) notificationCenter{
[[NSNotificationCenter defaultCenter] addObserver:self.contentView
selector:@selector(windowResized:)
name:NSWindowDidResizeNotification
object:[self window]];
}
- (void)windowDidLoad
{
[super windowDidLoad];
if (self.url != nil) {
[self.contentView.webView setMainFrameURL:[self.url absoluteString]];
}
// Implement this method to handle any initialization after your
// window controller's window has been loaded from its nib file.
}
@end

View file

@ -0,0 +1,13 @@
{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\vieww9600\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\f0\b\fs24 \cf0 (c)2011-2015 ZeroTier, Inc.\
Licensed under the GNU GPLv3\
\
UI Wrapper MacGap (c) Twitter, Inc.\
Licensed under the MIT License\
http://macgap.com/\
}

View file

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,337 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
<data>
<int key="IBDocument.SystemTarget">1070</int>
<string key="IBDocument.SystemVersion">11C74</string>
<string key="IBDocument.InterfaceBuilderVersion">1938</string>
<string key="IBDocument.AppKitVersion">1138.23</string>
<string key="IBDocument.HIToolboxVersion">567.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.WebKitIBPlugin</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>1938</string>
<string>822</string>
</object>
</object>
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSWindowTemplate</string>
<string>NSView</string>
<string>NSCustomObject</string>
<string>WebView</string>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.WebKitIBPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSCustomObject" id="1001">
<string key="NSClassName">WindowController</string>
</object>
<object class="NSCustomObject" id="1003">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1004">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSWindowTemplate" id="1005">
<int key="NSWindowStyleMask">15</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{196, 240}, {758, 410}}</string>
<int key="NSWTFlags">544735232</int>
<string key="NSWindowTitle">Window</string>
<string key="NSWindowClass">NSWindow</string>
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="1006">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="WebView" id="807146547">
<reference key="NSNextResponder" ref="1006"/>
<int key="NSvFlags">274</int>
<object class="NSMutableSet" key="NSDragTypes">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="set.sortedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>Apple HTML pasteboard type</string>
<string>Apple PDF pasteboard type</string>
<string>Apple PICT pasteboard type</string>
<string>Apple URL pasteboard type</string>
<string>Apple Web Archive pasteboard type</string>
<string>NSColor pasteboard type</string>
<string>NSFilenamesPboardType</string>
<string>NSStringPboardType</string>
<string>NeXT RTFD pasteboard type</string>
<string>NeXT Rich Text Format v1.0 pasteboard type</string>
<string>NeXT TIFF v4.0 pasteboard type</string>
<string>WebURLsWithTitlesPboardType</string>
<string>public.png</string>
<string>public.url</string>
<string>public.url-name</string>
</object>
</object>
<string key="NSFrameSize">{758, 410}</string>
<reference key="NSSuperview" ref="1006"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSReuseIdentifierKey">_NS:51</string>
<string key="FrameName"/>
<string key="GroupName"/>
<object class="WebPreferences" key="Preferences">
<string key="Identifier"/>
<object class="NSMutableDictionary" key="Values">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>WebKitDefaultFixedFontSize</string>
<string>WebKitDefaultFontSize</string>
<string>WebKitMinimumFontSize</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="12"/>
<integer value="12"/>
<integer value="1"/>
</object>
</object>
</object>
<bool key="UseBackForwardList">YES</bool>
<bool key="AllowsUndo">YES</bool>
</object>
</object>
<string key="NSFrameSize">{758, 410}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="807146547"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<int key="NSWindowCollectionBehavior">128</int>
<bool key="NSWindowIsRestorable">YES</bool>
</object>
</object>
<object class="IBObjectContainer" key="IBDocument.Objects">
<object class="NSMutableArray" key="connectionRecords">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">contentView</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="1006"/>
</object>
<int key="connectionID">23</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">window</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="1005"/>
</object>
<int key="connectionID">25</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">title: contentView.webView.mainFrameTitle</string>
<reference key="source" ref="1005"/>
<reference key="destination" ref="1001"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="1005"/>
<reference key="NSDestination" ref="1001"/>
<string key="NSLabel">title: contentView.webView.mainFrameTitle</string>
<string key="NSBinding">title</string>
<string key="NSKeyPath">contentView.webView.mainFrameTitle</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">31</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">webView</string>
<reference key="source" ref="1006"/>
<reference key="destination" ref="807146547"/>
</object>
<int key="connectionID">19</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
<object class="NSArray" key="object" id="1002">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1001"/>
<reference key="parent" ref="1002"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1003"/>
<reference key="parent" ref="1002"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1004"/>
<reference key="parent" ref="1002"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="1005"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="1006"/>
</object>
<reference key="parent" ref="1002"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="1006"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="807146547"/>
</object>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="807146547"/>
<reference key="parent" ref="1006"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.IBPluginDependency</string>
<string>-2.IBPluginDependency</string>
<string>-3.IBPluginDependency</string>
<string>1.IBPluginDependency</string>
<string>1.IBWindowTemplateEditedContentRect</string>
<string>1.NSWindowTemplate.visibleAtLaunch</string>
<string>2.CustomClassName</string>
<string>2.IBPluginDependency</string>
<string>5.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{357, 418}, {480, 270}}</string>
<integer value="1"/>
<string>ContentView</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.WebKitIBPlugin</string>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="1002"/>
<reference key="dict.values" ref="1002"/>
</object>
<nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference key="dict.sortedKeys" ref="1002"/>
<reference key="dict.values" ref="1002"/>
</object>
<nil key="sourceID"/>
<int key="maxID">31</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">ContentView</string>
<string key="superclassName">NSView</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">webView</string>
<string key="NS.object.0">WebView</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">webView</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">webView</string>
<string key="candidateClassName">WebView</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/ContentView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">WebView</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">reloadFromOrigin:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">reloadFromOrigin:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">reloadFromOrigin:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/WebView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">WindowController</string>
<string key="superclassName">NSWindowController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">contentView</string>
<string key="NS.object.0">ContentView</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">contentView</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">contentView</string>
<string key="candidateClassName">ContentView</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/WindowController.h</string>
</object>
</object>
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>

View file

@ -0,0 +1,14 @@
//
// main.m
// MacGap
//
// Created by Alex MacCaw on 08/01/2012.
// Copyright (c) 2012 Twitter. All rights reserved.
//
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **)argv);
}