2013-04-21 1 views
2

사용자가 우연히 무한 루프를 일으킬 수있는 스크립팅 언어를 구현하고 있습니다. 나는 마침표 (".") 키를 입력하는 동안 명령 키를 누른 채로 이러한 가출 고리를 취소 할 수있는 기회를 사용자에게 제공하려고합니다.좁은 루프에서 Command-Period를 확인하는 방법은 무엇입니까?

현재는 한 번에 모든 행에 대해,이 코드로 취소 확인 :

NSEvent * evt = [[NSApplication sharedApplication] nextEventMatchingMask: NSKeyDownMask untilDate: [NSDate date] inMode: WILDScriptExecutionEventLoopMode dequeue: YES]; 
if(evt) 
{ 
    NSString  * theKeys = [evt charactersIgnoringModifiers]; 
    if((evt.modifierFlags & NSCommandKeyMask) && theKeys.length > 0 && [theKeys characterAtIndex: 0] == '.') 
    { 
     // +++ cancel script execution here. 
    } 
} 

이의 문제는 심지어 스크립트가 실행되는 동안 사용자가 입력 할 수있는 키보드 이벤트를 먹는 것입니다 스크립트는 키 누르기를 확인할 수 있어야합니다. 또한 해당 NSKeyUp 이벤트를 dequeue하지 않습니다. 그러나 키 업 이벤트도 큐에서 제거하도록 지시하면 스크립트가 시작되기 전에 대기중인 키 누르기에 대해 keyUp을 큐에서 꺼낼 수 있습니다. 따라서 응용 프로그램에서 키가 릴리스되었음을 결코 알지 못할 수도 있습니다.

또한 실제로 취소 이벤트 인 것을 알기 전까지는 어떤 이벤트도 대기열에서 제외하지 않으려합니다.하지만 별도의 대기열 해제 호출은 없으며 두 번째 호출에서 맨 앞의 이벤트가 동일하다고 가정하는 것이 신뢰할 수 없다고 느낍니다. 하나. 그리고 그것이 첫 번째로 보장된다고하더라도, 그것은 사용자가 'a'를 입력 한 다음 Cmd-를 입력한다는 것을 의미합니다. 나는 'a'만보고 Cmd는 절대 볼 수 없다는 것을 의미합니다. 내가 이벤트를 큐에서 꺼내지 않으면 그 뒤에.

이전의 Carbon 대기 모드 인 GetKeys()보다 더 좋은 옵션이 있습니까? 다행히도 64 비트에서 사용할 수있는 것 같습니다.

또한 메뉴 막대에 스크립트를 취소하는 버튼을 추가하는 NSStatusItem을 추가하려고합니다. 하지만 어떻게하면 사용자를 허용하지 않는 방식으로 이벤트를 처리 할 수 ​​있습니까? 스크립트가 주 스레드의 룰러가 될 것으로 기대하면서 메뉴를 선택합니까?

제안 사항? 추천?

답변

1

이벤트 모니터를 사용하는 것이 좋습니다. NSApp에 이벤트를 요청하면 현재 프로세스에서 스크립트를 실행하고있는 것처럼 보이므로 자신의 프로세스에서만 이벤트를 모니터하면됩니다 (전역 적으로 모니터링하지 않아도됩니다).

는 (등, 이벤트 탭에 넣어, NSApplication 및 최우선 -sendEvent: 서브 클래스)이 작업을 수행하는 방법에는 여러 가지가 있지만,이 작업을 수행하는 가장 쉬운 방법은 함께 할 것 local event monitor :

id eventHandler = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDown handler:^(NSEvent *event) { 
    // check the runloop mode 
    // check for cmd-. 
    // abort the script if necessary 

    return event; 
}]; 

때 ' 모든 이벤트에 대해 모니터링 할 재, 모니터 등록을 취소하는 것을 잊지 마세요 : 데이브 네, 이것에 대해 갈 수있는 가장 쉬운 방법은 아마도 알 수 있듯이 -addLocalMonitorForEventsMatchingMask:를 사용

[NSEvent removeMonitor:eventHandler]; 
+0

슬프게도, 작동하지 않습니다 (방금 로컬 모니터를 시도했습니다). 귀하의 제안에 따라 실제로 이벤트를 큐에서 빼고 -sendEvent :를 통해 디스패치해야합니다. 하지만 그것은 스크립트가 실행되는 동안 사용자가 텍스트 필드 등을 입력 할 수 있다는 것을 의미합니다. 이는 내가 원하지 않는 것입니다. – uliwitness

+0

@uliwitness 나는 당신이 원하는 것을 이해하지 못한다고 생각합니다. '-sendEvent :'를 통해 이벤트가 전달되는 것을 막으려면 블록에서'nil'을 리턴하십시오. –

+0

스크립트를 실행 중입니다. 이러한 스크립트는 이벤트 대기열을 보거나 키 누르기를 처리하는 것을 포함하여 다른 프로그래밍 언어에서 수행 할 수있는 모든 작업을 수행 할 수 있습니다. 그렇지 않을 수도 있습니다. 스크립트 실행을 취소 할 수 있기를 원하지만 누군가가 실제로 취소하지 않는 한 정당한 키 이벤트를 스크립트에서 제외시키지 않으려합니다. AppKit은 sendEvent 내부에서 모니터를 실행하는 것처럼 보이므로 모니터 할 수있는 이벤트를 보내야합니다. 즉, 스크립트가 대기열의 이벤트를 더 이상 볼 수 없게됩니다. – uliwitness

2

.

신뢰할 수없는 느낌에도 불구하고 이벤트 대기열은 실제로 대기열이며 이벤트는 순서를 변경하지 않습니다. -nextEventMatchingMask:inMode:dequeue:NO으로 전화를 걸어 (이벤트 루프에서 표준 연습) 완벽하게 안전합니다. 이벤트를 검토하고 처리 할 것인지 결정한 다음 -nextEventMatchingMask:inMode:dequeue:YES으로 전화하여 이벤트를 사용하십시오. 두 호출간에 마스크와 모드가 동일한 지 확인하십시오.

+0

Dave에게 저의 경우에 효과가없는 이유에 대한 제 의견을 참조하십시오. 나는 이벤트를 처리하지 않고 스크립트를 실행하고있다. 이벤트 큐를 정기적으로 들여다보고 취소해야 하는지를 주기적으로 살펴보고 싶다. nextEvent는 대기열의 첫 번째 이벤트 만 가져옵니다. 누군가가 그것을 빼 놓지 않으면, 나는 Cmd-를 보지 못한다. 그 다음. – uliwitness

0

따라서 대신에 +[NSEvent modifierFlags]이 있습니다. 하지만 슬프게도 기간 키의 유스 케이스는 다루지 않습니다.

여기서 이벤트 큐의 핵심 문제는 API를 노출하는 것이 아닌 검색 할 수 있기를 원한다는 것입니다.내가 생각할 수있는 유일한 해결책은 배열로 모든 이벤트를 큐에 넣고 Command-. 이벤트를 확인한 다음 postEvent:atStart:을 사용하여 이벤트를 다시 대기시키는 것입니다. 예쁘지 않은.

아마도 최적화로 +[NSEvent modifierFlags]을 사용하면 명령 키를 누르고있을 때만 이벤트 대기열을 확인할 수 있지만 경쟁 조건이 나에게 열려있는 것 같습니다.

최종 제안이므로 -postEvent:atStart: (NSApplication 또는 NSWindow)을 덮어 쓰고 거기에 원하는 정보를 입력하십시오. 최악의 경우 디버깅이 흥미로울 수 있다고 생각합니다.

관련 문제