Как получить текущее активное окно с помощью Swift и Cocoa

#swift #macos #cocoa #safari-app-extension

#swift #macos #какао #safari-app-extension

Вопрос:

В настоящее время я разрабатываю расширение приложения Safari, которое состоит из двух частей:

  • Приложение только для строки состояния хоста
  • Расширение Safari

Далее хост-приложение предлагает глобальный ярлык, который открывает всплывающее окно в строке состояния. Однако я хочу проверить, какое окно приложения в данный момент активно, потому что я не хочу открывать всплывающее окно, если окно Safari в данный момент активно. Есть ли какой-либо способ узнать с помощью Swift, какое окно приложения в данный момент активно?

Спасибо за вашу помощь.

Комментарии:

1. Проверьте developer.apple.com/documentation/appkit/nsworkspace

2. Что делать, если Safari активен без окон?

Ответ №1:

Итак, с комментариями Александра и Вилеке, я думаю, что нашел решение.

С NSWorkspace.shared.frontmostApplication помощью вы можете проверить, активен ли Safari в данный момент. Но, как отметил Уилеке, это не означает, что у него есть активное окно. Поэтому мы CGWindowListCopyWindowInfo сначала получаем все окна и проверяем, принадлежит ли хотя бы одно из них Safari, сравнивая PID.

Таким образом, мы можем с уверенностью сказать, что Safari в настоящее время должно иметь активное окно, которое получает ключевые события. Это должно быть правдой, поскольку теперь существует способ, при котором Safari является самым передним без каких-либо окон или Safari в качестве окна, но в то же время не является самым передним.

Ну, если я что-то не пропустил. Но пока это работает.

Вот код, который я придумал:

 func safariIsActive() -> Bool {
        // Get the app that currently has the focus.
        let frontApp = NSWorkspace.shared.frontmostApplication!

        // Check if the front most app is Safari
        if frontApp.bundleIdentifier == "com.apple.Safari" {
            // If it is Safari, it still does not mean, that is receiving key events
            // (i.e., has a window at the front).
            // But what we can safely say is, that if Safari is the front most app
            // and it has at least one window, it has to be the window that
            // crrently receives key events.
            let safariPID = frontApp.processIdentifier

            // With this procedure, we get all available windows.
            let options = CGWindowListOption(arrayLiteral: CGWindowListOption.excludeDesktopElements, CGWindowListOption.optionOnScreenOnly)
            let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
            let windowInfoList = windowListInfo as NSArray? as? [[String: AnyObject]]

            // Now that we have all available windows, we are going to check if at least one of them
            // is owned by Safari.
            for info in windowInfoList! {
                let windowPID = info["kCGWindowOwnerPID"] as! UInt32
                if  windowPID == safariPID {
                    return true
                }
            }
        }
        return false
    }