Carbon Accessibility API - Получение информации об окнах в разных пространствах

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

Теперь я решил написать простую программу командной строки, которая могла бы сохранять положение всех открытых окон и менять их положение, когда я хочу восстановить их положение.

Мне удалось сделать что-то, что отлично работает, с помощью API доступности, который позволяет мне управлять окнами, которые не являются частью моего рабочего пространства. Однако у меня есть проблема: программа может видеть только те окна, которые находятся в моем текущем пространстве (здесь я говорю о функции OSX Spaces).

Другими словами, когда я запускаю свою программу для сохранения позиций окон, она сможет сохранить только позиции окон в пространстве, в котором я сейчас нахожусь.

Еще немного о моей программе:

  • Он просматривает все запущенные процессы и получает их PID.
  • Он создает элементы приложения из этих PID (AXUIElementCreateApplication)
  • Он получает окна, связанные с этим приложением, а затем их позиции

При получении элементов окон из элемента приложения AXUIElementCopyAttributeValues возвращает мне только окна текущего пространства.

Теперь, есть ли способ управлять любыми окнами (в разных местах)? В противном случае я бы не возражал против программного изменения пробелов, чтобы получить все окна, но это кажется невозможным.

Любая помощь будет оценена по достоинству!


person Martin Cote    schedule 20.04.2010    source источник


Ответы (2)


Я не знаю задокументированного способа переключения пробелов.

Возможно, вам понадобится CGSPrivate.h - CGSSetWorkspace и др. Просто имейте в виду, что эти функции являются SPI и могут выйти из строя без предупреждения даже в выпуске 10.6.x.

person Nicholas Riley    schedule 21.04.2010

Если вы хотите избежать использования частных API-интерфейсов, вы можете воспользоваться тем фактом, что в Mission Control есть сочетания клавиш для перехода в различные области, и вы можете программно отправлять коды клавиш для их активации. Я написал об этом сообщение в блоге (http://ianyh.com/blog/2013/06/05/accessibility/) для оконного менеджера, над которым я работал, под названием Amethyst, в котором есть пример кода, который вы можете проверить в -[AMWindow moveToSpace:].

Краткая версия перемещается в пространство выглядит примерно так, как если бы использовалось значение по умолчанию ctrl + arrow key для перемещения в соседние пространства:

CGEventRef keyboardDownEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, true);
CGEventRef keyboardUpEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, false);

CGEventSetFlags(keyboardDownEvent, kCGEventFlagMaskControl);
CGEventSetFlags(keyboardUpEvent, 0);

CGEventPost(kCGHIDEventTap, keyboardDownEvent);
CGEventPost(kCGHIDEventTap, keyboardUpEvent);

CFRelease(keyboardEvent);
CFRelease(keyboardEventUp);

Вы можете комбинировать это с NSWorkspaceActiveSpaceDidChangeNotification для обхода всех пространств и сбора данных окна.

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

person ianyh    schedule 19.08.2013