[macOS] 광역(?) 마우스 및 키보드 이벤트 인식
제목이 약간의 오해가 있을 수도 있어서 좀 더 자세히 적어보자면, 앱 내부의 마우스나 키 입력을 받는게 아니라 앱 윈도우에 포커스가 없는 상태에서 마우스나 키보드 이벤트를 받기 위한 내용이다. 흔히 쓰이는 윈도우의 '키보드 후킹'이라는 표현이 많이 비슷하기도 하다.
OS X 10.6 Snow Leopard 부터 추가된 NSEvent의 addGlobalMonitorForEvents(matching:handler:) 메소드를 이용하면 상당수의 컨트롤러 이벤트를 받는 것이 가능하다.
아래는 마우스 움직임을 핸들링 하기 위한 예제이다.
이 코드에서 matching 에 넘겨지는 값은 굉장히 많이 정의되어 있다. 예를 들자면 키가 떼어질 때의 이벤트 타입인 .keyUp 같은 것 말이다. 필요하다면 NSEventMask 정의를 찾아보자.
사용이 끝나면 NSEvent의 removeMonitor: 메소드를 이용해 핸들러를 제거해 주는 것을 잊지 말자.
참고로 위의 NSEvent.addGlobalMonitorForEvents(...)를 호출하면 리턴되는 값이 Any 이다. 별도의 타입이 정해져 있지 않은데 미래에는 바뀔 여지가 있을지도 모르겠다. (심지어 이전에는 AnyObject 였는데 Swift 3 로 오면서 Any 로 바뀌었다는 것도 기억하자)
하여간 이런 기능은 잘 쓰면 사용자에게 편리함을 줄 수도 있겠지만, 나쁜 의도로 쓰면 무서운 기능이 된다. 다행히도 macOS 에서는 이런 글로벌 이벤트를 받는 것만 가능하지 변경하거나 가로채어서 없애버리는 것은 불가능하다. 그리고 글로벌 이벤트를 핸들링 하는 앱은 Accessibility 를 통해 제어하는 것이 가능하기에 보안 문제도 윈도우에 비해서는 유연하다는 점은 정말 다행이다.
OS X 10.6 Snow Leopard 부터 추가된 NSEvent의 addGlobalMonitorForEvents(matching:handler:) 메소드를 이용하면 상당수의 컨트롤러 이벤트를 받는 것이 가능하다.
아래는 마우스 움직임을 핸들링 하기 위한 예제이다.
let eventMonitor = NSEvent.addGlobalMonitorForEvents( matching: [.mouseMoved, .keyDown]) { (event) in print("event: \(event)") }위 예제는 NSEvent 클래스를 이용해 글로벌 모니터를 붙여서 마우스 움직임과 키 입력을 감지하는 코드이다.
이 코드에서 matching 에 넘겨지는 값은 굉장히 많이 정의되어 있다. 예를 들자면 키가 떼어질 때의 이벤트 타입인 .keyUp 같은 것 말이다. 필요하다면 NSEventMask 정의를 찾아보자.
사용이 끝나면 NSEvent의 removeMonitor: 메소드를 이용해 핸들러를 제거해 주는 것을 잊지 말자.
NSEvent.removeMonitor(eventHandler)당연하겠지만, 이 모니터가 앱이 종료될 때 까지 쓰여야 한다면 딱히 제거할 필요는 없을 것이다.
참고로 위의 NSEvent.addGlobalMonitorForEvents(...)를 호출하면 리턴되는 값이 Any 이다. 별도의 타입이 정해져 있지 않은데 미래에는 바뀔 여지가 있을지도 모르겠다. (심지어 이전에는 AnyObject 였는데 Swift 3 로 오면서 Any 로 바뀌었다는 것도 기억하자)
잡설(?)
macOS Sierra 부터인지 아닌지 잘 모르겠지만, 이상하게도 앱 윈도우에 포커스가 가 있으면 오히려 모니터가 동작하지 않는 이상증상을 발견했다. 물론 내 착오일지도 모르겠지만 뭔가 변화가 있었을지도 모르겠다.하여간 이런 기능은 잘 쓰면 사용자에게 편리함을 줄 수도 있겠지만, 나쁜 의도로 쓰면 무서운 기능이 된다. 다행히도 macOS 에서는 이런 글로벌 이벤트를 받는 것만 가능하지 변경하거나 가로채어서 없애버리는 것은 불가능하다. 그리고 글로벌 이벤트를 핸들링 하는 앱은 Accessibility 를 통해 제어하는 것이 가능하기에 보안 문제도 윈도우에 비해서는 유연하다는 점은 정말 다행이다.
댓글