Skip to content

Commit

Permalink
Merge pull request #1 from kentya6/v0.2
Browse files Browse the repository at this point in the history
v0.2
  • Loading branch information
kentya6 authored Dec 17, 2016
2 parents 3e691c0 + 0126e8e commit fcb287f
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 75 deletions.
8 changes: 4 additions & 4 deletions Fuwari.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
objects = {

/* Begin PBXBuildFile section */
7E08825A1DFE246400CF0F37 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 7E0882591DFE246400CF0F37 /* dsa_pub.pem */; };
BE23E42F1DFA1623004DA6B7 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE23E42E1DFA1623004DA6B7 /* Constants.swift */; };
BE23E4321DFB8BF4004DA6B7 /* Magnet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE23E4311DFB8BF4004DA6B7 /* Magnet.framework */; };
BE5896971DFCE965007CE7AC /* LoginServiceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE5896961DFCE965007CE7AC /* LoginServiceKit.framework */; };
Expand All @@ -16,6 +15,7 @@
BE5896A51DFD0E8C007CE7AC /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE5896A31DFD0E8C007CE7AC /* Fabric.framework */; };
BE5896A81DFD0EF0007CE7AC /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE5896A71DFD0EF0007CE7AC /* Crashlytics.framework */; };
BE5896AA1DFD1076007CE7AC /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE5896A91DFD1076007CE7AC /* Sparkle.framework */; };
BE6473101E05FD91005E0AB0 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = BE64730F1E05FD91005E0AB0 /* dsa_pub.pem */; };
BE7E82591DF72E7A00F3F2F8 /* FullScreenWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE7E82581DF72E7A00F3F2F8 /* FullScreenWindow.swift */; };
BE7E825B1DF74A2D00F3F2F8 /* FloatWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE7E825A1DF74A2D00F3F2F8 /* FloatWindow.swift */; };
BEC844F71DED859300A4A57A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEC844F61DED859300A4A57A /* AppDelegate.swift */; };
Expand All @@ -32,7 +32,6 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
7E0882591DFE246400CF0F37 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = "<group>"; };
BE23E42E1DFA1623004DA6B7 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
BE23E4311DFB8BF4004DA6B7 /* Magnet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Magnet.framework; path = Carthage/Build/Mac/Magnet.framework; sourceTree = "<group>"; };
BE5896961DFCE965007CE7AC /* LoginServiceKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LoginServiceKit.framework; path = Carthage/Build/Mac/LoginServiceKit.framework; sourceTree = "<group>"; };
Expand All @@ -42,6 +41,7 @@
BE5896A31DFD0E8C007CE7AC /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Fabric.framework; sourceTree = SOURCE_ROOT; };
BE5896A71DFD0EF0007CE7AC /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = SOURCE_ROOT; };
BE5896A91DFD1076007CE7AC /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Carthage/Build/Mac/Sparkle.framework; sourceTree = "<group>"; };
BE64730F1E05FD91005E0AB0 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = "<group>"; };
BE7E82581DF72E7A00F3F2F8 /* FullScreenWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullScreenWindow.swift; sourceTree = "<group>"; };
BE7E825A1DF74A2D00F3F2F8 /* FloatWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatWindow.swift; sourceTree = "<group>"; };
BEC844F31DED859300A4A57A /* Fuwari.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Fuwari.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -160,7 +160,7 @@
isa = PBXGroup;
children = (
BEC844FF1DED859300A4A57A /* Info.plist */,
7E0882591DFE246400CF0F37 /* dsa_pub.pem */,
BE64730F1E05FD91005E0AB0 /* dsa_pub.pem */,
);
name = "Supprting Files";
sourceTree = "<group>";
Expand Down Expand Up @@ -228,8 +228,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BE6473101E05FD91005E0AB0 /* dsa_pub.pem in Resources */,
BEC844FB1DED859300A4A57A /* Assets.xcassets in Resources */,
7E08825A1DFE246400CF0F37 /* dsa_pub.pem in Resources */,
BE58969A1DFCEB07007CE7AC /* Localizable.strings in Resources */,
BEF57FF21DFD5CB6006595B6 /* PreferencesWindowController.xib in Resources */,
BEC844FE1DED859300A4A57A /* Main.storyboard in Resources */,
Expand Down
7 changes: 3 additions & 4 deletions Fuwari/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {

configureMenu()

if let keyCombo = KeyCombo(keyCode: kVK_ANSI_5, cocoaModifiers: [.shift, .command]) {
if let keyCombo = KeyCombo(keyCode: kVK_ANSI_6, cocoaModifiers: [.shift, .command]) {
HotKey(identifier: "Capture", keyCombo: keyCombo, target: self, action: #selector(capture)).register()
}
if let keyCombo = KeyCombo(keyCode: kVK_ANSI_Comma, cocoaModifiers: [.command]) {
HotKey(identifier: "Preferences", keyCombo: keyCombo, target: self, action: #selector(openPreferences)).register()
}

// Show Login Item
if !defaults.bool(forKey: Constants.UserDefaults.loginItem) && !defaults.bool(forKey: Constants.UserDefaults.suppressAlertForLoginItem) {
Expand Down Expand Up @@ -61,10 +58,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

@objc private func openPreferences() {
NSApp.activate(ignoringOtherApps: true)
PreferencesWindowController.shared.showWindow(self)
}

@objc private func capture() {
NSApp.activate(ignoringOtherApps: true)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Constants.Notification.capture), object: nil)
eventMonitor = NSEvent.addGlobalMonitorForEvents(matching: [.mouseMoved, .leftMouseUp], handler: {
(event: NSEvent) in
Expand Down
10 changes: 8 additions & 2 deletions Fuwari/CaptureGuideView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ class CaptureGuideView: NSView {
private let cursorFont = NSFont.systemFont(ofSize: 10.0)
private let cursorSize = CGFloat(25.0)
private let cursorGuideWidth = CGFloat(1.0)
private lazy var coordinateLabelShadow: NSShadow = {
let shadow = NSShadow()
shadow.shadowColor = NSColor(red: 1, green: 1, blue: 1, alpha: 0.5)
shadow.shadowOffset = NSSize(width: 1, height: -1)
return shadow
}()

override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
Expand Down Expand Up @@ -61,8 +67,8 @@ class CaptureGuideView: NSView {
let path = NSBezierPath(ovalIn: cursorCenter)
path.fill()

(Int(cursorPoint.x).description as NSString).draw(at: NSPoint(x: cursorPoint.x + cursorSize / 2, y: cursorPoint.y - cursorSize / 2), withAttributes: [NSFontAttributeName : cursorFont])
(Int(cursorPoint.y).description as NSString).draw(at: NSPoint(x: cursorPoint.x + cursorSize / 2, y: cursorPoint.y - cursorSize), withAttributes: [NSFontAttributeName : cursorFont])
(Int(cursorPoint.x).description as NSString).draw(at: NSPoint(x: cursorPoint.x + cursorSize / 2, y: cursorPoint.y - cursorSize / 2), withAttributes: [NSFontAttributeName : cursorFont, NSShadowAttributeName : coordinateLabelShadow])
(Int(frame.height - cursorPoint.y).description as NSString).draw(at: NSPoint(x: cursorPoint.x + cursorSize / 2, y: cursorPoint.y - cursorSize), withAttributes: [NSFontAttributeName : cursorFont, NSShadowAttributeName : coordinateLabelShadow])
}

func reset() {
Expand Down
25 changes: 23 additions & 2 deletions Fuwari/FloatWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,25 @@ class FloatWindow: NSWindow {
if event.modifierFlags.rawValue & NSEventModifierFlags.command.rawValue != 0 {
switch event.keyCode {
case UInt16(kVK_ANSI_S):
if let image = image {
floatDelegate?.save(floatWindow: self, image: image)
let saveLabel = NSTextField(frame: NSRect(x: 10, y: 10, width: 80, height: 26))
saveLabel.stringValue = "Save"
saveLabel.textColor = .white
saveLabel.font = NSFont.boldSystemFont(ofSize: 20)
saveLabel.alignment = .center
saveLabel.drawsBackground = true
saveLabel.backgroundColor = NSColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.4)
saveLabel.wantsLayer = true
saveLabel.layer?.cornerRadius = 10.0
saveLabel.isBordered = false
saveLabel.isEditable = false
saveLabel.isSelectable = false
contentView?.addSubview(saveLabel)

DispatchQueue.main.asyncAfter(deadline: .now()) {
if let image = self.image {
saveLabel.removeFromSuperview()
self.floatDelegate?.save(floatWindow: self, image: image)
}
}
case UInt16(kVK_ANSI_W):
fade(isIn: false) {
Expand All @@ -48,6 +65,10 @@ class FloatWindow: NSWindow {
default:
break
}
} else if event.keyCode == UInt16(kVK_Escape) {
fade(isIn: false) {
self.floatDelegate?.close(floatWindow: self)
}
}
}

Expand Down
56 changes: 39 additions & 17 deletions Fuwari/FullScreenWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,19 @@
//

import Cocoa
import Carbon

class FullScreenWindow: NSWindow {

var captureDelegate: CaptureDelegate?

private lazy var captureGuideView: CaptureGuideView = {
guard let frame = NSScreen.main()?.frame else { return CaptureGuideView() }
let captureGuideView = CaptureGuideView(frame: frame)
let captureGuideView = CaptureGuideView(frame: self.frame)
return captureGuideView
}()

override init(contentRect: NSRect, styleMask style: NSWindowStyleMask, backing bufferingType: NSBackingStoreType, defer flag: Bool) {
guard let frame = NSScreen.main()?.frame else {
super.init(contentRect: contentRect, styleMask: style, backing: bufferingType, defer: flag)
return
}
super.init(contentRect: frame, styleMask: .borderless, backing: .buffered, defer: false)
super.init(contentRect: contentRect, styleMask: .borderless, backing: .buffered, defer: false)

isReleasedWhenClosed = true
displaysWhenScreenProfileChanges = true
Expand All @@ -38,45 +34,71 @@ class FullScreenWindow: NSWindow {
contentView = captureGuideView

NotificationCenter.default.addObserver(self, selector: #selector(mouseMoved(with:)), name: Notification.Name(rawValue: Constants.Notification.mouseMoved), object: nil)

NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
(event: NSEvent) -> NSEvent? in
if event.keyCode == UInt16(kVK_Escape) {
self.captureDelegate?.didCanceled()
}
return event
}
}

func startCapture() {
orderBack(nil)
captureGuideView.cursorPoint = NSEvent.mouseLocation()
captureGuideView.cursorPoint = NSPoint(x: NSEvent.mouseLocation().x - frame.origin.x, y: NSEvent.mouseLocation().y)
}

override func mouseMoved(with event: NSEvent) {
captureGuideView.cursorPoint = NSEvent.mouseLocation()
captureGuideView.cursorPoint = NSPoint(x: NSEvent.mouseLocation().x - frame.origin.x, y: NSEvent.mouseLocation().y - frame.origin.y)
}

override func mouseDown(with event: NSEvent) {
captureGuideView.startPoint = NSEvent.mouseLocation()
captureGuideView.cursorPoint = NSEvent.mouseLocation()
captureGuideView.startPoint = NSPoint(x: NSEvent.mouseLocation().x - frame.origin.x, y: NSEvent.mouseLocation().y - frame.origin.y)
captureGuideView.cursorPoint = NSPoint(x: NSEvent.mouseLocation().x - frame.origin.x, y: NSEvent.mouseLocation().y - frame.origin.y)
}

override func mouseDragged(with event: NSEvent) {
captureGuideView.cursorPoint = NSEvent.mouseLocation()
captureGuideView.cursorPoint = NSPoint(x: NSEvent.mouseLocation().x - frame.origin.x, y: NSEvent.mouseLocation().y - frame.origin.y)
}

override func mouseUp(with event: NSEvent) {
capture(rect: captureGuideView.guideWindowRect)
}

private func capture(rect: NSRect) {
let windowId = NSApplication.shared().windows[0].windowNumber
var upRightPoint = NSPoint.zero

NSScreen.screens()?.forEach {
upRightPoint = NSPoint(x: max(upRightPoint.x, $0.frame.origin.x + $0.frame.width), y: max(upRightPoint.y, $0.frame.origin.y + $0.frame.height))
}

let cgRect = CGRect(x: rect.origin.x, y: frame.height - rect.origin.y - rect.height, width: rect.width, height: rect.height)
guard let cgImage = CGWindowListCreateImage(cgRect, .optionOnScreenBelowWindow, CGWindowID(windowId), .bestResolution) else {
var originY = CGFloat(0)
if frame.origin.y > 0 {
originY = upRightPoint.y - frame.origin.y - frame.height - (rect.height + rect.origin.y)
} else {
originY = NSScreen.main()!.frame.height - frame.origin.y - (rect.origin.y + rect.height)
}

let cgRect = CGRect(x: rect.origin.x + frame.origin.x, y: originY, width: rect.width, height: rect.height)
guard let cgImage = CGWindowListCreateImage(cgRect, .optionOnScreenBelowWindow, CGWindowID(windowNumber), .bestResolution) else {
return
}

captureGuideView.reset()

orderOut(nil)
captureDelegate?.didCaptured(rect: rect, image: cgImage)

var captureOffsetY = CGFloat(0)
if frame.origin.y > 0 {
captureOffsetY = frame.origin.y - (cgRect.origin.y + cgRect.height)
} else {
captureOffsetY = -(cgRect.origin.y - upRightPoint.y + rect.height)
}
captureDelegate?.didCaptured(rect: CGRect(x: cgRect.origin.x, y: captureOffsetY, width: cgRect.width, height: cgRect.height), image: cgImage)
}
}

protocol CaptureDelegate {
func didCanceled()
func didCaptured(rect: NSRect, image: CGImage)
}
10 changes: 6 additions & 4 deletions Fuwari/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1</string>
<string>0.2</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>2</string>
<key>Fabric</key>
<dict>
<key>APIKey</key>
Expand All @@ -40,6 +40,8 @@
</dict>
</array>
</dict>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
Expand All @@ -50,9 +52,9 @@
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>SUPublicDSAKeyFile</key>
<string>dsa_pub.pem</string>
<key>SUFeedURL</key>
<string>https://fuwari-app.com/appcast.xml</string>
<key>SUPublicDSAKeyFile</key>
<string>dsa_pub.pem</string>
</dict>
</plist>
36 changes: 28 additions & 8 deletions Fuwari/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@ class ViewController: NSViewController {
@IBOutlet private weak var versionTextField: NSTextField!

fileprivate var windowControllers = [NSWindowController]()
private var fullScreenWindow = FullScreenWindow()
fileprivate var fullScreenWindows = [FullScreenWindow]()

override func viewDidLoad() {
super.viewDidLoad()

fullScreenWindow.captureDelegate = self
let controller = NSWindowController(window: fullScreenWindow)
controller.showWindow(nil)
windowControllers.append(controller)
fullScreenWindow.orderOut(nil)
for (i, screen) in NSScreen.screens()!.enumerated() {
fullScreenWindows.append(FullScreenWindow())
fullScreenWindows[i] = FullScreenWindow(contentRect: NSRect(x: screen.frame.origin.x, y: screen.frame.origin.y, width: screen.frame.width, height: screen.frame.height), styleMask: .borderless, backing: .buffered, defer: false)
fullScreenWindows[i].captureDelegate = self

print(screen.frame, fullScreenWindows[i].frame)
fullScreenWindows.append(fullScreenWindows[i])
let controller = NSWindowController(window: fullScreenWindows[i])
controller.showWindow(nil)
windowControllers.append(controller)
fullScreenWindows[i].orderOut(nil)
}

NotificationCenter.default.addObserver(self, selector: #selector(didSelectCaptureButton(_:)), name: Notification.Name(rawValue: Constants.Notification.capture), object: nil)

Expand All @@ -42,7 +49,9 @@ class ViewController: NSViewController {
@IBAction private func didSelectCaptureButton(_: NSButton) {
NSCursor.hide()

fullScreenWindow.startCapture()
fullScreenWindows.forEach { fullScreenWindow in
fullScreenWindow.startCapture()
}
}

@IBAction private func didSelectPreferencesButton(_: NSButton) {
Expand All @@ -56,9 +65,18 @@ class ViewController: NSViewController {

extension ViewController: CaptureDelegate {
func didCaptured(rect: NSRect, image: CGImage) {
print(rect.width, rect.height, image.width, image.height)
createFloatWindow(rect: rect, image: image)
NSCursor.unhide()
fullScreenWindows.forEach {
$0.orderOut(nil)
}
}

func didCanceled() {
NSCursor.unhide()
fullScreenWindows.forEach {
$0.orderOut(nil)
}
}
}

Expand Down Expand Up @@ -88,6 +106,8 @@ extension ViewController: FloatDelegate {
} catch {
print(error.localizedDescription)
}
} else {
floatWindow.level = Int(CGWindowLevelForKey(.maximumWindow))
}
}
}
Expand Down
Loading

0 comments on commit fcb287f

Please sign in to comment.