Заставьте wmctrl игнорировать окна, отличные от текущего рабочего пространства

Я очень полагаюсь на wmctrl, чтобы переключаться между окнами, чтобы избежать многократного ввода alt-tab. Я всегда использовал одно рабочее пространство, но теперь я хочу начать использовать более одного.

Мне было интересно, можно ли изменить контекст wmctrl, чтобы при вводе wmctrl -l, отображаются только окна из текущего рабочего пространства, а не все окна из всех рабочих пространств.

Например, если у меня в рабочей области открыто окно Firefox 1. У меня есть сочетание клавиш на ctrl+alt+f который выполняет wmctrl -a firefox, который переключается на Firefox. Если я открою новое окно Firefox в рабочей области 2 и введите ctrl+alt+f, он переключится на окно в рабочей области 1, что не то, что я хочу.

Любые предложения / идеи о том, как решить эту проблему?

РЕДАКТИРОВАТЬ: я использую compiz (Unity)

2 ответа

Решение

Если вы используете Compiz (запустите wmctrl -m если не уверен), wmctrl видит только 1 рабочий стол (2-е поле wmctrl -l, т.е. 0), но вы можете использовать опцию geometry (-G), чтобы узнать, какое окно на каком виртуальном рабочем столе. Все окна на вашем текущем рабочем столе будут иметь х-позицию между 0 и шириной вашего экрана. То же самое для y-позиции между 0 и высотой вашего экрана. Таким образом, вы можете использовать что-то подобное

#!/bin/bash

SCREEN_W=$(xwininfo -root | sed -n 's/^  Width: \(.*\)$/\1/p')
SCREEN_H=$(xwininfo -root | sed -n 's/^  Height: \(.*\)$/\1/p')

NAME='Navigator.Firefox'

wmctrl -xlG | awk -v W="$SCREEN_W" -v H="$SCREEN_H" -v NAME="$NAME" '$7==NAME && $3>=0 && $3<W && $4>=0 && $4<H {print $1}' | while read WINS; do wmctrl -ia "$WINS"; done

exit 0

Вы можете жестко закодировать ширину и высоту экрана, если хотите, и ИМЯ, если вы хотите использовать одну строку. Я не уверен, как вы хотите обрабатывать несколько окон, соответствующих NAME. Это сфокусирует их всех.

Для метасити число окон на рабочем столе можно найти, используя wmctrl -l и grepping 2-го поля.

У меня есть ответ на 2022 год, он довольно мощный, основанный на новейшей логике wmctrl, хорошо, что он имитирует автогорячую клавишу в Windows.

Итак, сначала нам нужно получить активный рабочий стол/рабочее пространство

      wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}'

После этого вы можете собрать его, чтобы получить список ТОЛЬКО окна на этом рабочем столе.

      D=$(wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}')
WINNAME="GVIM"
# Or you can get the full name as hex, more accurate for same window name
WIN=$(wmctrl -l | grep "  $DESKTOP " | grep -i $WIN | awk '{print $1}')
# WIN will be filled with 0xYYYY ID in hex or use simple winname
IN=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | awk --field-separator="$(hostname) " '{print $2}')
# Get the number of window contain it's name
STATUS=$(wmctrl -l | grep "  $DESKTOP " | grep -i $WINNAME | wc -l)

Затем вы можете проверить это, используя if like this (для winname)

      if [ $STATUS -gt 0 ]
then
   activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)      
   # zenity --notification --text="$activeWindow"
   if [[ $activeWindow =~ "$WINNAME" ]]
   then
       wmctrl -r "$WIN" -b toggle,hidden
   else
       wmctrl -a "$WIN"
   fi
else
   /usr/bin/gvim # if the app hasn't started yet, start it
fi

ИЛИ ЖЕ

Для шестнадцатеричного идентификатора

      # ... output omitted
   if [[ $activeWindow =~ "$WINNAME" ]]
   then
       wmctrl -i -r "$WIN" -b toggle,hidden
   else
       wmctrl -i -a "$WIN"
   fi
# ... output omitted, see source before

Итак, если вы соберете все это вместе (для использования имени окна, это не пуля, как если бы одно и то же имя между рабочим пространством, ну, оно будет следовать за другим рабочим пространством)

      #!/bin/bash

DESKTOP=$(wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}')
STATUS=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | wc -l)
WIN=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | awk --field-separator="$(hostname) " '{print $4}')
# zenity --notification --text="$STATUS $DESKTOP $WIN"

if [ $STATUS -gt 0 ]
then
   activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)      
   # zenity --notification --text="$activeWindow"
   if [[ $activeWindow =~ "GVIM" ]]
   then
       wmctrl -r $WIN -b toggle,hidden
   else
       wmctrl -a $WIN
   fi
else
   /usr/bin/gvim
fi

ИЛИ BULLET PROF, используя HEX ID

      #!/bin/bash

DESKTOP=$(wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}')
STATUS=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | wc -l)
WIN=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | awk '{print $1}')
#zenity --notification --text="$WIN"
if [ $STATUS -gt 0 ]
then
   activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)      
   #zenity --notification --text="$STATUS $DESKTOP \"$WIN\" $activeWindow"
   if [[ $activeWindow =~ "GVIM" ]]
   then
       wmctrl -i -r "$WIN" -b toggle,hidden
   else
       wmctrl -i -a "$WIN"
   fi
else
   /usr/bin/gvim
fi

-я вman wmctrlсредства :

-i Интерпретировать аргументы окна () как числовое значение, а не строковое имя окна. Если числовое значение начинается с префикса «0x», предполагается, что это шестнадцатеричное число.

Вы можете получить переключение окон, как AHK Script в Windows, но более мощное, чем должно.

Этот скрипт протестирован на XFCE и работает как с Xubuntu 22.04, так и с Fedora 36.

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