[Cocoa] 마우스 커서 감지 – NSTrackingArea

특정한 뷰에 마우스가 들어오거나 나갈 때에는 이벤트가 발생하는데, 경우에 따라서는 뷰 외부의 다른 객체가 뷰에 이러한 마우스 이벤트가 일어나는 것을 감지해야 할 필요가 있다. 예를 들면 NSView에 대해 별도의 서브 클래싱 없이 마우스 이벤트 처리를 하고 싶을 때처럼 말이다. 이럴 때는 NSTrackingArea를 만들어서 원하는 뷰에 추가해주는 것으로 서브클래싱 작업을 피할 수 있다.

NSTrackingArea

NSTrackingArea는 마우스 추적과 커서 업데이트 이벤트를 특정한 영역에서 구현해준다. 이 추적영역 객체를 생성할 때는 다음과 같은 정보가 필요하다.

1) 영역이 어디인지 (CGRect)
2) 추적 옵션은 무엇인지
3) 타겟은 누구인지 (id)
4) 또 선택적으로 추가로 던질 userInfo는 무엇인지

추적 영역이 붙는 뷰와 메시지를 받는 타겟이 동일할 필요는 없다. 이렇게 생성된 마우스 추적 영역은 뷰에 addTrackingArea: 메소드를 통해 추적영역을 추가하게 된다.

추적 옵션에 따라서, owner는  mouseEnterd:, mouseExited:, mouseMoved:, cursorUpdate: 등의 메시지를 받게 된다.

옵션 – NSTrackingAreaOption

추적옵션(NSTrackingAreaOption)은 다음과 같은 것들이 있다. 각각은 바이트 연산으로 묶어줄 수 있다.

  • NSTrackingMouseEnteredAndExited – 마우스가 들어오고 나가는 것을 감지
  • NSTrackingMouseMoved – 영역 내에서 마우스가 움직이는 것을 감지
  • NSTrackingCursorUpdated – 영역내에 마우스의 움직임을 모두 감지

또한 영역의 상태에 따라서도 추적 여부를 지정할 수 있는 옵션이 있다.

  • NSTrackingActiveWhenFirstResponder – 뷰가 First Responder일 때에만 동작
  • NSTrackingActiveInKeyWindow – 뷰가 키윈도에 있을 때만 동작
  • NSTrackingAciveInActiveApp – 활성화된 앱일 때만 동작
  • NSTrakingActiveAlways – 항상동작

그외 옵션

  • NSTrackingAssumeInside – 별로 쓰이지는 않는다. 추적영역을 벗어난 마우스 포인터가 여전히 그 뷰 안에 있다고 가정한다.
  • NSTrackingInVisibleRect – 뷰의 visibleRect에 동기화됨. 지정해준 rect 크기는 무시된다.
  • NSTrackingEnabledDuringMouseDrage – 드래깅 중간에 영역에 들어갔을 때도 추적을 활성화한다. 이 옵션이 켜지지 않으면 드래그하는 중에 이 영역을 지나갈 때에는 옵션이 활성화되지 않는다.

예제

NSTimer *fadeTimer;

-(void)awakeFramNib {
    NSTrackingArea *area = [[NSTrakingArea alloc] initWithRect:self.window.frame
        option:(NSTrakingMouseEnteredAndExited | NSTrakingActiveInAcitveApp | NSTrackingInVisibleRect)
        owner:self
        userInfo:nil];

    [self.window.contentView addTrackingArea:area];

}

-(void)mouseEnterd:(NSEvent*)event
{
    self.fadeTimer = nil;
    [[self.window animator] setAlphaValue:1.0];
}

-(void)mouseExited:(NSEvent*)event
{
    self.fadeTimer =<# 타이머를 생성 #>
}

소스코드 : http://www.box.com/s/69ded0033db0a452ddf1