본문 바로가기

카테고리 없음

[karabiner] 맥북 디테일하게 키매핑하기 - complex_modifications

나처럼 키보드 리매핑 없이는 못쓰는 사람들 분명히 있을 것이다

윈도우에서는 오토핫키를 통해서 키를 매핑해서 사용했고,

리눅스에서는 Key Mapper라는 프로그램이 존재했고(xmodmap은 다소 한계가 있는듯 느꼈었다)

맥에서는 Karabiner라는 오픈소스 프로그램을 통해서 키를 매핑할 수 있다

디바이스별로 다른 키매핑을 적용할 수 있기 때문에, 배열이 다른 키보드를 혼용할 때에도 좋고, 매핑 설정도 나름 디테일하다

그리고 autoHotkey에 비해서 더 pure하다는 생각이 든다 (내부 동작 구조는 시간이 나면 꼭 알아보고 싶다)

참고로 karabinber를 사용하면 Karabiner DriverKit VirtualHIDKeyboard 라는 가상 장치를 입력장치로 사용하는듯 하다(확실하지 않음)

 

Karabiner는 Karabiner-element 라는 전용 GUI 프로그램을 제공한다

따라서 프로그래밍에 능숙하지 않아도 이 프로그램 하나만으로 키를 매핑할 "수는" 있다. 

이 프로그램의 기본 사용법은 상당히 쉽고, 조금만 검색해보면 자료가 충분하기 때문에 굳이 언급하지는 않겠다

Simple modifications, Functions keys로 하나의 키를 원하는 키로 간편하게 변경할 수 있다

문제는 다음 탭인 Complex modifications로 넘어가면서 발생한다

 

 

Complex modifications

키를 커스텀해서 사용하려면, 단순히 하나의 키를 다른 키로 변경하여 사용할 수도 있긴 하지만, 

더 디테일한 설정이 요구될  때도 있다. 예를들면

  • 조합키
  • 같은 키라도 특정 조건 하에서 다른 동작을 주고 싶은 경우
  • 하나의 키에 여러 동작 부여  

Complex modifications는 이러한 경우들을 설정하는 옵션이다

문제는 이러한 설정들을 gui에서 직접 설정할 수 없고, 이미 다른 사람이 설정한 값을 받아오는 식으로 사용해야 한다는 것이다

물론 이미 만들어진 설정이 많이 존재하고, 입맛에 맞게 수정 또한 어느정도 가능하지만 저장이 불가능하고, 어디까지나 다른사람이 만든 것을 수정하는 것이기 때문에 GUI를 통한 설정에는 한계가 존재한다.

 

 

 

karabiner.json

사실 Karabiner에서 사용되는 모든 설정들은 모두 karabiner.json이라는 설정 파일 하나에 지정되어 있다

karabiner-element를 통해 설정을 변경하는 건 사실 이 파일을 편집하는 것과 마찬가지인 것이다

반대로 이 파일을 수정하면 Karabiner의 설정 또한 변경된다 (저장하는 순간 적용된다)

JSON은 개발을 몰라도 어느정도 눈치가 있으면 수정할 수 있다

이 JSON을 편하게 설정할 수 있는 karabiner-complex-rules-generator 라는 Web UI또한 존재한다

Karabiner Complex Rules Generator

karabiner-complex-rules-generator와 Karabiner 공식 메뉴얼을 통해 간편하게 karabiner.json 파일을 수정할 수 있다

해당 파일의 위치는 사용자디렉토리/.config/karabiner.json 이고 편집은 메모장, notepad++, vscode등 각자 편한 툴을 이용하면 된다

해당 파일을 간단히 살펴보겠다

{
    "global": {
        "check_for_updates_on_startup": true,
        "show_in_menu_bar": true,
        "show_profile_name_in_menu_bar": false
    },
    "profiles": [
        {
            "complex_modifications": {
                "parameters": {
                    "basic.simultaneous_threshold_milliseconds": 50,
                    "basic.to_delayed_action_delay_milliseconds": 500,
                    "basic.to_if_alone_timeout_milliseconds": 1000,
                    "basic.to_if_held_down_threshold_milliseconds": 500,
                    "mouse_motion_to_scroll.speed": 100
                },
                "rules": [
                --- 여기를 편집! ---
                예)
                	{
		        		"type": "  basic",
			    		"from": {
			        		"key_code": "semicolon",
		            		"modifiers": {
		                		"mandatory": ["shift"],
	    	            		"optional": ["caps_lock"]
			        		}
		        		},
		        		"to": [
			            	{
			            	    "key_code": "semicolon"
			            	}
			        	]
			    	},
			    	{
			        	"type": "basic",
			        	"from": {
			        	    "key_code": "semicolon",
			            	"modifiers": {
			                	"optional": ["caps_lock"]
			            	}
			        	},
			        	"to": [
			            	{
			                	"key_code": "semicolon",
			                	"modifiers": ["left_shift"]
			            	}
			        	]
			    	}
                    --- 여기까지 ----
                ]
            },
            "devices": [
                {
                    "disable_built_in_keyboard_if_exists": false,
                    "fn_function_keys": [],
                    "identifiers": {
                        "is_keyboard": true,
                        "is_pointing_device": false,
                        "product_id": 641,
                        "vendor_id": 1452
                    },
                    "ignore": false,
                    "manipulate_caps_lock_led": true,
                    "simple_modifications": []
                }
            ],
            "fn_function_keys": [
                {
                    "from": {
                        "key_code": "f1"
                    },
                    "to": [
                        {
                            "consumer_key_code": "display_brightness_decrement"
                        }
                    ]
                },
				
                ...중략...
                
                {
                    "from": {
                        "key_code": "f12"
                    },
                    "to": [
                        {
                            "consumer_key_code": "volume_increment"
                        }
                    ]
                }
            ],
            "name": "Default profile",
            "parameters": {
                "delay_milliseconds_before_open_device": 1000
            },
            "selected": true,
            "simple_modifications": [],
            "virtual_hid_keyboard": {
                "country_code": 0,
                "indicate_sticky_modifier_keys_state": true,
                "mouse_key_xy_scale": 100
            }
        }
    ]
}

profiles 항목 하위에 simple_modification, functions_keys, complex_modification 등 우리가 Karabiner-Elements를 통해 설정하던 모든 항목들이 존재함을 알 수 있다. 

우리는 이 중에서 complex_modification 항목을 편집하게 된다. (나머지는 Karabiner-Elements에서 설정한다)

각 Profile마다 다른 설정을 줄 수 있지만, 지금은 하나의 Profile만을 사용하는 것을 가정한다

 

 

매핑 실습

우선 내가 처음으로 설정한 것은, caps_lock의 위치에 fn 키를 매핑하고, fn키+h,j,k,l 를 조합하여 방향키로 사용하는 것이다.

우선 Karabiner-Elements를 통해 caps_lock을 fn으로 매핑해 주었다

Simple modification을 통한 단일 키 매핑

그리고 조합키를 만들기 위하여 karabiner-complex-rules-generator를 통해 JSON을 만들어 준다.

직접 작성할 수도 있지만, 이렇게 하는 것이 더 편리하다.

여기서 설정을 위해 몇가지 알아야 할 점들이 존재한다.

Karabiner Complex Rules Generator 

 

 

Modifier

제일 처음 알아야 될 요소는 Modifier이다.

alt-tab을 예로 들어보면 tab은 단독으로 사용되면 tab의 기능을 하지만, alt라는 조건키가 입력된 상태에서 사용되면 활성창을 전환하는 기능을 한다.

여기서 조건이 되는 alt라는 키를 Mandatory Modifier라고 한다.

그리고 tab이 바로 from 키가 된다. (반대로 tab이 Mandatory Modifier, alt가 from 키가 될 수도 있다.)

ctrl-alt-del와 같은 경우 경우에는 Mandatory Modifier 에 ctrl, alt 두 가지를 설정할 수도 있다.

나같은 경우에는 h를 왼쪽 방향키로 사용할 것이므로 h를 from key로, fn을 Mandatory Modifier로 설정해 주었다. 

Mandatory Modifier는 하나의 조건이다. 이제 h라는 키는 fn이 활성화된 상태에서는 방향키로 작동한다.

 

그런데, Mandatory Modifier만으로는 부족한 경우가 있다.

예를들어 방향키에 추가로 붙어서 새로운 동작을 실행하는 키들이 존재한다.

예를들어 방향키에 Command키를 추가하면, 한 글자가 아닌 한 문장의 처음과 끝으로 커서가 이동한다

이렇듯  추가적인 키는 Optional Modifier에 추가하고, 보통은 "any"로 추가하여 모든 키에 대한 추가 동작을 허용한다

그런데 한 가지 아쉬운것은 Mandatory Modifier에 Command, Option, Control, fn 등 기존 Modifier 키들만 사용이 가능하다는 것이다.

 

 

To Event

From Key에 대한 설정이 끝났으면 To Event를 통해 실제로 동작할 키에 대한 설정을 하게 된다

보통 나처럼 키 매핑이 목적인 경우에는 'ADD TO EVENT', 'ADD TO_IF_ALONE EVENT' 두 가지 항목을 설정하게 된다

이름으로 알 수 있듯이 키가 조합 키로 사용되었을 때와 단독으로 사용되었을 경우의 매핑을 각각 적용할 수 있다.

나같은 경우에는 'ADD TO EVENT' 의 항목의 Key Code 값으로 Left Arrow 값을 주었다.

To Event 역시 Modifier 설정을 통해 동작을 조합키로 설정할 수 있으며

repeat, lazy 플래그를 통해 더 디테일을 적용할 수도 있지만 다 작성하기엔 너무 길어질것 같으므로 메뉴얼을 참고하거나 추후에 다른 문서로 작성하려고 한다

 

 

Conditions

내가 작성한 Rule이 적용되는 조건을 작성할 수 있다.

예를들어서 특정한 애플리케이션에서만 키를 다르게 적용한다던지

키보드마다 다른 매핑을 사용한다던지 등의 설정을 적용할 수 있다.

특히 Apple 배열과, 우리가 흔히 사용하는 ANSI 배열 등 키보드의 종류에 따라 키 배열이 다르기 때문에, Condition 옵션으로 획일화하게 된다.

조건의 종류로는 디바이스 종류, 키보드 종류, input source(입력 언어) 등이 있어 디테일한 설정이 가능하다

Condition에 대한 내용은 추가로 작성하겠다

 

 

적용하기

다음은 Karabiner Complex Rule Generator로 작성을 마친 모습이다

화면 오른쪽에 설정 내용이 JSON으로 자동으로 생성되기 때문에 해당 내용을 복사해서 karabiner.json 파일에 복사하여 준다.

complex_modifications의 rules 내에 햇갈리지 않고 잘 복사하도록 유의한다

복사 후 저장하면 저절로 변경 내용이 적용된다.

만약 적용되지 않으면, 위치가 틀렸거나 설정이 잘못된 것이므로 검토하도록 한다

 

 

 

이 문서는 추후에 json 설정과 Karabiner-Element 개요 및 기본 사용법 두 가지의 문서로 나눌 계획이다