Skip to content

Commit

Permalink
refactored Makefile to use clang modules
Browse files Browse the repository at this point in the history
ViewController init()s cleaned up
fixed OpenURL handling bug
  • Loading branch information
kfix committed Feb 25, 2015
1 parent bb8c0f3 commit b45a556
Show file tree
Hide file tree
Showing 20 changed files with 224 additions and 124 deletions.
84 changes: 42 additions & 42 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#!/usr/bin/make -f
$(shell [ -d build ] || mkdir build)
appdir := apps
apps := Hangouts.app Trello.app Digg.app Vine.app
appexec := build/MacOS/MacPin
#apps := $(addsuffix .app, $(basename $(wildcard sites/*)))
#apps := $(patsubst %, %.app, $(basename $(wildcard sites/*)))
debug ?=
debug += -D APP2JSLOG -D SAFARIDBG -D WK2LOG -D DBGMENU
debug += -D APP2JSLOG -D SAFARIDBG -D WK2LOG -D DBGMENU
#^ need to make sure !release target
#verbose := -driver-print-jobs
# ^ just a dry-run
#verbose := -v
all: $(apps)
exec := build/MacPin.exec

VERSION := 1.1.0
LAST_TAG != git describe --abbrev=0 --tags
Expand All @@ -17,33 +19,30 @@ REPO := MacPin
ZIP := $(REPO).zip
GH_RELEASE_JSON = '{"tag_name": "v$(VERSION)","target_commitish": "master","name": "v$(VERSION)","body": "MacPin build of version $(VERSION)","draft": false,"prerelease": false}'

swiftc := xcrun -sdk macosx swiftc
swiftc := xcrun -sdk macosx swiftc $(verbose)
sdkpath := $(shell xcrun --show-sdk-path --sdk macosx)
frameworks := -F $(sdkpath)/System/Library/Frameworks -F build
modincdirs := -I build -L build -I objc
bridgehdrs := $(wildcard modules/*/objc-bridging.h)
bridgeopt := $(addprefix -import-objc-header , $(bridgehdrs))
frameworks := -F $(sdkpath)/System/Library/Frameworks -F build -F build/Frameworks
modincdirs := -I build -L build -L build/Frameworks
modincdirs += $(addprefix -I ,$(patsubst %/,%,$(dir $(wildcard modules/*/module.modulemap))))

modules/%/objc-bridging.h: ; #ignore missing bridge headers
build/%.objc-bridging.o: modules/%/objc-bridging.h
env bash objc/bridge-maker.sh $< $@
#build/%.appex
#$(swiftc) -application-extension
# https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/SystemExtensionKeys.html#//apple_ref/doc/uid/TP40014212-SW15

build/%.exec: build/%.o build/%.objc-bridging.o
build/MacOS/%: execs/%.swift build/Frameworks/lib%.dylib
install -d $(@D)
$(swiftc) $(debug) $(frameworks) $(modincdirs) \
-Xlinker -rpath -Xlinker @executable_path/ \
-emit-executable -o $@ $< $(wildcard build/$*.objc-bridging.o)
-Xlinker -rpath -Xlinker @loader_path/../Frameworks \
-module-link-name $* -module-name $*.MainExec \
-emit-executable -o $@ $<

build/%.o: modules/%/main.swift build/lib%.dylib
$(swiftc) $(debug) $(frameworks) $(bridgeopt) $(modincdirs) \
-l$* -module-link-name $* -module-name $*Main \
-emit-object -o $@ $<

build/lib%.dylib build/%.swiftmodule build/%.swiftdoc: modules/%/*.swift
$(swiftc) $(debug) $(frameworks) $(modincdirs) $(bridgeopt) \
-emit-library -o build/lib$*.dylib \
build/Frameworks/lib%.dylib build/%.swiftmodule build/%.swiftdoc: modules/%/*.swift
install -d $(@D)
$(swiftc) $(debug) $(frameworks) $(modincdirs) \
-emit-library -o $@ \
-Xlinker -install_name -Xlinker @rpath/lib$*.dylib \
-emit-module -module-name $* -module-link-name $* -emit-module-path build/$*.swiftmodule \
$(filter-out $(wildcard modules/*/main.swift), $+)
$+

build/%.a: build/%.o
ar rcs $@ $<
Expand All @@ -59,52 +58,53 @@ icons/%.icns: icons/WebKit.icns

# https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html
# https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html
%.app: $(exec) icons/%.icns sites/% entitlements.plist
%.app: $(appexec) icons/%.icns sites/% entitlements.plist build/Frameworks/lib$(notdir $(appexec)).dylib
python2.7 -m bundlebuilder \
--name=$* \
--bundle-id=com.github.kfix.macpin.$* \
--bundle-id=com.github.kfix.$(notdir $(appexec)).$* \
--builddir=$(appdir) \
--executable=$(exec) \
--executable=$(appexec) \
--iconfile=icons/$*.icns \
--file=sites/$*:Contents/Resources \
$(addprefix --lib=,$(filter %.dylib,$+)) \
build
#install -d $(appdir)/$*.app/Contents/MacOS/modules
#install $(modobjs) $(appdir)/$*.app/Contents/MacOS/modules
install build/lib*.dylib $(appdir)/$*.app/Contents/MacOS
plutil -replace CFBundleShortVersionString -string "$(VERSION)" $(appdir)/$*.app/Contents/Info.plist
plutil -replace CFBundleVersion -string "0.0.0" $(appdir)/$*.app/Contents/Info.plist
plutil -replace NSHumanReadableCopyright -string "built $(shell date) by $(shell id -F)" $(appdir)/$*.app/Contents/Info.plist
#true = NSSupportsAutomaticTermination NSSupportsSuddenTermination
plutil -replace NSSupportsAutomaticTermination -bool true $(appdir)/$*.app/Contents/Info.plist
plutil -replace NSSupportsSuddenTermination -bool true $(appdir)/$*.app/Contents/Info.plist
-codesign -s - -f --entitlements entitlements.plist $(appdir)/$*.app && codesign -dv $(appdir)/$*.app
-asctl container acl list -file $(appdir)/$*.app

%.appex: %.app appex.plist
# --bundle-id=com.github.kfix.macpin.$*.Extension

install: $(apps)
cd $(appdir); cp -R $+ ~/Applications

clean:
-rm $(exec) *.o *.d *.zip
-cd build && rm *.o *.a *.dylib *.d *.swiftmodule *.swiftdoc *.exec
-rm -rf build
-cd $(appdir) && rm -rf *.app

uninstall:
-defaults delete $(exec)
-rm -rf ~/Library/Caches/com.github.kfix.$(exec).* ~/Library/WebKit/com.github.kfix.$(exec).* ~/Library/WebKit/$(exec)
-defaults delete $(appexec)
-rm -rf ~/Library/Caches/com.github.kfix.$(notdir $(appexec)).* ~/Library/WebKit/com.github.kfix.$(notdir $(appexec)).* ~/Library/WebKit/$(notdir $(appexec))
-rm -rf ~/Library/Saved\ Application\ State/com.github.kfix.macpin.*
-rm -rf ~/Library/Preferences/com.github.kfix.macpin.*
-cd ~/Applications; rm -rf $(apps)
-defaults read com.apple.spaces app-bindings | grep com.githib.kfix.macpin.
-defaults read com.apple.spaces app-bindings | grep com.github.kfix.macpin.
# open ~/Library/Preferences/com.apple.spaces.plist

test: $(exec)
#-defaults delete $(exec)
test: $(appexec)
#-defaults delete $(notdir appexec)
$< http://browsingtest.appspot.com

doc: $(exec)
doc: $(appexec)
echo ":print_module MacPin" | xcrun swift $(modincdirs) -deprecated-integrated-repl

nightly: $(exec) DYLD_FRAMEWORK_PATH=/Volumes/WebKit/WebKit.app/Contents/Frameworks/10.10
-defaults delete $(exec)
-rm -rf ~/Library/WebKit/$(exec)
nightly: $(appexec) DYLD_FRAMEWORK_PATH=/Volumes/WebKit/WebKit.app/Contents/Frameworks/10.10
-defaults delete $(notdir $(appexec))
-rm -rf ~/Library/WebKit/$(notdir $(appexec))
$<

tag:
Expand All @@ -120,5 +120,5 @@ release: clean $(apps) $(ZIP)
dload=$$(curl --fail -X POST -H "Content-Type: application/gzip" --data-binary "@$(ZIP)" "$$posturl=$(ZIP)&access_token=$(GITHUB_ACCESS_TOKEN)" | jq -r .browser_download_url | sed 's/[\{\}]//g') && \
echo "$(REPO) now available for download at $$dload"

.PRECIOUS: icons/%.icns $(appdir)/%.app build/lib%.dylib
.PRECIOUS: icons/%.icns $(appdir)/%.app build/Frameworks/lib%.dylib
.PHONY: clean install uninstall test all tag release nightly doc
38 changes: 31 additions & 7 deletions entitlements.plist
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<?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>com.apple.security.app-sandbox</key>
<true/> -->
<key>com.apple.security.get-task-allow</key>
<true/>
</dict>
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>com.github.kfix.macpin</string>
</array>
<!-- <key>com.apple.security.app-sandbox</key>
<true/> -->
<!-- <key>com.apple.security.inherit/key>
<true/> -->
<key>com.apple.security.get-task-allow</key>
<true/> <!-- for Safari remote debugging -->
<!--
<key>com.apple.security.temporary-exception.files.home-relative-path.read-only</key>
<array>
<string>/Library/</string>
</array>
<key>com.apple.security.files.user-selected.executable</key>
<key>seatbelt-profiles</key>
<array>
</array>
<key>com.apple.security.scripting-targets</key>
<dict>
<key>com.apple.mail</key>
<array>
<string>com.apple.mail.compose</string>
</array>
</dict>
-->
</dict>
</plist>
5 changes: 2 additions & 3 deletions modules/MacPin/main.swift → execs/MacPin.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Cocoa
import MacPin

// gotta set these before MacPin()->NSWindow()
Expand All @@ -11,8 +12,6 @@ NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "__WebInspectorPageG

let app = NSApplication.sharedApplication() //connect to CG WindowServer, always accessible as var:NSApp
app.setActivationPolicy(.Regular) //lets bundle-less binaries (`make test`) get app menu and fullscreen button
//let applicationDelegate = MacPin()
let applicationDelegate = AppDelegate()
let applicationDelegate = MacPin.AppDelegate()
app.delegate = applicationDelegate
NSAppleEventManager.sharedAppleEventManager().setEventHandler(applicationDelegate, andSelector: "handleGetURLEvent:replyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) //handle `open url`
app.run()
21 changes: 17 additions & 4 deletions modules/MacPin/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Cocoa
import ObjectiveC
import WebKitPrivates

extension NSMenu {
func easyAddItem(title: String , _ action: String , _ key: String? = nil, _ keyflags: [NSEventModifierFlags] = []) {
Expand All @@ -19,10 +20,10 @@ extension NSMenu {
}

//@NSApplicationMain // doesn't work without NIBs, using main.swift instead :-(
public class AppDelegate: NSObject, NSApplicationDelegate {
public class AppDelegate: NSObject {

public var browserController = BrowserViewController()
public var windowController: WindowController
var browserController = BrowserViewController()
var windowController: WindowController

override public init() {
browserController.title = nil
Expand All @@ -33,6 +34,18 @@ public class AppDelegate: NSObject, NSApplicationDelegate {

func conlog(msg: String) { browserController.conlog(msg) }

func handleGetURLEvent(event: NSAppleEventDescriptor!, replyEvent: NSAppleEventDescriptor?) {
if let urlstr = event.paramDescriptorForKeyword(AEKeyword(keyDirectObject))!.stringValue {
warn("\(__FUNCTION__) `\(urlstr)` -> jsruntime.delegate.launchURL()")
jsruntime.delegate.tryFunc("launchURL", urlstr)
//replyEvent == ??
}
//replyEvent == ??
}
}

extension AppDelegate: NSApplicationDelegate {

//public func applicationDockMenu(sender: NSApplication) -> NSMenu?

public func applicationShouldOpenUntitledFile(app: NSApplication) -> Bool { return false }
Expand Down Expand Up @@ -125,7 +138,7 @@ public class AppDelegate: NSObject, NSApplicationDelegate {
windowController.window?.initialFirstResponder = browserController.view // should defer to selectedTab.initialFirstRepsonder, which is always a webview
windowController.showWindow(self)

NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector: "handleGetURLEvent:replyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) //handle `open url`
NSAppleEventManager.sharedAppleEventManager().setEventHandler(self, andSelector: "handleGetURLEvent:replyEvent:", forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) //route registered url scehems
}

//public func application(theApplication: NSApplication, openFile filename: String) -> Bool {}
Expand Down
29 changes: 20 additions & 9 deletions modules/MacPin/AppScriptRuntime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
Joey Korkames (c)2015
Special thanks to Google for its horrible Hangouts App on Chrome for OSX :-)
*/
// somehow get a JXA bridge working?
// https://developer.apple.com/library/mac/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/index.html

let jsruntime = AppScriptRuntime() //singleton

import Cocoa
import JavaScriptCore // https://github.com/WebKit/webkit/tree/master/Source/JavaScriptCore/API

public extension JSValue {
Expand All @@ -24,6 +27,7 @@ public extension JSValue {
func registerURLScheme(scheme: String)
func postNotification(title: String, _ subtitle: String?, _ msg: String)
func openURL(urlstr: String, _ app: String?)
func sleep(secs: Double)
}

public class AppScriptRuntime: NSObject, OSXScriptExports {
Expand All @@ -40,6 +44,22 @@ public class AppScriptRuntime: NSObject, OSXScriptExports {

//func log(msg: String) { }

func sleep(secs: Double) {
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(Double(NSEC_PER_SEC) * secs))
dispatch_after(delayTime, dispatch_get_main_queue()){}
}

/*
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
*/

func loadSiteApp() {
if let app_js = NSBundle.mainBundle().URLForResource("app", withExtension: "js") {
// https://bugs.webkit.org/show_bug.cgi?id=122763 -- allow evaluteScript to specify source URL
Expand Down Expand Up @@ -79,15 +99,6 @@ public class AppScriptRuntime: NSObject, OSXScriptExports {
}
}

func handleGetURLEvent(event: NSAppleEventDescriptor!, replyEvent: NSAppleEventDescriptor?) {
if let urlstr = event.paramDescriptorForKeyword(AEKeyword(keyDirectObject))!.stringValue {
warn("\(__FUNCTION__) `\(urlstr)` -> jsruntime.delegate.launchURL()")
delegate.tryFunc("launchURL", urlstr)
//replyEvent == ??
}
//replyEvent == ??
}

// func newTrayTab
// support opening a page as a NSStatusItem icon by the clock
// https://github.com/phranck/CCNStatusItem
Expand Down
16 changes: 8 additions & 8 deletions modules/MacPin/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import JavaScriptCore // https://github.com/WebKit/webkit/tree/master/Source/Ja

public class TabViewController: NSTabViewController { // & NSViewController
let URLBox = "Current URL"
let urlboxVC = URLBoxController(urlbox: NSTextField())!
let urlbox = URLBoxController(webViewController: nil)
let ShareButton = "Share URL"
let NewTabButton = "Open New Tab"
var cornerRadius = CGFloat(0.0) // increment above 0.0 to put nice corners on the window FIXME userDefaults
Expand All @@ -38,9 +38,7 @@ public class TabViewController: NSTabViewController { // & NSViewController

override public func tabView(tabView: NSTabView, didSelectTabViewItem tabViewItem: NSTabViewItem) {
super.tabView(tabView, didSelectTabViewItem: tabViewItem)
urlboxVC.representedObject = tabViewItem.viewController // KVC bind webview title and URL to urlbox
urlboxVC.nextResponder = tabViewItem.view // ensure all menu bindings will walk responder tree starting from webview
urlboxVC.view.nextKeyView = tabViewItem.view // TABbing off the urlbox will move focus to selected webview
urlbox.representedObject = tabViewItem.viewController

if let window = view.window {
if let view = tabViewItem.view {
Expand Down Expand Up @@ -74,7 +72,9 @@ public class TabViewController: NSTabViewController { // & NSViewController
override public func toolbarDefaultItemIdentifiers(toolbar: NSToolbar) -> [AnyObject] {
let tabs = super.toolbarDefaultItemIdentifiers(toolbar)
//return [ShareButton, NewTabButton] + tabs! + [NSToolbarFlexibleSpaceItemIdentifier]
return [ShareButton, NewTabButton, NSToolbarFlexibleSpaceItemIdentifier] + tabs!
//return [ShareButton, NewTabButton, NSToolbarFlexibleSpaceItemIdentifier] + tabs!
//return [NSToolbarFlexibleSpaceItemIdentifier, ShareButton] + tabs! + [NewTabButton, NSToolbarFlexibleSpaceItemIdentifier]
return [NSToolbarFlexibleSpaceItemIdentifier, ShareButton, NSToolbarFlexibleSpaceItemIdentifier] + tabs! + [NSToolbarFlexibleSpaceItemIdentifier, NewTabButton, NSToolbarFlexibleSpaceItemIdentifier]
//tabviewcontroller somehow remembers where tabs! was and keeps putting new tabs in that position
}

Expand Down Expand Up @@ -121,7 +121,7 @@ public class TabViewController: NSTabViewController { // & NSViewController
ti.visibilityPriority = NSToolbarItemVisibilityPriorityLow
ti.minSize = CGSize(width: 70, height: 24)
ti.maxSize = CGSize(width: 600, height: 24)
ti.view = urlboxVC.view
ti.view = urlbox.view
return ti

default:
Expand Down Expand Up @@ -261,11 +261,11 @@ public class BrowserViewController: TabViewController, BrowserScriptExports {

func toggleTransparency() { isTransparent = !isTransparent }

func loadSiteApp() { jsruntime.loadSiteApp() }
func editSiteApp() { NSWorkspace.sharedWorkspace().openFile(NSBundle.mainBundle().resourcePath!) }

func newTabPrompt() {
if let wvc = newTab(NSURL(string: "about:blank")!) {
//if let id: AnyObject = tabViewItemForViewController(wvc)?.identifier { tabSelected = id }
tabSelected = wvc
wvc.gotoButtonClicked(nil)
}
Expand Down Expand Up @@ -318,7 +318,6 @@ public class BrowserViewController: TabViewController, BrowserScriptExports {
}
return nil
}
func newTab(urlstr: String) { if let url = NSURL(string: urlstr) { newTab(url) } }
func newTab(url: NSURL) -> WebViewController? {
if let wvc = WebViewController(agent: nil) {
newTab(wvc)
Expand All @@ -344,6 +343,7 @@ public class BrowserViewController: TabViewController, BrowserScriptExports {
tab.initialFirstResponder = subvc.view
addTabViewItem(tab)
}
func newTab(urlstr: String) { if let url = NSURL(string: urlstr) { newTab(url) } }

func conlog(msg: String) { // _ webview: WKWebView? = nil
warn(msg)
Expand Down
1 change: 1 addition & 0 deletions modules/MacPin/Exts.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Cocoa
import WebKit
import WebKitPrivates
import JavaScriptCore

func warn(msg:String) { NSFileHandle.fileHandleWithStandardError().writeData((msg + "\n").dataUsingEncoding(NSUTF8StringEncoding)!) }
Expand Down
Loading

0 comments on commit b45a556

Please sign in to comment.