Вот мой первоначальный ответ на предложенную вами проблему, который, как было заявлено, должен работать в довольно последних (ish) версиях MacOS:
use application "System Events"
set _P to a reference to (every process whose class of windows contains window)
set _W to a reference to (windows of _P whose value of attribute "AXMinimized" is false)
set value of attribute "AXMinimized" of _W to true
Я мог бы добавить, что если мы подставим значение каждой переменной в следующую строку, где на нее есть ссылка, и (для простоты) решим игнорировать фильтрацию, используемую для процессов и окон, становится очевидным, что эти четыре строки будут оценивать во время компиляции в эту единственную строку кода:
tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false
Однако вы (ОП) сообщили, что он был медленным и не всегда надежным, и, вероятно, использовал не итеративный, а рекурсивный метод.
Я жду подробностей об обстоятельствах, при которых приведенный выше сценарий был признан ненадежным.
Вы спросили, могу ли я создать код аналогичного итеративного характера/структуры для одного из предложенных вами методов.
Это скрипт, который сочетает в себе функциональность моего оригинального скрипта со структурой кода, взятой из вашего:
use application "System Events"
get the name of every application process whose class of windows contains window
repeat with P in the result
get (every window of process (contents of P) whose value of attribute "AXMinimized" is false)
repeat with W in the result
set the value of attribute "AXMinimized" of (contents of W) to true
end repeat
end repeat
Так же, как и ваш скрипт, здесь явно перебираются все процессы приложения, извлеченные из фильтра (фильтр в вашем — это свойство visible
для каждого process
, тогда как фильтр в моем — это набор window
объектов каждого process
). Вы вольны меняться, если чувствуете в этом необходимость.
Однако, оказавшись внутри цикла repeat
, который перебирает processes
, ваш сценарий забыл сделать итерацию через каждое окно, принадлежащее каждому процессу. Вот почему вам понадобился резервный оператор, который устанавливает для свойства visible
значение false
, что просто скрывает процесс приложения (то, что вы явно указали в своем OP, что вы не хотели делать).
Если свойство visible
не задано, единственным другим выполняемым действием будет щелчок пункта меню Minimize
один раз для каждого процесса. Это приведет к сворачиванию переднего окна (то есть того, которое в данный момент находится в фокусе) этого процесса приложения, но все остальные окна, принадлежащие ему, останутся без изменений, т. е. только одно окно. для каждого приложения процесс будет сведен к минимуму. Все остальные просто скрыты переключателем видимости.
Решением этой проблемы было создание второго цикла repeat
, вложенного в первый, который выполняет итерацию по всем окнам определенного процесса, полученным с помощью фильтра (который, как и прежде, я выбрал в качестве атрибута AXMinimized
).
Тогда достаточно просто установить для атрибута AXMinimized
для каждого окна значение true
.
Как вы указали, одним из преимуществ вашего скрипта является то, что он сворачивает окна быстрее, чем мой. Из того, что я могу сказать, по какой-то причине фактическое свертывание анимации происходит быстрее при запуске с помощью меню, чем при запуске через настройку значения атрибута. Поэтому я пошел дальше и создал скрипт, который не пытается устанавливать атрибуты окон, а вместо этого использует ваш механизм щелчка по пункту меню Minimize
:
use application "System Events"
set _P to a reference to (every application process whose visible is true)
repeat with P in (_P as list)
set frontmost of P to true
set _M to (a reference to menu 1 of menu bar item "Window" of menu bar 1 of P)
set _minimise to (a reference to menu item "Minimise" of _M)
set _minimize to (a reference to menu item "Minimize" of _M)
set _W to windows of P
set n to count _W
if n > 0 then perform action "AXRaise" of _W's front item
repeat n times
if (_minimize exists) and (_minimize is enabled) then
click _minimize
else if (_minimise exists) and (_minimise is enabled) then
click _minimise
end if
end repeat
end repeat
Этот скрипт, по сути, представляет собой переработанную версию вашего, использующую те же критерии фильтрации для своих процессов (whose visible is false
) и щелкающий пункт меню Minimize
(или Minimise
), чтобы свернуть окна. Он содержит как внешний цикл repeat
для processes
, так и внутренний цикл repeat
для windows
.
Честно говоря, трудно сказать, какой из них сворачивает окна быстрее, чем другой, поэтому я позволю вам судить об этом.
Однако, вспоминая то, что вы указали в своем первоначальном брифе, вы конкретно спросили:
- Для "глобального сворачивания действия, а не [для] прохождения через систему меню";
- Не предлагать другие предложения, "такие как "скрыть все" или "скрыть" функции. Я ищу [a] функцию "свернуть все открытые окна";
- Чтобы "[включить] анимацию."
Откровенно говоря, есть только одно решение, которое удовлетворяет всем этим критериям, и это исходный ответ, который я опубликовал. Другие решения, которые вы нашли, либо не работают, либо полагаются на скрытие окон приложений; последний вклад, который я предоставил выше, работает, но использует пункты меню, что не является вашим идеальным методом; а сценарий до этого, который впервые продемонстрировал вложенность двух циклов repeat
для итерации через оба процесса и окна, может быть продемонстрирован с помощью индуктивных рассуждений как сценарий, идентичный моему исходному решению, которое, несмотря на не имеет явных итерационных операторов, которые вы привыкли видеть в языке программирования, действительно по-прежнему выполняет итерацию по объектам process
и window
за кулисами.
Вы, конечно, можете выбрать любой метод, который вы хотите, так как это ваш проект и ваше конечное удовлетворение, которое важно при создании инструмента, который вы будете использовать изо дня в день. Но, чтобы высказать свое честное и окончательное мнение о наилучшем способе достижения того, что вы намереваетесь сделать, я настоятельно рекомендую вам выбрать сжатую форму моего первого ответа, которая представляет собой эту очень элегантную и простую строку кода:
tell application "System Events" to set value of attribute "AXMinimized" of windows of processes to false
person
CJK
schedule
15.03.2018