Skip to content

Commit

Permalink
Merge branch 'release/1.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJeong committed Mar 6, 2022
2 parents a3f396c + c7d8847 commit 9d4d6c8
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 47 deletions.
10 changes: 10 additions & 0 deletions BetterCapsLock.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
575AFB3927B8BE8700FB1F57 /* CGEventFlags+KeyCodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575AFB3827B8BE8700FB1F57 /* CGEventFlags+KeyCodes.swift */; };
575AFB3C27B8BEAA00FB1F57 /* Shortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575AFB3B27B8BEAA00FB1F57 /* Shortcut.swift */; };
57BB8B1F27D30FEB008E16A0 /* KeyInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57BB8B1E27D30FEB008E16A0 /* KeyInterceptor.swift */; };
57D17F3D27D46F9E001F05D2 /* StatusBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57D17F3C27D46F9E001F05D2 /* StatusBar.swift */; };
57D17F4227D473F1001F05D2 /* ModifierMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57D17F4127D473F1001F05D2 /* ModifierMode.swift */; };
57F0DD4625E8E8DB005E95DE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F0DD4525E8E8DB005E95DE /* AppDelegate.swift */; };
57F0DD4A25E8E8DB005E95DE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 57F0DD4925E8E8DB005E95DE /* Assets.xcassets */; };
57F0DD5725E8E911005E95DE /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F0DD5625E8E911005E95DE /* main.swift */; };
Expand All @@ -23,6 +25,8 @@
575AFB3827B8BE8700FB1F57 /* CGEventFlags+KeyCodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGEventFlags+KeyCodes.swift"; sourceTree = "<group>"; };
575AFB3B27B8BEAA00FB1F57 /* Shortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shortcut.swift; sourceTree = "<group>"; };
57BB8B1E27D30FEB008E16A0 /* KeyInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyInterceptor.swift; sourceTree = "<group>"; };
57D17F3C27D46F9E001F05D2 /* StatusBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBar.swift; sourceTree = "<group>"; };
57D17F4127D473F1001F05D2 /* ModifierMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModifierMode.swift; sourceTree = "<group>"; };
57F0DD4225E8E8DB005E95DE /* BetterCapsLock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BetterCapsLock.app; sourceTree = BUILT_PRODUCTS_DIR; };
57F0DD4525E8E8DB005E95DE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
57F0DD4925E8E8DB005E95DE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -76,6 +80,8 @@
57F0DD5625E8E911005E95DE /* main.swift */,
575AFB3827B8BE8700FB1F57 /* CGEventFlags+KeyCodes.swift */,
575AFB3B27B8BEAA00FB1F57 /* Shortcut.swift */,
57D17F3C27D46F9E001F05D2 /* StatusBar.swift */,
57D17F4127D473F1001F05D2 /* ModifierMode.swift */,
);
path = BetterCapsLock;
sourceTree = "<group>";
Expand Down Expand Up @@ -151,6 +157,8 @@
57F0DD4625E8E8DB005E95DE /* AppDelegate.swift in Sources */,
57F0DD5725E8E911005E95DE /* main.swift in Sources */,
57F0DD6E25E8EAD1005E95DE /* CapsLockManager.swift in Sources */,
57D17F4227D473F1001F05D2 /* ModifierMode.swift in Sources */,
57D17F3D27D46F9E001F05D2 /* StatusBar.swift in Sources */,
575AFB3C27B8BEAA00FB1F57 /* Shortcut.swift in Sources */,
575AFB3927B8BE8700FB1F57 /* CGEventFlags+KeyCodes.swift in Sources */,
57F0DD6F25E8EAD1005E95DE /* InputSourceManager.swift in Sources */,
Expand Down Expand Up @@ -292,6 +300,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.3.0;
PRODUCT_BUNDLE_IDENTIFIER = com.blogspot.crowjdh.BetterCapsLock;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "BetterCapsLock/BetterCapsLock-Bridging-Header.h";
Expand All @@ -314,6 +323,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.3.0;
PRODUCT_BUNDLE_IDENTIFIER = com.blogspot.crowjdh.BetterCapsLock;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "BetterCapsLock/BetterCapsLock-Bridging-Header.h";
Expand Down
38 changes: 2 additions & 36 deletions BetterCapsLock/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,18 @@

import Cocoa

// TODO: Implement options view for choosing between two modes
// Temporary flag for choosing between two modes.
let debugUseCmd = true

class AppDelegate: NSObject, NSApplicationDelegate {
static var statusItem: NSStatusItem!

func applicationDidFinishLaunching(_ aNotification: Notification) {
if (!CapsLockManager.requestAccess()) {
exit(1)
}
AppDelegate.initStatusItem()
AppDelegate.setStatusIcon()
StatusBar.instance.initialize()

CapsLockManager.initialize()

if !debugUseCmd || true {
if ModifierMode.getCurrent() == .CapsLock && SecretMode.enabled {
ShortcutManager.initialize()
}
}

static func initStatusItem() {
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
statusItem.highlightMode = false
statusItem.button?.setButtonType(.pushOnPushOff)

let editMenuItem = NSMenuItem()
editMenuItem.title = "Quit"
editMenuItem.action = #selector(quit(_:))
editMenuItem.target = self

let menu = NSMenu()
menu.addItem(editMenuItem)

statusItem.menu = menu
}

static func setStatusIcon(enabled: Bool = false) {
let icon = NSImage(named: NSImage.Name(enabled ? "StatusIconActive" : "StatusIcon"))
icon?.size = NSSize(width: 18.0, height: 18.0)
icon?.isTemplate = true

statusItem.button?.image = icon
}

@objc static func quit(_ sender: AnyObject?) {
exit(0)
}
}
6 changes: 3 additions & 3 deletions BetterCapsLock/CapsLockManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class CapsLockManager {
}

static func initialize() {
if debugUseCmd {
if ModifierMode.getCurrent() == .SecondaryCommand {
KeyInterceptor.interceptEvents(eventTypes: [.keyDown, .keyUp, .flagsChanged], callback: handleSecondaryCommand)
instance.registerSecondaryCommandEventListener()
} else {
} else if ModifierMode.getCurrent() == .CapsLock {
// Keep handling caps lock with same logic, since:
// 1. I tried to capture caps lock event with:
// CGEventType(rawValue: NSEvent.EventType.systemDefined)
Expand Down Expand Up @@ -126,7 +126,7 @@ class CapsLockManager {
IOHIDSetModifierLockState(ioConnect, Int32(kIOHIDCapsLockState), state)
IOServiceClose(ioConnect)

AppDelegate.setStatusIcon(enabled: state)
StatusBar.instance.setStatusIcon(enabled: state)
}

func getCapsLockState() -> Bool {
Expand Down
6 changes: 3 additions & 3 deletions BetterCapsLock/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSBackgroundOnly</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
Expand Down
26 changes: 26 additions & 0 deletions BetterCapsLock/ModifierMode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// ModifierMode.swift
// BetterCapsLock
//
// Created by DongHyun Jung on 2022/03/06.
//

import Foundation

private let KEY_MODIFIER_MODE = "modifier_mode"

enum ModifierMode: String, CaseIterable {
case CapsLock, SecondaryCommand

static func getCurrent() -> Self {
if let modifierMode = UserDefaults.standard.value(forKey: "modifier_mode") as? String {
return ModifierMode(rawValue: modifierMode)!
} else {
return ModifierMode.CapsLock
}
}

static func update(mode: Self) {
UserDefaults.standard.setValue(mode.rawValue, forKey: KEY_MODIFIER_MODE)
}
}
130 changes: 130 additions & 0 deletions BetterCapsLock/StatusBar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//
// StatusBar.swift
// BetterCapsLock
//
// Created by DongHyun Jung on 2022/03/06.
//

import Cocoa

class StatusBar {

static let instance = StatusBar()

var statusItem: NSStatusItem!

private init() {
}

func initialize() {
initStatusItem()
initMenu()
setStatusIcon()
}

func initStatusItem() {
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
statusItem.highlightMode = false
statusItem.button?.setButtonType(.pushOnPushOff)
}

func initMenu() {
let modifierMenuItem = createModifierMenuItem()
let secretMenuItem = createSecretMenuItem()
let quitMenuItem = createQuitMenuItem()

let menu = NSMenu()
menu.addItem(modifierMenuItem)
menu.addItem(secretMenuItem)
menu.addItem(quitMenuItem)

statusItem.menu = menu
}

func createModifierMenuItem() -> NSMenuItem {
let modifierMenuItem = NSMenuItem()
modifierMenuItem.title = "Switch mode"
modifierMenuItem.submenu = NSMenu()

for (index, modifierMode) in ModifierMode.allCases.enumerated() {
modifierMenuItem.submenu!.addItem(createModeMenu(index: index, modifierMode: modifierMode))
}

return modifierMenuItem
}

func createSecretMenuItem() -> NSMenuItem {
let secretMenuItem = NSMenuItem(title: SecretMode.enabled ? "Back to normal" : "You don't want this.", action: #selector(toggleSecretMode(_:)), keyEquivalent: "")
secretMenuItem.target = self
secretMenuItem.isAlternate = true
secretMenuItem.keyEquivalentModifierMask = [.option]

return secretMenuItem
}

func createQuitMenuItem() -> NSMenuItem {
let quitMenuItem = NSMenuItem(title: "Quit", action: #selector(quit(_:)), keyEquivalent: "")
quitMenuItem.target = self

return quitMenuItem
}

func createModeMenu(index: Int, modifierMode: ModifierMode) -> NSMenuItem {
let currMode = ModifierMode.getCurrent()
let isCurrentMode = modifierMode == currMode

let modeMenuItem = NSMenuItem(title: "\(modifierMode.rawValue)(\(isCurrentMode ? "On" : "Off"))", action: #selector(selectModifierMode(_:)), keyEquivalent: "")
modeMenuItem.target = self
modeMenuItem.tag = index

return modeMenuItem
}

func setStatusIcon(enabled: Bool = false) {
let icon = NSImage(named: NSImage.Name(enabled ? "StatusIconActive" : "StatusIcon"))
icon?.size = NSSize(width: 18.0, height: 18.0)
icon?.isTemplate = true

statusItem.button?.image = icon
}

@objc func toggleSecretMode(_ sender: AnyObject?) {
SecretMode.toggle()

relaunch()
}

@objc func selectModifierMode(_ sender: NSMenuItem) {
let mode = ModifierMode.allCases[sender.tag]
ModifierMode.update(mode: mode)

relaunch()
}

@objc func quit(_ sender: AnyObject?) {
exit(0)
}

func relaunch() {
let url = URL(fileURLWithPath: Bundle.main.resourcePath!)
let path = url.deletingLastPathComponent().deletingLastPathComponent().absoluteString
let task = Process()
task.launchPath = "/usr/bin/open"
task.arguments = [path]
task.launch()
exit(0)
}
}

class SecretMode {

static let KEY_SECRET_MODE_ENABLED = "isSecretModeEnabled"

static var enabled: Bool {
return UserDefaults.standard.bool(forKey: KEY_SECRET_MODE_ENABLED)
}

static func toggle() {
UserDefaults.standard.setValue(!enabled, forKey: KEY_SECRET_MODE_ENABLED)
}
}
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@
Fixes caps lock occasionally not working when switching input source with it.
This is for the people who uses caps lock key to change input source.
- To enable "real caps lock" feature, instead of long pressing caps lock key, enter ```Shift + Caps Lock```.
- You can also use **right ⌘** to switch input source.

# Usage
1. Archive & put ```BetterCapsLock.app``` to ```Application``` directory
2. System Preferences > Keyboard > Modifier Keys...
## Common
1. Build & archive & put ```BetterCapsLock.app``` to ```Application``` directory
2. System Preferences > Secyrity & Privacy > Privacy tab
- Add the application to ```Accessibility```

## For CapsLock users
- System Preferences > Keyboard > Modifier Keys...
- Map Caps Lock to ```No Action```
3. System Preferences > Secyrity & Privacy > Privacy tab
- Add the application to ```Accessibility```
4. System Preferences > Users & Groups > Login Items tab

## For right ⌘ users
![Usage](./resources/usage.png)

## Launch on startup
- System Preferences > Users & Groups > Login Items tab
- Add the application to the list
Binary file added resources/usage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9d4d6c8

Please sign in to comment.