wmctrl Ubuntu 17.10 переключение, выше не переключение вниз

Попробовав ответы на этот вопрос: Как запустить приложение с установленным "Всегда сверху"? особенно в комментариях @MichaelTunnell:

Это лучший вариант для меня, потому что я могу создать bash-скрипт или сочетание клавиш (что я и сделал), используя эту команду, и таким образом я могу использовать его, когда мне это нужно, а не когда я этого не делаю. Я сделал изменения, хотя... Я хотел, чтобы ярлык всегда был включен сверху для активного окна, и только тогда, когда мне было нужно, вот моя команда. wmctrl -r :ACTIVE: -b toggle,above

Я мог всегда переключаться сверху в Ubuntu 16.10 или ниже, но не в Ubuntu 17.10, который я установил прямо сейчас и хотел бы иметь тот же ярлык

Я также попробовал этот пост, который в основном является более подробным постом комментария Майкла Таннелла: сочетание клавиш для всегда на вершине Ubuntu

Ярлык можно увидеть на изображении ниже, и он работает для установки для окна Always-on-top значения True, но даже если я снова использую ту же команду для "выключения", я не могу заставить активное приложение удалить это свойство.

Это ошибка в GNOME Ubuntu 17.10? Или я пропускаю какие-либо дополнительные настройки в этой конкретной версии?

1 ответ

Решение

wmctrl не полностью совместим с Wayland, который является сеансом по умолчанию в Ubuntu 17.10.

В качестве обходного пути вы переключаетесь обратно на сеанс Xorg после этого вопроса и ответов: как вы переключаетесь с Wayland обратно на Xorg в Ubuntu 17.10?

После долгих исследований и разработки того, как написать правильный код на bash, я создал одну команду, которая использует команды wmctrl в слое логики для эффективного переключения состояния "всегда наверху" на текущем рабочем столе GNOME! Вот:

bash -c 'wmctrl -r :ACTIVE: -b $([[ $(xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") _NET_WM_STATE) =~ "ABOVE" ]] && echo "remove" || echo "add"),above'

Он проверяет свойство активного окна "_NET_WM_STATE", используя xpropsи если он содержит текст "ВЫШЕ", это означает, что опция "всегда сверху" активна. Тогда он просто запускает wmctrl команда с параметром add или remove по мере необходимости.


Разбивка команд (каждая команда вставляется в следующую, заменяя заполнитель):

  • Получить идентификатор активного окна:

    xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}"

  • Получить состояние окна из xprop, используя идентификатор:

    xprop -id $(■) _NET_WM_STATE

  • Проверьте, содержит ли состояние 'ABOVE', указывая, что окно установлено на 'всегда сверху':

    [[ $(■) =~ "ABOVE" ]]

  • Верните "remove", если true, в противном случае верните "add":

    ■ && echo "remove" || echo "add"

  • запустить команду wmctrl, используя возвращаемое значение в качестве параметра

    wmctrl -r :ACTIVE: -b $(■),above

  • Отправить все это bash так что вы можете использовать подстановку команд ${ ... }bash логическая оценка [[ ... ]] и оператор соответствия регулярному выражению =~

    bash -c '■'

    Этот последний шаг, в частности, занял у меня очень много времени, чтобы понять. Пока я не понял, что сочетания клавиш не работают в bash по умолчанию, я не представлял, почему команды работали в консоли, так как я их тестировал, но молча терпел неудачу при запуске непосредственно в качестве сочетания клавиш. Это вело меня вверх по стене целую вечность!

Примечание: поскольку вам нужны кавычки вокруг команды, которую вы отправляете в bash, я должен был быть осторожен при написании команды, чтобы я никогда не заходил глубже, чем на один уровень (используя двойные кавычки). Любое дальнейшее вложение строк в кавычки потребовало бы множества запутанных обратных косых черт, чтобы избежать кавычек.

Я думаю, что решение Джеффа отличное, но мне нужно что-то более читаемое / адаптируемое, поэтому я написал этот быстрый сценарий bash, который работает очень похоже, но использует xdotool получить идентификатор для xprop

#!/bin/bash

# check if window is currently "ABOVE"
xprop -id $(xdotool getactivewindow) | grep NET_WM_STATE | grep -q ABOVE

if [ $? -eq 0 ]; then
        wmctrl -r :ACTIVE: -b remove,above
else
        wmctrl -r :ACTIVE: -b add,above
fi

Теперь я просто указываю ярлык на этот сценарий, и он работает для меня.

Думаю, довольно понятно. Единственная часть, которая может потребовать объяснения, - это$?который просто возвращает код выхода предыдущей команды (в данном случае grep: 0, если он совпал, 1, если он не удался). Обратите внимание, что, вероятно, не рекомендуется использовать код выхода таким образом, посколькуgrep может выйти из строя по какой-либо другой причине, но сбой этого скрипта представляет собой довольно низкий риск;)

Другие вопросы по тегам