web-dev-qa-db-fra.com

Comment puis-je faire en sorte que wmctrl ouvre la fenêtre la plus récemment utilisée d'une application?

J'ai un script en cours d'exécution wmctrl -x -a "$1". Il affiche la fenêtre, passée comme argument au script, par exemple:

wmctrl -x -a "Firefox" 

active firefox.

Cependant, avec des applications qui ont plusieurs fenêtres, cela ne fait pas apparaître les fenêtres last utilisées. Considérez que j'ai 3 fenêtres ouvertes dans LibreOffice Writer, nommé 'Doc 1', 'Doc 2' et 'Doc 3' et je suis sur Doc 3 et je passe à une autre application. L'exécution du script affiche "Doc 1" et non "Doc 3" qui a été utilisé en dernier.

Un indicateur pour résoudre ce problème dans wmctrl?

1
Salil Surendran

Sur demande, scission d'une autre réponse, complétée par une nouvelle section.

Focus historique des fenêtres

Comment afficher la dernière fenêtre focalisée d'une application

Comme mentionné dans mon commentaire, actuellement, il n'y a pas d'historique de focus de Windows. Cela signifie que si nous en avons besoin, nous devons le créer nous-mêmes. Le premier script ci-dessous fait exactement cela; Il garde une trace de la fenêtre actuellement focalisée et stocke l'historique dans un petit fichier, actualisé une fois par seconde. L'ordre des lignes est également l'ordre de mise au point; la ligne du haut représente la dernière fenêtre focalisée, la dernière ligne la "plus ancienne".

Pour qu'un script lève la dernière fenêtre focalisée d'une application, il suffit de lire les lignes de haut en bas, de trouver la première occurrence d'une fenêtre de l'application et de la lever. C'est exactement ce que fait le deuxième script, si vous l'exécutez avec le WM_CLASS de la fenêtre recherchée.

Les scripts

  1. Le script d'arrière-plan, gardant une trace de l'historique de la mise au point. Ce script est une copie exacte du premier ici :

    #!/usr/bin/env python3
    import subprocess
    import time
    import os
    
    rootdata = os.environ["HOME"]+"/.focus_history"
    open(rootdata, "wt").write("This is an empty line")
    
    def current_windows():
        try:
            return subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8")
        except subprocess.CalledProcessError:
            pass
    
    def convert_format(w_id):
        return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]
    
    def read_data():
        return open(rootdata).read().splitlines()
    
    def get_top(wlist):
        try:
            top = convert_format(
                [l.split("#")[-1].strip() for l in subprocess.check_output(
                    ["xprop", "-root"]
                    ).decode("utf-8").splitlines() \
                   if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0])
            return [l for l in wlist if top in l][0]
        except IndexError:
            pass
    
    if __name__ == "__main__":
        while True:
            time.sleep(1)
            wdata = current_windows()
            if wdata != None:
                wlist = wdata.splitlines()
                # get frontmost window (as in wmctrl -lG)
                top = get_top(wlist)
                oldlist = read_data()
                if not any([top == oldlist[0], top == None]):
                    # clean up closed windows
                    [oldlist.remove(l) for l in oldlist if not l.split()[0] in wdata]
                    # remove possible other mentions of the active window
                    [oldlist.remove(l) for l in oldlist if l.startswith(top.split()[0])]
                    open(rootdata, "wt").write(("\n").join([top]+oldlist))
    

    Copiez le script dans un fichier vide, enregistrez-le sous focus_history.py

  2. Le script pour ouvrir la dernière fenêtre focalisée d'une application.

    #!/usr/bin/env python3
    import os
    import subprocess
    import sys
    
    lookfor = sys.argv[1]
    winhistory = os.environ["HOME"]+"/.focus_history"
    
    for l in open(winhistory):
        wid = l.split()[0]
        wmclass = subprocess.check_output(
            ["xprop", "-id", wid, "WM_CLASS"]
            ).decode("utf-8").strip()
        if lookfor in wmclass:
            subprocess.check_output(["wmctrl", "-ia", wid])
            break
    

    Enregistrez-le sous raise_recent.py.

Comment utiliser

  1. assurez-vous que wmctrl est installé:

    Sudo apt install wmctrl
    
  2. Testez- exécutez le premier script en tant que document d'information avec la commande:

    python3 /path/to/focus_history.py
    

    NB assurez-vous que le script démarre avant autres fenêtres ouvertes, sinon les fenêtres sera enregistré (bien sûr) une fois qu'ils auront obtenu leur premier focus.

  3. Appelez le deuxième script avec la commande (par exemple)

    python3 /path/to/raise_recent.py gedit
    

    ... pour afficher la dernière fenêtre focalisée de gedit.

  4. Si tout fonctionne correctement, ajoutez le premier script aux applications de démarrage. Notez cependant que vous devez probablement ajouter une pause avant le démarrage du script, pour éviter que wmctrl ne se brise. (Bien que le script ne devrait pas, car il gère l'exception possible).

C'est ça.

2
Jacob Vlijm