wmctrl: enfoca la ventana más reciente de una aplicación

wmctrl: enfoca la ventana más reciente de una aplicación

He creado algunos atajos que imitan el comportamiento Mod4+ de Unity num.

wmctrl -xa Sublime || subl

Lo que no me gusta es que una vez que se ejecuta sublime, siempre enfoca la primera ventana abierta. Me gustaría enfocar la última ventana "enfocada". Lo mismo que en Unity. ¿Existe una bandera para eso?

Respuesta1

Este script hace lo que quieres:

#!/bin/bash

app=$1
workspace=$(wmctrl -d | grep '\*' | cut -d ' ' -f1)
win_list=$(wmctrl -lx | grep $app | grep " $workspace " | awk '{print $1}')

IDs=$(xprop -root|grep "^_NET_CLIENT_LIST_STACKING" | tr "," " ")
IDs=(${IDs##*#})

for (( idx=${#IDs[@]}-1 ; idx>=0 ; idx-- )) ; do
    for i in $win_list; do
        if [ $((i)) = $((IDs[idx])) ]; then
            wmctrl -ia $i
            exit 0
        fi
    done
done

exit 1

EDITAR: esta secuencia de comandos siempre se centra en la última ventana enfocada, en lugar de recorrer las ventanas en el orden en que se abrieron.

EDITAR 2: modifiqué el script (resulta que wmctrl y xprop usan formatos ligeramente diferentes para mostrar números hexadecimales).

EDITAR 3: el nombre de la aplicación debe tomarse de la tercera columna de wmctrl -lx para evitar ciertos conflictos.

Respuesta2

He creado un conmutador de aplicaciones muy robusto usando wmctrl. Revisa miPublicación en foros de Ubuntuy mirespuesta de preguntabuntu.

Este es el script para ejecutar:

#!/bin/bash
app_name=$1
workspace_number=`wmctrl -d | grep '\*' | cut -d' ' -f 1`
win_list=`wmctrl -lx | grep $app_name | grep " $workspace_number " | awk '{print $1}'`


active_win_id=`xprop -root | grep '^_NET_ACTIVE_W' | awk -F'# 0x' '{print $2}' | awk -F', ' '{print $1}'`
if [ "$active_win_id" == "0" ]; then
    active_win_id=""
fi


# get next window to focus on, removing id active
switch_to=`echo $win_list | sed s/.*$active_win_id// | awk '{print $1}'`
# if the current window is the last in the list ... take the first one
if [ "$switch_to" == "" ];then
    switch_to=`echo $win_list | awk '{print $1}'`
fi


if [[ -n "${switch_to}" ]]
    then
        (wmctrl -ia "$switch_to") &
    else
        if [[ -n "$2" ]]
            then
                ($2) &
        fi
fi


exit 0

Respuesta3

Hice una combinación de ambas respuestas anteriores que me parece bastante conveniente. Permite:

  • establezca el foco en la ventana enfocada más recientemente de la aplicación (respuesta de Raul Laasner)si esa ventana aún no tiene el foco;
  • de lo contrario, pase a la siguiente ventana de la aplicación (respuesta de mreq);
  • si no hay ninguna ventana de la aplicación, abra una (ahora hay un segundo argumento opcional que especifica el comando a ejecutar en ese caso).

Aquí está el guión:

#!/bin/bash
if [ $# -lt 1 ] ; then
  echo "Usage : $0 <window name> [<command to run if there is no window with that name>]"
  exit 1
fi

app_name=$1

workspace_number=`wmctrl -d | grep '\*' | cut -d' ' -f 1`
win_list=`wmctrl -lx | grep $app_name | grep " $workspace_number " | awk '{print $1}'`

# Get the id of the active window (i.e., window which has the focus)
active_win_id=`xprop -root | grep '^_NET_ACTIVE_W' | awk -F'# 0x' '{print $2}' | awk -F', ' '{print $1}'`
if [ "$active_win_id" == "0" ]; then
    active_win_id=""
fi

# If the window currently focused matches the first argument, seek the id of the next window in win_list which matches it
if [[ "$win_list" == *"$active_win_id"* ]]; then

    # Get next window to focus on 
    # (sed removes the focused window and the previous windows from the list)
    switch_to=`echo $win_list | sed s/.*$active_win_id// | awk '{print $1}'`

    # If the focused window is the last in the list, take the first one
    if [ "$switch_to" == "" ];then
        switch_to=`echo $win_list | awk '{print $1}'`
    fi

# If the currently focused window does not match the first argument
else

    # Get the list of all the windows which do
    win_list=$(wmctrl -lx | grep $app_name | awk '{print $1}')

    IDs=$(xprop -root|grep "^_NET_CLIENT_LIST_STACKING" | tr "," " ")
    IDs=(${IDs##*#})

   # For each window in focus order
    for (( idx=${#IDs[@]}-1 ; idx>=0 ; idx-- )) ; do
        for i in $win_list; do

           # If the window matches the first argument, focus on it
            if [ $((i)) = $((IDs[idx])) ]; then
                wmctrl -ia $i
                exit 0
            fi
        done
    done
fi

# If a window to focus on has been found, focus on it
if [[ -n "${switch_to}" ]]
then
    (wmctrl -ia "$switch_to") &

# If there is no window which matches the first argument
else

    # If there is a second argument which specifies a command to run, run it
    if [[ -n "$2" ]]
    then
        ($2) &
    fi
fi

exit 0

Ejemplo de usos:

focus_window.sh vlc vlc
focus_window.sh gnome-control-center gnome-control-center
focus_window.sh gnome-terminal gnome-terminal

Respuesta4

Tarde para la respuesta, pero logré hacerlo funcionar correctamente, en mi caso, usando Firefox:

/usr/lib/firefox/firefox && sleep 0.5 && wmctrl -ia $(wmctrl -l Firefox | grep "Mozilla Firefox" | sort -r | head -n 1 | cut -d " " -f 1)

Explicación:

/usr/lib/firefox/firefox- Abre Firefox

sleep 0.5- Da algo de tiempo para que se abra la ventana.

wmctrl -ia- Centrarse en una ID de ventana específica

$(wmctrl -l Firefox | grep "Mozilla Firefox" | sort -r | head -n 1 | cut -d " " -f 1)- Obtiene el ID de la última ventana, que en mi caso está abierta en la página de inicio, por lo que su nombre es "Mozilla Firefox".

información relacionada