2013-08-04 2 views
1

Я успешно реагирую на события клавиатуры через метод keyDown: мой оконный контроллер.
Проблема возникает при выполнении перетаскивания мышью:
События клавиатуры, похоже, отложены и будут стрелять только по мыши.Какао: при перетаскивании событий клавиатуры не будет срабатывать (NSEventTrackingRunLoopMode)

Чтобы было ясно, что я имею в виду:
• место журнал заявление в KeyDown вы контроллера оконного: (. На NSSlider для экс) метод
• запустить приложение, выполнить некоторые операции перетаскивания
• время поддерживая перетаскивание, нажмите любую клавишу: ничего не записывается на консоль.
• разблокировка: журналы появляются, yay ...

Управление, которое я перетаскиваю, является обычным NSSlider.
Я реализовал механизм перетаскивания, используя подход «Mouse-Tracking Loop». , что я понимаю, при перетаскивании основной режим цикла NSApplication переключается на NSEventTrackingRunLoopMode, тем самым ограничивая входящие события.

Итак, я просто добавил NSKeyDownMask & NSKeyUpMask в мой цикл отслеживания и при запуске, называемый self.nextResponder keyDown/up: метод соответственно. Моя проблема решена для этого конкретного пользовательского подкласса.

А как насчет контроля на какао? Я не могу закодировать это исключение ...

Я надеялся на «addLocalMonitorForEventsMatchingMask:» NSEvent по методу , но, увы, говорит доктор: «не будет вызываться для событий, которые потребляются вложенными события отслеживания петель, такие как управление отслеживание, отслеживание меню или перетаскивание окна ».

Итак, нет ли простого решения для приема клавиатурных событий независимо от режима runloop приложения?

+0

У меня есть аналогичная проблема в том, что таймеры, похоже, не срабатывают, когда я использую подход «Mouse-Tracking Loop» - независимо от того, какой режим цикла запуска я добавляю. Таймеры срабатывают, когда меню верхнего уровня сбрасывается ... - так какой-то прогресс в этом? –

ответ

2

Как вы нашли в документации для NSEvent класс 'addGlobalMonitorForEventsMatchingMask:handler:, это ограничение по дизайну.

Однако вы можете обойти его, используя инфраструктуру IOKit (в частности, части IOHID) для приема событий/прерываний устройства низкого уровня. Я просто должен был сделать это недавно, чтобы отслеживать некоторые нажатия клавиш во время перетаскивания мышью.

Основная суть заключается в создании менеджер IOHID с IOHIDManagerCreate(), затем добавить тип (ы) устройств к менеджеру, что он должен «контролировать» с IOHIDManagerSetDeviceMatchingMultiple(), зарегистрировать обратный вызов с менеджером по IOHIDManagerRegisterInputValueCallback(), планировать правильный бег -очередь для менеджера с IOHIDManagerScheduleWithRunLoop() и, наконец, откройте менеджера с помощью IOHIDManagerOpen().

Чтобы получить эти события низкого уровня во время перетаскивания мышью, выполните эту настройку в отдельном потоке. При планировании цикла выполнения для менеджера используйте CFRunLoopGetCurrent(), чтобы получить цикл выполнения для текущего потока, и вызовите CFRunLoopRun() после IOHIDManagerOpen().

This guide from Apple может помочь вам приступить к работе, а также this Q&A here on Stack Overflow.

+0

Я ударился головой о стену, пытаясь заставить IOHIDManager работать с полноэкранным приложением CGL. Я не понял из всех примеров, что вам нужно предоставить цикл цикла ... и я не понял, пока не прочитаю ваш ответ, что цикл выполнения, вероятно, должен быть в другом потоке. Спасибо! –

Смежные вопросы