OSX: Как определить, работает ли управление миссией?
Когда запускается Mission Control, он не позволяет приложениям получать события клавиатуры и мыши. Это также оставляет последнее приложение запущенным, думая, что оно все еще имеет фокус. Это проблема для меня, потому что я не получаю события keyUp или mouseUp, если я запускаю Mission Control, удерживая кнопку мыши или клавишу нажатой, и мое приложение будет вести себя так, как будто эта кнопка мыши или кнопка удерживается нажатой.
Я хотел бы либо прочитать события клавиатуры и мыши, даже когда контроль миссии активен, либо способ определить, что контроль миссии активен. В идеале я хотел бы иметь возможность сделать последнее, так как я фактически не могу использовать свое приложение во время работы Mission Control.
Я попробовал пару вещей без удачи:
- Используйте addGlobalMonitorForEventsMatchingMask, чтобы зарегистрировать глобальный монитор для событий клавиатуры и мыши. Это захватывает события мыши (но не события клавиатуры, хотя в документации сказано, что события keyDown должны отправляться на глобальный монитор), когда я переключаюсь на другое приложение, но, похоже, Mission Control не позволяет событиям распространяться на глобальные мониторы.
- Проверьте
[[NSRunningApplication currentApplication] {isActive, ownsMenuBar}]
. По-видимому, мое приложение активно, хотя оно не получает события! - Проверьте
[NSApp keyWindow] != nil
. Видимо, одно из моих окон должно получать ключевые события. Ни один из них не является. - Проверьте, является ли Mission Control одним из запущенных приложений, возвращаемых
[NSWorkspace runningApplications]
. Mission Control не отображается в этом списке при запуске.
Редактировать:
Я наконец-то решил эту проблему (хотя и не очень удовлетворительно). Для мыши оказывается, что вы можете запросить состояние нажатых кнопок с помощью [NSEvent pressedMouseButtons]
. Я просто отслеживаю то, что, по моему мнению, должно быть состояние мыши из событий NSLeftMouseDown и NSLeftMouseUp, и сравниваю это с [NSEvent pressedMouseButtons]
от времени, чтобы убедиться, что они согласованы. Если это не так, то я знаю, что что-то похитило мое событие NSLeftMouseUp и действую соответственно.
Что касается клавиатуры, я не смог найти способ запросить состояние клавиатуры, поэтому я не мог сделать аналогичный обходной путь. В итоге я отключил переключение приложений с помощью параметров презентации при нажатии клавиш.
Ответы
Ответ 1
Как минимум в OS X 10.10 вы можете использовать этот код, чтобы проверить, активен ли контроль миссии:
func missionControlIsActive() -> Bool
{
var result: Bool = false
let windowInfosRef = CGWindowListCopyWindowInfo(CGWindowListOption(kCGWindowListOptionOnScreenOnly), CGWindowID(0)) // CGWindowID(0) is equal to kCGNullWindowID
let windowList: NSArray = windowInfosRef.takeRetainedValue() // We own the returned CFArrayRef
for entry in windowList
{
if (entry.objectForKey("kCGWindowOwnerName") as! String) == "Dock"
{
var bounds: NSDictionary = entry.objectForKey("kCGWindowBounds") as! NSDictionary
if (bounds.objectForKey("Y") as! NSNumber) == -1
{
result = true
}
}
}
return result
}
В двух словах код проверяет, отображается ли на экране определенное окно, принадлежащее процессу док-станции OS X, и если оно находится в определенной позиции. Если оба условия будут выполнены, Mission Control будет активен прямо сейчас. Код будет работать в изолированном приложении, и никаких привилегий для вспомогательных устройств не требуется.
Ответ 2
Пробовал ли вы уровень bash с помощью NSTask? Что-то вроде ps -faxU <username>
должно содержать список всех запущенных процессов, а затем вы могли бы анализировать выходные данные, или вы могли бы использовать ps -faxU <username> | grep -i "mission control"
(Наверху я не уверен, как процесс может быть вызван, но sth вроде "управление миссией" " выглядит вполне законно). Возможно, это не самое элегантное решение, но если ничего не работает, это может стоить того.
Ответ 3
Может быть, я что-то пропустил, но вы пытались использовать метки событий вместо глобального мониторинга?
Ответ 4
Похоже, что DTrace имеет некоторую способность видеть, что управление миссией активировано. Попробуйте запустить:
sudo fs_usage -filesys | Миссия Grep
из командной строки, а затем запускает приложение управления миссиями из папки /Application.
Вы должны увидеть много результатов, связанных с запуском Mission Control. К сожалению, этот же вывод не появился с помощью короткого выреза или прокрутки клавиатуры. Конечно, использование DTrace в производственном коде не является тем, что я бы рекомендовал.