OSX - отключение общесистемных сенсорных жестов

Мне нужно программно отключить/подавить общесистемные сенсорные жесты в Mac OS. Я имею в виду такие жесты, как смахивание четырьмя пальцами между пробелами и т. д.

Я просмотрел EventTap, но это не вариант (несмотря на предыдущие отчеты здесь - возможно, он изменился в версии 10.8)

Я также пробовал множество способов программного изменения системных настроек. Например, я попытался использовать IOConnectSetCFProperties для службы, найдя ее с помощью IORegistryEntryCreateCFProperties.

Я также изучил панель настроек трекпада, чтобы увидеть, как они это делают, и попытался воспроизвести ее (игнорируйте любые несоответствия создания/выпуска, это просто тестовый код):

    NSInteger zero = 0;
    CFNumberRef numberWith0 = CFNumberCreate(kCFAllocatorDefault, kCFNumberNSIntegerType, &zero);

    CFMutableDictionaryRef propertyDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                                                    &kCFTypeDictionaryKeyCallBacks,
                                                                    &kCFTypeDictionaryValueCallBacks);

    CFDictionarySetValue(propertyDict, @"TrackpadFourFingerHorizSwipeGesture", numberWith0);

    io_connect_t connect = getEVSHandle(); // Found in the MachineSettings framework

    if (!connect)
    {
        NSLog(@"Unable to get EVS handle");
    }

    kern_return_t status = IOConnectSetCFProperties(connect, propertyDict);

    if (status != KERN_SUCCESS)
    {
        NSLog(@"Unable to get set IO properties");
    }

    CFRelease(propertyDict);
    CFPreferencesSetValue(CFSTR("com.apple.trackpad.fourFingerHorizSwipeGesture"), _numberWith0, kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

    CFPreferencesSetValue(CFSTR("TrackpadFourFingerHorizSwipeGesture"), _numberWith0, CFSTR("com.apple.driver.AppleBluetoothMultitouch.trackpad"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

    CFPreferencesSynchronize(kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);

    status = BSKernelPreferenceChanged(CFSTR("com.apple.driver.AppleBluetoothMultitouch.trackpad"));

В этом случае кажется, что он работает, ошибок нет, и параметр отключается на панели настроек системы, однако жест четырьмя пальцами продолжает работать. Я подозреваю, что выход из системы, а затем вход в нее будут иметь эффект, но я не пробовал, потому что в любом случае этого недостаточно.

Стоит отметить, что сама панель Pref также вызывает BSKernelPreferenceChanged, но я не знаю, какая это может быть структура, чтобы связать ее. Возможно, это ключ к проблеме...

ОБНОВЛЕНИЕ: На самом деле я нашел его и связал с ним. Добавление этого вызова ничего не изменило, хотя он возвращает 1, что может указывать на ошибку. Я добавил вызов в код выше.

Наконец, я попробовал это с терминала:

defaults write -globalDomain com.apple.trackpad.fourFingerHorizSwipeGesture 0
defaults write  com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadFourFingerHorizSwipeGesture 0

Это тоже не дает немедленного эффекта.

Я не верю, что это невозможно, должен же быть способ...

Совместимость с MAS не требуется.


person tarmes    schedule 28.11.2012    source источник
comment
Что касается бита записи по умолчанию, что вы подразумеваете под не имеет немедленного эффекта. Он работает после перезагрузки? Много раз вам приходилось использовать «док-станцию ​​killall» и «finder killall», чтобы некоторые настройки по умолчанию вступили в силу.   -  person jeremy    schedule 06.12.2012
comment
Привет, Джереми. Действительно, но мне нужно, чтобы это имело немедленный эффект, как это происходит, когда вы меняете параметры трекпада на панели настроек.   -  person tarmes    schedule 06.12.2012
comment
Вы можете попробовать перезапустить Finder, если не хотите выходить из системы.   -  person Grady Player    schedule 07.12.2012
comment
Извините, возможно, это неясно. Я хочу иметь возможность использовать трекпад для своего собственного приложения. В настоящее время это невозможно, потому что система берет на себя очень много жестов. Поэтому я хотел бы отключить жесты, когда мое приложение используется, а затем снова включить их, и я не хочу беспокоить пользователя повторным запуском, все это должно быть невидимым и мгновенным.   -  person tarmes    schedule 07.12.2012
comment
Почему вы пытаетесь это сделать? Если пользователь настроил эти жесты, почему вы пытаетесь переопределить настройки пользователя?   -  person Jonathan Grynspan    schedule 07.12.2012
comment
Так что пользователю будет доступно больше жестов для приложения. Они будут применяться только тогда, когда он/она удерживает горячую клавишу, после чего трекпад будет вести себя как обычно.   -  person tarmes    schedule 07.12.2012
comment
Это косвенно, но если у вас есть способ отслеживать вызовы API, вы можете увидеть, как Вспомогательные программы Magic Mouse работают. Или попробуйте связаться с автором BetterTouchTool и узнать, готов ли он дать совет.   -  person GargantuChet    schedule 13.12.2012
comment
Привет. Я поговорил с автором BTT (который мне очень помог), но он тоже не смог решить эту проблему.   -  person tarmes    schedule 13.12.2012


Ответы (2)


Я тоже пытаюсь это сделать.

Отводы событий не работают, равно как и представление, которое является первым ответчиком.

Из документов Apple:

Однако есть определенные общесистемные жесты, такие как смахивание четырьмя пальцами. для которых реализация системы имеет приоритет над любой обработкой жестов, выполняемой приложением.

Единственный способ, которым я смог остановить общесистемные жесты, — это использовать CGDisplayCapture. Это дает моему приложению эксклюзивный доступ ко всем событиям... но также и к полноэкранному контексту рисования.

Возможно есть возможность посмотреть какие звонки идут в кварц сервисы событий при входе в этот режим

https://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html

person Johan Nordberg    schedule 13.12.2012

Я думаю, что вы ищете не в том месте для отключения сенсорных событий. Способ, которым OSX (и многие другие системы) заключается в том, что первый респондент в цепочке представлений, обрабатывающий событие, остановит распространение события. Вам нужно будет написать обработчики событий в ваших представлениях для каждого из сенсорных событий, которые вы хотите обработать, и, если они существуют, ОС перестанет отправлять события на всем пути к искателю или любому другому приложению, следующему в очереди для обработки сенсорного экрана. Мероприятия.

См.: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/EventOverview/HandlingTouchEvents/HandlingTouchEvents.html

В частности: обработка событий Multi-Touch (вызовите setAcceptsTouchEvents, затем реализуйте касания...WithEvent...)

Надеюсь, это поможет!

person jeremy    schedule 07.12.2012
comment
Привет. Я понятия не имею, будет ли это работать для стандартного приложения, если глобальные жесты все еще будут происходить. В любом случае я не могу этого сделать, потому что пытаюсь добавить жесты в другое приложение (управляя им через Assistive API). Итак, я должен сделать то, что я пытаюсь сделать... - person tarmes; 07.12.2012
comment
На горячую клавишу вы можете загрузить прозрачный полноэкранный вид на экран, который может фиксировать события? - person jeremy; 07.12.2012
comment
К сожалению, нет, поскольку пользователю по-прежнему необходимо иметь возможность взаимодействовать с другим приложением. - person tarmes; 08.12.2012
comment
Я думаю, что они пройдут, если вы не справитесь с ними, возможно, стоит попробовать. Вы смотрели [NSEvent addGlobalMonitorForEventsMatchingMask]? - person jeremy; 08.12.2012