wmctrl - Fokussieren Sie das aktuellste Fenster einer App

wmctrl - Fokussieren Sie das aktuellste Fenster einer App

Ich habe einige Verknüpfungen erstellt, die das Mod4+ num-Verhalten von Unity nachahmen.

wmctrl -xa Sublime || subl

Was mir nicht gefällt, ist, dass Sublime, wenn es einmal läuft, immer das erste geöffnete Fenster fokussiert. Ich möchte das letzte „fokussierte“ Fenster fokussieren. Dasselbe wie in Unity. Gibt es dafür ein Flag?

Antwort1

Dieses Skript macht, was Sie wollen:

#!/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

BEARBEITEN: Dieses Skript konzentriert sich immer auf das zuletzt fokussierte Fenster, anstatt die Fenster in der Reihenfolge zu durchlaufen, in der sie geöffnet wurden.

BEARBEITEN 2: Ich habe das Skript geändert (es stellte sich heraus, dass wmctrl und xprop leicht unterschiedliche Formate für die Anzeige von Hexadezimalzahlen verwenden).

BEARBEITEN 3: Der App-Name sollte aus der 3. Spalte von wmctrl -lx übernommen werden, um bestimmte Konflikte zu vermeiden.

Antwort2

Ich habe einen sehr robusten App-Umschalter mit erstellt wmctrl. Schauen Sie sich meineBeitrag im Ubuntu-Forumund meinAskubuntu-Antwort.

Dies ist das zu startende Skript:

#!/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

Antwort3

Ich habe eine Kombination aus den beiden vorherigen Antworten erstellt, die ich recht praktisch finde. Sie ermöglicht:

  • den Fokus auf das zuletzt fokussierte Fenster der App setzen (Antwort von Raul Laasner)wenn dieses Fenster nicht bereits den Fokus hat;
  • andernfalls zum nächsten Fenster der App wechseln (Antwort von mreq);
  • Wenn kein App-Fenster vorhanden ist, öffnen Sie eines (es gibt jetzt ein optionales zweites Argument, das den in diesem Fall auszuführenden Befehl angibt).

Hier ist das Skript:

#!/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

Anwendungsbeispiele:

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

Antwort4

Die Antwort kommt spät, aber in meinem Fall hat es mit Firefox problemlos geklappt:

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

Erläuterung:

/usr/lib/firefox/firefox- Öffnet Firefox

sleep 0.5- Gibt dem Fenster etwas Zeit zum Öffnen

wmctrl -ia- Konzentrieren Sie sich auf eine bestimmte Fenster-ID

$(wmctrl -l Firefox | grep "Mozilla Firefox" | sort -r | head -n 1 | cut -d " " -f 1)- Ruft die letzte Fenster-ID ab, die in meinem Fall auf der Startseite geöffnet ist, daher lautet der Name „Mozilla Firefox“.

verwandte Informationen