Initial commit.

This commit is contained in:
2024-12-27 15:25:41 -08:00
commit d6e097506a
26 changed files with 1433 additions and 0 deletions

175
src/AppDelegate.swift Normal file
View File

@@ -0,0 +1,175 @@
import Cocoa
import Carbon
import ServiceManagement
import OSLog
struct Program {
let path: String
let name: String
let ext: String
}
func appActivatedHandler(nextHandler: EventHandlerCallRef?, theEvent: EventRef?, userData: UnsafeMutableRawPointer?) -> OSStatus {
print("App was activated!")
return noErr
}
class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
fileprivate static let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: AppDelegate.self)
)
var paths = ["/Applications", "/System/Applications",
"/System/Applications/Utilities",
"/Applications/Xcode.app/Contents/Applications",
"/System/Library/CoreServices/Applications"]
var programs: [Program] = []
let fileManager = FileManager.default
let window = PopoverPanel(viewController: SearchViewController())
func applicationDidFinishLaunching(_ notification: Notification) {
Self.logger.debug("applicationDidFinishLaunching")
NSRunningApplication.current.hide()
window.delegate = self
//GlobalEventTap.shared.enable()
for path in paths {
do {
let items = try fileManager.contentsOfDirectory(atPath: path)
for item in items {
let name = String(item.dropLast(4))
if item.hasSuffix(".app") {
if !programs.contains(where: { name == $0.name }) {
programs.append(Program(path: path, name: name, ext: ".app"))
}
}
}
} catch {
print("Error reading directory: \(error.localizedDescription)")
}
}
window.makeKeyAndOrderFront(nil)
// TODO: Implement Unregister and Uninstall.
// TODO: A user should be able to enter hot keys to trigger.
// We either can use local event monitor or let user choose
// from list.
var hotKeyRef: EventHotKeyRef?
let hotKeyID: EventHotKeyID = EventHotKeyID(signature: OSType("grap".fourCharCodeValue), id: 1)
// GetEventDispatcherTarget
var err = RegisterEventHotKey(UInt32(kVK_Space), UInt32(optionKey), hotKeyID, GetApplicationEventTarget(), UInt32(kEventHotKeyNoOptions), &hotKeyRef)
//let handler = NewEventHandlerUPP()
// Handler get executed on main thread.
let handler: EventHandlerUPP = { (inHandlerCallRef, inEvent, inUserData) -> OSStatus in
AppDelegate.logger.debug("Shortcut handler fired off.")
if let delegate = NSApplication.shared.delegate as? AppDelegate {
let window = delegate.window
if window.isKeyWindow {
window.resignKey()
} else {
window.makeKeyAndOrderFront(nil)
}
}
return noErr
}
var eventHandlerRef: EventHandlerRef? = nil
if err == noErr {
Self.logger.debug("Registered hot key.")
var eventType = EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed))
err = InstallEventHandler(GetApplicationEventTarget(), handler, 1, &eventType, nil, &eventHandlerRef)
if err == noErr {
Self.logger.debug("Event handler installed.")
} else {
Self.logger.debug("Failed to install event handler.")
}
} else {
Self.logger.debug("Failed to register hot key.")
}
}
//func applicationWillTerminate(_ notification: Notification) {
//}
func windowDidBecomeKey(_ notification: Notification) {
Self.logger.debug("Popover became key.")
}
func windowDidResignKey(_ notification: Notification) {
Self.logger.debug("Popover resigned key.")
if window.isVisible {
window.orderOut(nil)
}
}
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows: Bool) -> Bool {
Self.logger.debug("Application reopened.")
if !window.isKeyWindow {
window.makeKeyAndOrderFront(nil)
}
return true
}
}
extension String {
subscript(index: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: index)]
}
}
extension String {
public func levenshtein(_ other: String) -> Int {
let sCount = self.count
let oCount = other.count
guard sCount != 0 else {
return oCount
}
guard oCount != 0 else {
return sCount
}
let line : [Int] = Array(repeating: 0, count: oCount + 1)
var mat : [[Int]] = Array(repeating: line, count: sCount + 1)
for i in 0...sCount {
mat[i][0] = i
}
for j in 0...oCount {
mat[0][j] = j
}
for j in 1...oCount {
for i in 1...sCount {
if self[i - 1] == other[j - 1] {
mat[i][j] = mat[i - 1][j - 1] // no operation
}
else {
let del = mat[i - 1][j] + 1 // deletion
let ins = mat[i][j - 1] + 1 // insertion
let sub = mat[i - 1][j - 1] + 1 // substitution
mat[i][j] = min(min(del, ins), sub)
}
}
}
return mat[sCount][oCount]
}
}

View File

@@ -0,0 +1,33 @@
import Cocoa
import os
final class EditableNSTextField: NSTextField {
private let commandKey = NSEvent.ModifierFlags.command.rawValue
private let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue
override func performKeyEquivalent(with event: NSEvent) -> Bool {
if event.type == NSEvent.EventType.keyDown {
if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
switch event.charactersIgnoringModifiers! {
case "x":
if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true }
case "c":
if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true }
case "v":
if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true }
case "z":
if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true }
case "a":
if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self) { return true }
default:
break
}
} else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
if event.charactersIgnoringModifiers == "Z" {
if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true }
}
}
}
return super.performKeyEquivalent(with: event)
}
}

55
src/EventMonitor.swift Normal file
View File

@@ -0,0 +1,55 @@
import Cocoa
class EventMonitor {
fileprivate let mask: NSEvent.EventTypeMask
fileprivate var monitor: Any?
fileprivate init(mask: NSEvent.EventTypeMask) {
self.mask = mask
}
deinit {
stop()
}
func start() {
fatalError("start must be implemented by a subclass of EventMonitor")
}
func stop() {
if monitor != nil {
NSEvent.removeMonitor(monitor!)
monitor = nil
}
}
}
final class LocalEventMonitor: EventMonitor {
typealias Handler = (NSEvent) -> NSEvent?
private let handler: Handler
init(mask: NSEvent.EventTypeMask, handler: @escaping Handler) {
self.handler = handler
super.init(mask: mask)
}
override func start() {
monitor = NSEvent.addLocalMonitorForEvents(matching: mask, handler: handler)
}
}
final class GlobalEventMonitor: EventMonitor {
typealias Handler = (NSEvent) -> Void
private let handler: Handler
init(mask: NSEvent.EventTypeMask, handler: @escaping Handler) {
self.handler = handler
super.init(mask: mask)
}
override func start() {
monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler)
}
}

74
src/GlobalEventTap.swift Normal file
View File

@@ -0,0 +1,74 @@
import AppKit
import Carbon
import OSLog
fileprivate func handleGlobalEvents(proxy: CGEventTapProxy,
type: CGEventType, event: CGEvent,
refcon: UnsafeMutableRawPointer?
) -> Unmanaged<CGEvent>? {
let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: AppDelegate.self)
)
switch type {
case .keyDown:
//logger.debug(".keyDown")
if (event.flags.rawValue & CGEventFlags.maskAlternate.rawValue) == CGEventFlags.maskAlternate.rawValue &&
(event.flags.rawValue & (CGEventFlags.maskShift.rawValue | CGEventFlags.maskControl.rawValue | CGEventFlags.maskCommand.rawValue)) == 0 {
logger.debug("maskAlternate")
}
logger.debug("Option rawValue=\(CGEventFlags.maskAlternate.rawValue)")
// var keyCode = event.getIntegerValueField(.keyboardEventKeycode)
//if keyCode == 49 {
// logger.debug("EVENT TAP")
// return nil
//}
case .keyUp:
//logger.debug(".keyUp")
break
default:
break
}
//event.setIntegerValueField(.keyboardEventKeycode, value: keyCode) // NOTE: ???
return Unmanaged.passUnretained(event)
}
final class GlobalEventTap {
fileprivate static let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: GlobalEventTap.self)
)
static let shared = GlobalEventTap()
private init() {}
deinit {}
func enable() {
let eventMask = (1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue)
guard let eventTap = CGEvent.tapCreate(tap: .cgSessionEventTap,
place: .headInsertEventTap,
options: .defaultTap,
eventsOfInterest: CGEventMask(eventMask),
callback: handleGlobalEvents,
userInfo: nil) else {
Self.logger.debug("Failed to create event.")
return
}
Self.logger.debug("Event was created.")
let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0)
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes)
CGEvent.tapEnable(tap: eventTap, enable: true)
CFRunLoopRun()
}
}

33
src/Helpers.swift Normal file
View File

@@ -0,0 +1,33 @@
import AppKit
func systemImage(_ name: String, _ size: NSFont.TextStyle, _ scale: NSImage.SymbolScale, _ configuration: NSImage.SymbolConfiguration) -> NSImage? {
return NSImage(systemSymbolName: name, accessibilityDescription: nil)?
.withSymbolConfiguration(
NSImage.SymbolConfiguration(textStyle: size, scale: scale)
.applying(configuration)
)
}
func isDirectory(atPath path: String) -> Bool {
var isDir: ObjCBool = false
if FileManager.default.fileExists(atPath: path, isDirectory: &isDir) {
return isDir.boolValue
}
return false
}
extension String {
/// This converts string to UInt as a fourCharCode
public var fourCharCodeValue: Int {
var result: Int = 0
if let data = self.data(using: String.Encoding.macOSRoman) {
data.withUnsafeBytes({ (rawBytes) in
let bytes = rawBytes.bindMemory(to: UInt8.self)
for i in 0 ..< data.count {
result = result << 8 + Int(bytes[i])
}
})
}
return result
}
}

44
src/Info.plist Normal file
View File

@@ -0,0 +1,44 @@
<?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>Grapp</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>com.garikme.Grapp</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Grapp</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>0.1</string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key>
<string>15.0</string>
<key>DTSDKName</key>
<string>macosx15.0</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>13.0</string>
<key>LSUIElement</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

85
src/Makefile Normal file
View File

@@ -0,0 +1,85 @@
FLAGS = -g
CFLAGS = -g
#-O
MACOS_VERSION = 13.0
SDK = $(shell xcrun --show-sdk-path)
XCODE_PATH = $(shell xcode-select --print-path)
EXEC = Grapp
SRCMODULES = Helpers.swift EditableNSTextField.swift EventMonitor.swift \
GlobalEventTap.swift PopoverPanel.swift SearchViewController.swift \
AppDelegate.swift main.swift
ARMOBJMODULES = $(addprefix ./arm64/,$(SRCMODULES:.swift=.o))
X86OBJMODULES = $(addprefix ./x86_64/,$(SRCMODULES:.swift=.o))
LIBS =
FRAMEWORKS = -framework AppKit -framework ServiceManagement
./arm64/%.o: %.swift
swift -frontend -c -target arm64-apple-macos$(MACOS_VERSION) $(FLAGS) \
-primary-file $< $(filter-out $<, $(SRCMODULES)) $(LIBS) $(FRAMEWORKS) -sdk $(SDK) \
-module-name $(EXEC) -o $@ -emit-module
ifdef UNIVERSAL
./x86_64/%.o: %.swift
@swift -frontend -c -target x86_64-apple-macos$(MACOS_VERSION) \
$(FLAGS) -primary-file $< $(filter-out $<, $(SRCMODULES)) $(LIBS) $(FRAMEWORKS) \
-sdk $(SDK) -module-name $(EXEC) -o $@ -emit-module
endif
./arm64/$(EXEC): $(ARMOBJMODULES)
@ld -syslibroot $(SDK) -lSystem $(FRAMEWORKS) -arch arm64 -macos_version_min \
$(MACOS_VERSION).0 \
/Library/Developer/CommandLineTools/usr/lib/swift/macosx/libswiftCompatibilityPacks.a \
-sectcreate __TEXT __info_plist Info.plist \
-L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L \
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift \
-no_objc_category_merging -L $(XCODE_PATH) -rpath \
Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \
./arm64/main.o $(filter-out ./arm64/main.o, $(ARMOBJMODULES)) \
-o $@
ifdef UNIVERSAL
./x86_64/$(EXEC): $(X86OBJMODULES)
@ld -syslibroot $(SDK) -lSystem $(FRAMEWORKS) -arch x86_64 -macos_version_min \
$(MACOS_VERSION).0 \
/Library/Developer/CommandLineTools/usr/lib/swift/macosx/libswiftCompatibilityPacks.a \
-sectcreate __TEXT __info_plist Info.plist \
-L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L \
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift \
-no_objc_category_merging -L $(XCODE_PATH) -rpath \
Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \
./x86_64/main.o $(filter-out ./x86_64/main.o, $(X86OBJMODULES)) \
-o $@
endif
ifdef UNIVERSAL
$(EXEC): ./arm64/$(EXEC) ./x86_64/$(EXEC)
@lipo -create -output $(EXEC) $^
else
$(EXEC): ./arm64/$(EXEC)
@lipo -create -output $(EXEC) $^
endif
$(EXEC).app: $(EXEC)
@rm -rf $@
@mkdir -p $@/Contents/MacOS/ && \
mkdir -p $@/Contents/Resources/ && \
cp Info.plist $@/Contents/ && \
cp resources/AppIcon.icns $@/Contents/Resources/ && \
cp $(EXEC) $@/Contents/MacOS/ && \
codesign -s ${DEVELOPER_ID} -f --timestamp -o runtime $(EXEC).app
all: $(EXEC).app
run: all
@open $(EXEC).app
clean:
rm -rf $(EXEC) $(EXEC).app arm64 x86_64
mkdir arm64 x86_64
clean-all: clean

61
src/PopoverPanel.swift Normal file
View File

@@ -0,0 +1,61 @@
import Cocoa
import OSLog
class PopoverPanel: NSPanel {
fileprivate static let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: PopoverPanel.self)
)
override var canBecomeKey: Bool { true }
init(viewController: NSViewController) {
super.init(
contentRect: CGRect(x: 0, y: 0, width: 100, height: 100),
styleMask: [.titled, .nonactivatingPanel, .utilityWindow, .fullSizeContentView],
backing: .buffered,
defer: false
)
super.contentViewController = viewController
title = ""
//isMovable = false
isMovableByWindowBackground = false
isFloatingPanel = true
isOpaque = false
level = .statusBar
titleVisibility = .hidden
titlebarAppearsTransparent = true
animationBehavior = .none
collectionBehavior = [.moveToActiveSpace, .fullScreenAuxiliary, .transient]
isReleasedWhenClosed = false
hidesOnDeactivate = false
standardWindowButton(.closeButton)?.isHidden = true
standardWindowButton(.miniaturizeButton)?.isHidden = true
standardWindowButton(.zoomButton)?.isHidden = true
}
override func performKeyEquivalent(with event: NSEvent) -> Bool {
Self.logger.debug("performKeyEquivalent keyCode=\(event.keyCode)")
let commandKey = NSEvent.ModifierFlags.command.rawValue
if event.type == NSEvent.EventType.keyDown {
if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey,
event.charactersIgnoringModifiers! == "w" {
resignKey()
return true
} else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey,
event.charactersIgnoringModifiers! == "q" {
NSApplication.shared.terminate(self)
return true
} else if event.keyCode == 53 {
resignKey()
return true
}
}
return super.performKeyEquivalent(with: event)
}
}

View File

@@ -0,0 +1,175 @@
import AppKit
import OSLog
fileprivate enum ViewConstants {
static let spacing2: CGFloat = 2
static let spacing10: CGFloat = 10
static let spacing20: CGFloat = 20
static let spacing40: CGFloat = 40
}
class SearchViewController: NSViewController, NSTextFieldDelegate {
fileprivate static let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: SearchViewController.self)
)
var foundProgram: Program? = nil
private var appIconImage: NSImageView = {
//let image = NSImageView(image: NSApp.applicationIconImage)
let image = NSImageView()
image.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
image.imageScaling = .scaleAxesIndependently
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
private var searchInput: EditableNSTextField = {
let textField = EditableNSTextField()
textField.placeholderString = "Search programs . . ."
textField.bezelStyle = .roundedBezel
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
private var programsLabel: NSTextField = {
let textField = NSTextField()
textField.stringValue = ""
textField.isEditable = false
textField.isBezeled = false
textField.drawsBackground = false
textField.alignment = .left
textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .body).pointSize, weight: .bold)
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
private var settingsButton: NSButton = {
let button = NSButton()
button.image = systemImage("gearshape.fill", .title2, .large, .init(paletteColors: [.white, .systemRed]))
button.isBordered = false
button.action = #selector(openSettings)
button.sizeToFit()
button.toolTip = "Quit"
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private func addSubviews() {
view.addSubview(appIconImage)
view.addSubview(searchInput)
view.addSubview(programsLabel)
view.addSubview(settingsButton)
}
private func setConstraints() {
NSLayoutConstraint.activate([
appIconImage.widthAnchor.constraint(equalToConstant: 70),
appIconImage.heightAnchor.constraint(equalTo: appIconImage.widthAnchor, multiplier: 1),
appIconImage.topAnchor.constraint(equalTo: view.topAnchor, constant: ViewConstants.spacing20),
appIconImage.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -ViewConstants.spacing10),
appIconImage.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: ViewConstants.spacing10),
searchInput.widthAnchor.constraint(equalToConstant: 300),
searchInput.topAnchor.constraint(equalTo: appIconImage.topAnchor),
searchInput.leadingAnchor.constraint(equalTo: appIconImage.trailingAnchor, constant: ViewConstants.spacing10),
settingsButton.firstBaselineAnchor.constraint(equalTo: searchInput.firstBaselineAnchor),
settingsButton.leadingAnchor.constraint(equalTo: searchInput.trailingAnchor, constant: ViewConstants.spacing10),
settingsButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -ViewConstants.spacing10),
programsLabel.topAnchor.constraint(equalTo: searchInput.bottomAnchor, constant: ViewConstants.spacing10),
programsLabel.leadingAnchor.constraint(equalTo: appIconImage.trailingAnchor, constant: ViewConstants.spacing10),
programsLabel.trailingAnchor.constraint(equalTo: searchInput.trailingAnchor),
])
}
override func viewDidLoad() {
super.viewDidLoad()
searchInput.delegate = self
addSubviews()
setConstraints()
}
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.center()
}
override func loadView() {
self.view = NSView()
}
//private func fetchIcon() {
// for key in resultPaths.keys {
// }
//}
@objc
private func openSettings() {
}
func controlTextDidChange(_ obj: Notification) {
var list = ""
let programs = delegate.programs
for program in programs {
if program.name.lowercased().contains(searchInput.stringValue.lowercased()) {
if !list.isEmpty {
list += ", "
}
list += program.name + program.ext
foundProgram = program
break
} else {
foundProgram = nil
}
}
if let program = foundProgram {
programsLabel.stringValue = program.name + program.ext
let url = URL(fileURLWithPath: program.path).appendingPathComponent(program.name+program.ext)
appIconImage.image = NSWorkspace.shared.icon(forFile: url.path)
} else {
programsLabel.stringValue = ""
appIconImage.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
}
}
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
if commandSelector == #selector(NSResponder.insertNewline(_:)) {
if let program = foundProgram {
let url = URL(fileURLWithPath: program.path).appendingPathComponent(program.name+program.ext)
let config = NSWorkspace.OpenConfiguration()
NSWorkspace.shared.openApplication(at: url, configuration: config, completionHandler: { [weak self] application, error in
if let error = error {
Self.logger.debug("Failed to open application: \(error.localizedDescription)")
} else {
Self.logger.debug("Application opened successfully")
DispatchQueue.main.async {
if let window = self?.view.window {
window.resignKey()
}
}
}
})
}
// TODO: Send this whenever SearchViewController becomes visible.
NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self)
return true
} else if commandSelector == #selector(NSResponder.insertTab(_:)) {
return true
}
return false
}
}

8
src/main.swift Normal file
View File

@@ -0,0 +1,8 @@
import AppKit
import Foundation
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

BIN
src/resources/AppIcon.icns Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB