├── FarewellOfCapsDelay ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon-128.png │ │ ├── Icon-16.png │ │ ├── Icon-256.png │ │ ├── Icon-32.png │ │ ├── Icon-512.png │ │ ├── Icon-16@2x.png │ │ ├── Icon-32@2x.png │ │ ├── Icon-128@2x.png │ │ ├── Icon-256@2x.png │ │ ├── Icon-512@2x.png │ │ └── Contents.json │ └── AccentColor.colorset │ │ └── Contents.json ├── Info.plist ├── FarewellOfCapsDelay.entitlements ├── main.swift ├── PopupFix │ ├── Utils.swift │ ├── PopupFix.swift │ ├── ApplicationObserver.swift │ └── UIElement.swift ├── PreferenceDialog.swift ├── PreferenceHelper.swift ├── InputSourceManager.swift ├── InputManager.swift ├── UserDefaultWrapper.swift ├── AppDelegate.swift └── Base.lproj │ └── Main.storyboard ├── FarewellOfCapsDelay.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── james.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── xcshareddata │ └── xcschemes │ │ └── FarewellOfCapsDelay.xcscheme └── project.pbxproj ├── .gitignore ├── Karabiner.md └── README.md /FarewellOfCapsDelay/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-128.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-16.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-256.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-32.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-512.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-16@2x.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-32@2x.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-128@2x.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-256@2x.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GST-Main/FOCD/HEAD/FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Icon-512@2x.png -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay/FarewellOfCapsDelay.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay/main.swift: -------------------------------------------------------------------------------- 1 | import AppKit 2 | import os 3 | 4 | let app = NSApplication.shared 5 | let delegate = AppDelegate() 6 | let logger = Logger(subsystem: "com.GST.focd", category: "FOCD") 7 | app.delegate = delegate 8 | app.setActivationPolicy(.accessory) 9 | _ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) 10 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay.xcodeproj/xcuserdata/james.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FarewellOfCapsDelay.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1A7806BE2C71F88C0080D50A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### macOS ### 2 | # General 3 | .DS_Store 4 | .AppleDouble 5 | .LSOverride 6 | 7 | # Icon must end with two \r 8 | Icon 9 | 10 | 11 | # Thumbnails 12 | ._* 13 | 14 | # Files that might appear in the root of a volume 15 | .DocumentRevisions-V100 16 | .fseventsd 17 | .Spotlight-V100 18 | .TemporaryItems 19 | .Trashes 20 | .VolumeIcon.icns 21 | .com.apple.timemachine.donotpresent 22 | 23 | # Directories potentially created on remote AFP share 24 | .AppleDB 25 | .AppleDesktop 26 | Network Trash Folder 27 | Temporary Items 28 | .apdisk 29 | 30 | ### macOS Patch ### 31 | # iCloud generated files 32 | *.icloud 33 | 34 | ### Xcode ### 35 | ## User settings 36 | xcuserdata/ 37 | 38 | ## Xcode 8 and earlier 39 | *.xcscmblueprint 40 | *.xccheckout 41 | 42 | ### Xcode Patch ### 43 | *.xcodeproj/* 44 | !*.xcodeproj/project.pbxproj 45 | !*.xcodeproj/xcshareddata/ 46 | !*.xcodeproj/project.xcworkspace/ 47 | !*.xcworkspace/contents.xcworkspacedata 48 | /*.gcno 49 | **/xcshareddata/WorkspaceSettings.xcsettings 50 | -------------------------------------------------------------------------------- /Karabiner.md: -------------------------------------------------------------------------------- 1 | # Karabiner 사용가이드 2 | 3 | ## 키 매핑 4 | 5 | Caps Lock이 아닌 Right alt나 Right Command로 맵핑 가능. 6 | 7 | - Karabiner 설정 중 8 | - Karabiner에서 Complex Modifications에서 아래의 rule을 새로 추가 후 적용 9 | 10 | 아래는 Caps Lock을 Right Alt로 맵핑 예시: 11 | 12 | ```json 13 | { 14 | "description": "Right Alt를 Caps Lock으로 (반복 없음, 뗄 때는 무시)", 15 | "manipulators": [ 16 | { 17 | "from": { 18 | "key_code": "right_alt", 19 | "modifiers": { "optional": ["any"] } 20 | }, 21 | "to": [ 22 | { 23 | "key_code": "caps_lock", 24 | "repeat": false 25 | } 26 | ], 27 | "to_after_key_up": [ 28 | { 29 | "set_variable": { 30 | "name": "vk_none", 31 | "value": 0 32 | } 33 | } 34 | ], 35 | "type": "basic" 36 | } 37 | ] 38 | } 39 | ``` 40 | 41 | ## 충돌 해결 42 | 43 | FOCD가 Karabiner같은 프로그램이나 내부 권한, 혹은 FOCD 개발 시, 충돌되었을 때의 해결법 44 | 45 | 1. '설정 > 일반 > 로그인 항목 > 백그라운드에서 허용' 에서 Karabiner와 관련된 사항의 토글 버튼을 오프, FOCD 재부팅 후 다시 토글 온 46 |
47 | image
48 | 49 | 2. 1.이 안될 시, `tccutil`로 FOCD의 권한 초기화 후 다시 FOCD 실행 50 | 51 | ```bash 52 | $ tccutil reset All com.GST.focd 53 | ``` 54 | 55 | 56 | ## Copyright 57 | 58 | 이 가이드는 [@hanbat1mj](https://github.com/hanbat1mj) 님의 도움으로 작성되었습니다. -------------------------------------------------------------------------------- /FarewellOfCapsDelay/PopupFix/Utils.swift: -------------------------------------------------------------------------------- 1 | import ApplicationServices 2 | 3 | extension AXError: @retroactive CustomStringConvertible { 4 | public var description: String { 5 | switch self { 6 | case .success: "success" 7 | case .failure: "failure" 8 | case .illegalArgument: "illegalArgument" 9 | case .invalidUIElement: "invalidUIElement" 10 | case .invalidUIElementObserver: "invalidUIElementObserver" 11 | case .cannotComplete: "cannotComplete" 12 | case .attributeUnsupported: "attributeUnsupported" 13 | case .actionUnsupported: "actionUnsupported" 14 | case .notificationUnsupported: "notificationUnsupported" 15 | case .notImplemented: "notImplemented" 16 | case .notificationAlreadyRegistered: "notificationAlreadyRegistered" 17 | case .notificationNotRegistered: "notificationNotRegistered" 18 | case .apiDisabled: "apiDisabled" 19 | case .noValue: "noValue" 20 | case .parameterizedAttributeUnsupported: "parameterizedAttributeUnsupported" 21 | case .notEnoughPrecision: "notEnoughPrecision" 22 | @unknown default: "fuck" 23 | } 24 | } 25 | } 26 | 27 | extension Date { 28 | private static let timestampFormatter: DateFormatter = { 29 | let formatter = DateFormatter() 30 | formatter.dateFormat = "HH:mm:ss.SSSS" 31 | return formatter 32 | }() 33 | 34 | var timestamp: String { 35 | return Self.timestampFormatter.string(from: self) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "Icon-16@2x.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "Icon-32.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "Icon-32@2x.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "Icon-128.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "Icon-128@2x.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "Icon-256.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "Icon-256@2x.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "Icon-512.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "Icon-512@2x.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Farewell Of Capslock Delay 2 | 맥 운영체제에서 캡스락으로 입력기 전환 시 딜레이가 생기는 불편함을 해결해주는 애플리케이션 입니다. 3 | 4 | ## 설치 5 | macOS 14 Sonoma 기준 6 | 1. 앱 실행 7 | 2. 설정 > 개인정보 보호 및 보안 > 입력 모니터링 > 항목에 앱 추가 8 | 3. 설정 > 키보드 > 입력 소스 우측의 "편집" > Caps Lock 키로 ABC 입력 소스 전환 해제 9 | 10 | #### 추천사항 - 시작 프로그램 설정 11 | 일반 > 로그인 항목 > 로그인 시 열기 > 항목에 앱 추가 12 | 13 | #### 추천사항 - 캡스락 비활성화 14 | 키보드 > 키보드 단축키 > 보조 키 > 캡스락 키를 '동작없음'으로 설정 15 | 16 | > [!TIP] 17 | > '시스템 설정 마법사' 기능으로 한번에 설정할 수 있습니다. 18 | 19 | ## 사용법 20 | 앱을 실행합니다. 이 앱은 별도의 창 없이 상태 바에만 존재하는 앱입니다. 21 | 22 | ### 종료 23 | 상태 바에서 ⇪ 아이콘을 클릭해 종료 버튼 누르기 24 | 25 | ### 단축키 26 | * **CapsLock** - 한/영 전환 27 | * **Shift + CapsLock** - 캡스락 토글 28 | * **Option + CapsLock** - 세번째 입력기(일어/중국어)로 전환 29 | 30 | > [!Note] 31 | > 일어 입력기는 로마지만 지원하며 중국어 입력기는 병음 간체만 지원합니다. 32 | 33 | > [!Note] 34 | > 새로 추가된 입력기는 인식하지 않습니다. 앱을 종료 후 재실행 해주세요. 35 | 36 | 37 | ## 제거 38 | 앱 파일을 삭제 39 | 40 | ## Karabiner 사용시 41 | [가이드](https://github.com/GST-Main/FOCD/blob/master/Karabiner.md) 참고 42 | 43 | 44 | ## 업데이트 로그 45 | ### 1.1.0 46 | * 고부하 상태에서 간헐적인 한영전환 씹힘 문제를 완화하였습니다. 47 | * 캡스락 상태에선 캡스락키가 한영전환 대신 캡스락 해제로 작동합니다. 48 | * 상태 바 아이콘 숨기기 기능을 추가하였습니다. 아이콘이 숨겨져도 그대로 작동하며 앱을 한번 더 실행시 다시 나타납니다. 49 | 50 | ### 1.1.1 51 | * macOS 15.2에서의 비정상 작동 수정 52 | 53 | ### 1.2.0 54 | * 간헐적으로 한영 전환 팝업이 비정상적으로 등장하는 macOS 버그 픽스 기능을 추가했습니다. 55 | * 해당 기능을 사용하기 위해선 접근성 권한을 설정해주어야 합니다. 56 | * 앱 아이콘과 이름을 건전하게 변경하였습니다. 57 | 58 | ### 1.2.1 59 | * 한영전환 씹힘문제 개선 60 | * 팝업픽스 기능 비정상 작동 수정 61 | 62 | ### 1.3.0 63 | * 구름입력기 지원 64 | * 두벌식외 다른 한국어 레이아웃 지원 65 | * 캡스락 수동관리 : 키보드 설정에서 캡스락을 비활성화하면 인디케이터가 깜빡이지 않습니다 66 | * 설정 마법사 추가 67 | 68 | ## 알려진 문제 69 | * 아주 가끔식 입력이 밀리거나 씹히는 문제가 있습니다. 70 | * 간혹 일어•중국어 입력기 전환시 영어 입력모드로 진입합니다. 일어 모드 진입시 히라가나 입력모드로 전환되는 것이 의도된 바입니다. 71 | * 아이패드 유니버설 컨트롤 기능 사용시 아이패드에 포커스가 넘어가 있어도 캡스락이 맥에서 한/영 전환으로 동작합니다. 72 | * 팝업 제거 기능은 편법적인 방법을 사용하므로 순간 나타났다 사라질 수 있습니다. 73 | * 다른 접근성 프로그램과 함께 사용할 시 정상 작동하지 않을 수 있습니다. '설정 > 개인정보 보호 및 보안 > 입력 모니터링'에서 키보드 권한을 사용중인 다른 프로그램을 확인해주세요. 74 | 75 | # Disclaimer 76 | 이 소프트웨어를 사용하면서 발생하는 문제는 개발자가 아닌 사용자의 책임임. 77 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay.xcodeproj/xcshareddata/xcschemes/FarewellOfCapsDelay.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /FarewellOfCapsDelay/PreferenceDialog.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct PreferenceDialog: View { 4 | @State private var options: Set