diff --git a/Makefile b/Makefile deleted file mode 100644 index 9f92372..0000000 --- a/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -metalt: - cc -o metalt main.m -framework AppKit diff --git a/Metalt.xcodeproj/project.pbxproj b/Metalt.xcodeproj/project.pbxproj new file mode 100644 index 0000000..7ac5ec6 --- /dev/null +++ b/Metalt.xcodeproj/project.pbxproj @@ -0,0 +1,330 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 1772ED9820702E480066DAE5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1772ED9720702E480066DAE5 /* AppDelegate.swift */; }; + 1772ED9C20702E4A0066DAE5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1772ED9B20702E4A0066DAE5 /* Assets.xcassets */; }; + 1772ED9F20702E4A0066DAE5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1772ED9D20702E4A0066DAE5 /* Main.storyboard */; }; + 1772EDA820702FF80066DAE5 /* AltToMetaTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1772EDA720702FF80066DAE5 /* AltToMetaTransformer.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1772ED9420702E480066DAE5 /* Metalt.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metalt.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1772ED9720702E480066DAE5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 1772ED9B20702E4A0066DAE5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1772ED9E20702E4A0066DAE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 1772EDA020702E4A0066DAE5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1772EDA120702E4A0066DAE5 /* Metalt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Metalt.entitlements; sourceTree = ""; }; + 1772EDA720702FF80066DAE5 /* AltToMetaTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltToMetaTransformer.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1772ED9120702E480066DAE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1772ED8B20702E480066DAE5 = { + isa = PBXGroup; + children = ( + 1772ED9620702E480066DAE5 /* Metalt */, + 1772ED9520702E480066DAE5 /* Products */, + ); + sourceTree = ""; + }; + 1772ED9520702E480066DAE5 /* Products */ = { + isa = PBXGroup; + children = ( + 1772ED9420702E480066DAE5 /* Metalt.app */, + ); + name = Products; + sourceTree = ""; + }; + 1772ED9620702E480066DAE5 /* Metalt */ = { + isa = PBXGroup; + children = ( + 1772ED9720702E480066DAE5 /* AppDelegate.swift */, + 1772EDA720702FF80066DAE5 /* AltToMetaTransformer.swift */, + 1772ED9B20702E4A0066DAE5 /* Assets.xcassets */, + 1772ED9D20702E4A0066DAE5 /* Main.storyboard */, + 1772EDA020702E4A0066DAE5 /* Info.plist */, + 1772EDA120702E4A0066DAE5 /* Metalt.entitlements */, + ); + path = Metalt; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1772ED9320702E480066DAE5 /* Metalt */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1772EDA420702E4A0066DAE5 /* Build configuration list for PBXNativeTarget "Metalt" */; + buildPhases = ( + 1772ED9020702E480066DAE5 /* Sources */, + 1772ED9120702E480066DAE5 /* Frameworks */, + 1772ED9220702E480066DAE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Metalt; + productName = Metalt; + productReference = 1772ED9420702E480066DAE5 /* Metalt.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1772ED8C20702E480066DAE5 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = Alaminium; + TargetAttributes = { + 1772ED9320702E480066DAE5 = { + CreatedOnToolsVersion = 9.3; + }; + }; + }; + buildConfigurationList = 1772ED8F20702E480066DAE5 /* Build configuration list for PBXProject "Metalt" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 1772ED8B20702E480066DAE5; + productRefGroup = 1772ED9520702E480066DAE5 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1772ED9320702E480066DAE5 /* Metalt */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1772ED9220702E480066DAE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1772ED9C20702E4A0066DAE5 /* Assets.xcassets in Resources */, + 1772ED9F20702E4A0066DAE5 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1772ED9020702E480066DAE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1772ED9820702E480066DAE5 /* AppDelegate.swift in Sources */, + 1772EDA820702FF80066DAE5 /* AltToMetaTransformer.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 1772ED9D20702E4A0066DAE5 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 1772ED9E20702E4A0066DAE5 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1772EDA220702E4A0066DAE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1772EDA320702E4A0066DAE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 1772EDA520702E4A0066DAE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Metalt/Metalt.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 6FY44PDSLB; + INFOPLIST_FILE = Metalt/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = me.alaminium.Metalt; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 1772EDA620702E4A0066DAE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Metalt/Metalt.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 6FY44PDSLB; + INFOPLIST_FILE = Metalt/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = me.alaminium.Metalt; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1772ED8F20702E480066DAE5 /* Build configuration list for PBXProject "Metalt" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1772EDA220702E4A0066DAE5 /* Debug */, + 1772EDA320702E4A0066DAE5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1772EDA420702E4A0066DAE5 /* Build configuration list for PBXNativeTarget "Metalt" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1772EDA520702E4A0066DAE5 /* Debug */, + 1772EDA620702E4A0066DAE5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1772ED8C20702E480066DAE5 /* Project object */; +} diff --git a/Metalt.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Metalt.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..5b1868e --- /dev/null +++ b/Metalt.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Metalt.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Metalt.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Metalt.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Metalt/AltToMetaTransformer.swift b/Metalt/AltToMetaTransformer.swift new file mode 100644 index 0000000..f395830 --- /dev/null +++ b/Metalt/AltToMetaTransformer.swift @@ -0,0 +1,66 @@ +// +// AltToMetaTransformer.swift +// Metalt +// +// Created by Habib Alamin on 27/03/2018. +// Copyright © 2018 Alaminium. All rights reserved. +// + +import Foundation +import AppKit + +func appPrefersMeta() -> Bool +{ + return NSWorkspace.shared + .frontmostApplication?.localizedName == "Terminal" +} + +func keyEventLeftAltPressed(_ eventFlags: CGEventFlags) -> Bool +{ + return + (Int32(eventFlags.rawValue) & NX_DEVICELALTKEYMASK) == + NX_DEVICELALTKEYMASK +} + +func altToMetaTransformer(proxy: CGEventTapProxy, + type: CGEventType, + event: CGEvent, + refcon: UnsafeMutableRawPointer?) + -> Unmanaged? +{ + if (keyEventLeftAltPressed(event.flags) && appPrefersMeta()) + { + let eventSource = CGEventSource(event: event) + + let newEventCharDown = event.copy() + let newEventCharUp = event.copy() + let notMaskAlternate = + CGEventFlags(rawValue: ~CGEventFlags.maskAlternate.rawValue) + + newEventCharDown?.type = .keyDown + newEventCharUp?.type = .keyUp + newEventCharDown?.flags = event.flags.intersection(notMaskAlternate) + newEventCharUp?.flags = event.flags.intersection(notMaskAlternate) + newEventCharDown?.setSource(eventSource) + newEventCharUp?.setSource(eventSource) + + let newEventEscDown = + CGEvent(keyboardEventSource: eventSource, + virtualKey: 53, + keyDown: true) + let newEventEscUp = + CGEvent(keyboardEventSource: eventSource, + virtualKey: 53, + keyDown: false) + + newEventEscDown?.tapPostEvent(proxy) + newEventCharDown?.tapPostEvent(proxy) + newEventEscUp?.tapPostEvent(proxy) + newEventCharUp?.tapPostEvent(proxy) + + return nil + } else + { + return Unmanaged.passRetained(event) + } +} diff --git a/Metalt/AppDelegate.swift b/Metalt/AppDelegate.swift new file mode 100644 index 0000000..58b4cb0 --- /dev/null +++ b/Metalt/AppDelegate.swift @@ -0,0 +1,60 @@ +// +// AppDelegate.swift +// Metalt +// +// Created by Habib Alamin on 31/03/2018. +// Copyright © 2018 Alaminium. All rights reserved. +// + +import Cocoa + +import AppKit + +import Foundation + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + @IBOutlet weak var statusBarItemMenu: NSMenu! + + let statusBarItem = NSStatusBar.system + .statusItem(withLength: NSStatusItem.variableLength) + + func applicationDidFinishLaunching(_ aNotification: Notification) + { + statusBarItem.title = "⌥" + statusBarItem.menu = statusBarItemMenu + + let accessibilityCheckOptions = [ + kAXTrustedCheckOptionPrompt.takeRetainedValue() : kCFBooleanTrue + ] as CFDictionary + + if (!AXIsProcessTrustedWithOptions(accessibilityCheckOptions)) + { + // AX prompt remains after app termination. + NSApplication.shared.terminate(self) + } else + { + let tap = CGEvent + .tapCreate(tap: .cgAnnotatedSessionEventTap, + place: .tailAppendEventTap, + options: .defaultTap, + eventsOfInterest: + CGEventMask(1 << CGEventType.keyDown.rawValue), + callback: altToMetaTransformer, + userInfo: nil) + // TODO: handle `tap == nil` + + let runLoopSource = + CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0) + + CFRunLoopAddSource(CFRunLoopGetCurrent(), + runLoopSource, + .commonModes) + CFRunLoopRun() + } + } + + func applicationWillTerminate(_ aNotification: Notification) + { + } +} diff --git a/Metalt/Assets.xcassets/AppIcon.appiconset/Contents.json b/Metalt/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/Metalt/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Metalt/Assets.xcassets/Contents.json b/Metalt/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Metalt/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Metalt/Base.lproj/Main.storyboard b/Metalt/Base.lproj/Main.storyboard new file mode 100644 index 0000000..b30c835 --- /dev/null +++ b/Metalt/Base.lproj/Main.storyboard @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Metalt/Info.plist b/Metalt/Info.plist new file mode 100644 index 0000000..d96ea99 --- /dev/null +++ b/Metalt/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2018 Alaminium. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + LSUIElement + + + diff --git a/Metalt/Metalt.entitlements b/Metalt/Metalt.entitlements new file mode 100644 index 0000000..e89b7f3 --- /dev/null +++ b/Metalt/Metalt.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/README.md b/README.md deleted file mode 100644 index c8732e9..0000000 --- a/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Metalt -====== - -Metalt is a daemon for macOS that rewrites key events of the form left- + $KEY to the form Esc quickly followed by $KEY, but only if Terminal.app is the application which has the focus. This is useful for macOS users of Emacs on the console who use Terminal.app, instead of something like iTerm2, and would like to be able to use left- as META without having to give up right- for typing special characters or using global shortcuts. - -If you use iTerm2, there is a built-in option to do the same thing only for iTerm. diff --git a/main.m b/main.m deleted file mode 100644 index d3bd05c..0000000 --- a/main.m +++ /dev/null @@ -1,94 +0,0 @@ -#import - -bool appPrefersMeta(NSRunningApplication *app) -{ - NSString *appName = [app localizedName]; - - return [appName isEqualToString:@"Terminal"]; -} - -bool keyEventLeftAltPressed(CGEventFlags eventFlags) -{ - return (eventFlags & NX_DEVICELALTKEYMASK) == NX_DEVICELALTKEYMASK; -} - -CGEventRef eventCallback (CGEventTapProxy proxy, - CGEventType eventType, - CGEventRef event, - void *context) -{ - CGEventFlags flags = CGEventGetFlags(event); - NSRunningApplication *focusedApp = - [[NSWorkspace sharedWorkspace] frontmostApplication]; - - if (keyEventLeftAltPressed(flags) && appPrefersMeta(focusedApp)) - { - CGEventSourceRef eventSource = CGEventCreateSourceFromEvent(event); - - CGEventRef newEventCharDown = CGEventCreateCopy(event); - CGEventRef newEventCharUp = CGEventCreateCopy(event); - - CGEventSetType(newEventCharDown, kCGEventKeyDown); - CGEventSetType(newEventCharUp, kCGEventKeyUp); - CGEventSetFlags(newEventCharDown, flags & ~kCGEventFlagMaskAlternate); - CGEventSetFlags(newEventCharUp, flags & ~kCGEventFlagMaskAlternate); - CGEventSetSource(newEventCharDown, eventSource); - CGEventSetSource(newEventCharUp, eventSource); - - CGEventRef newEventEscDown = - CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)53, true); - CGEventRef newEventEscUp = - CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)53, false); - - CFRelease(eventSource); - - CGEventTapPostEvent(proxy, newEventEscDown); - CGEventTapPostEvent(proxy, newEventCharDown); - CGEventTapPostEvent(proxy, newEventEscUp); - CGEventTapPostEvent(proxy, newEventCharUp); - - CFRelease(newEventEscDown); - CFRelease(newEventCharDown); - CFRelease(newEventEscUp); - CFRelease(newEventCharUp); - - return NULL; - } else - { - return event; - } -} - -int main(int argc, const char * argv[]) -{ - @autoreleasepool { - CFMachPortRef tap = - CGEventTapCreate(kCGAnnotatedSessionEventTap, - kCGTailAppendEventTap, - kCGEventTapOptionDefault, - CGEventMaskBit(kCGEventKeyDown), - eventCallback, - NULL); - - if (tap) - { - CFRunLoopSourceRef runLoopSource = - CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0); - - CFRunLoopAddSource(CFRunLoopGetCurrent(), - runLoopSource, - kCFRunLoopCommonModes); - - CFRunLoopRun(); - - CFRelease(runLoopSource); - } else - { - printf("Metalt must be run as root to allow it to " - "read and modify low-level key events.\n"); - exit(1); - } - } - - return 0; -}