web-dev-qa-db-fra.com

Comment afficher toutes les fenêtres d'une application?

J'ai une application utilisant plusieurs fenêtres. Comment puis-je rapidement afficher toutes les fenêtres de cette application au premier plan?

Lorsque je fais défiler les applications avec la molette de défilement, une fenêtre s’affiche. Lorsque vous passez à la fenêtre suivante, la dernière fenêtre est à nouveau mise en arrière-plan.

Lorsque je clique sur l'icône de l'application, je reçois un aperçu en plein écran de toutes les fenêtres. Je dois sélectionner chaque fenêtre manuellement et déplacer plusieurs fois ma souris sur la moitié de l'écran.

Ma meilleure solution jusqu’à présent est de minimiser toutes les fenêtres (Ctrl+Super+D), puis affichez les fenêtres de mon application à l'aide de la molette de défilement.

Y a-t-il une meilleure solution?

20
peq

EDIT -nouvelle réponse-

La réponse ci-dessous est/sont encore totalement valide (s), ainsi que les options suggérées. La perspicacité continue m'a cependant amené à ajouter cette option pour utiliser l'indicateur ci-dessous, qui est probablement la solution la plus élégante.

En tant que tel, il devrait probablement remplacer l'option 5 (en utilisant un fichier .desktop).

Il suffit de choisir l’application dans la liste, et toutes les fenêtres de l’application correspondante (présente dans la fenêtre courante) apparaîtront:

enter image description here

Comment utiliser

de ppa:

Sudo add-apt-repository ppa:vlijm/upfront
Sudo apt-get update
Sudo apt-get install upfront

... ou manuellement:

#!/usr/bin/env python3
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
import os
import subprocess
import getpass

currpath = os.path.dirname(os.path.realpath(__file__))

class Indicator():
    def __init__(self):
        self.app = 'raise_apps'
        iconpath = os.path.join(currpath, "raise.png")
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)       
        self.indicator.set_menu(self.create_menu())
        # the thread:
        self.update = Thread(target=self.check_recent)
        # daemonize the thread to make the indicator stopable
        self.update.setDaemon(True)
        self.update.start()

    def create_menu(self):
        # creates the (initial) menu
        self.menu = Gtk.Menu()
        # separator
        initial = Gtk.MenuItem("Fetching list...")
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(initial)
        self.menu.append(menu_sep)
        # item_quit.show() 
        self.menu.show_all()
        return self.menu

    def raise_wins(self, *args):
        index = self.menu.get_children().index(self.menu.get_active())
        selection = self.menu_items2[index][1]
        for w in selection:
            execute(["wmctrl", "-ia", w])

    def set_new(self):
        # update the list, appearing in the menu
        for i in self.menu.get_children():
            self.menu.remove(i)
        for app in self.menu_items2:

            sub = Gtk.MenuItem(app[0])
            self.menu.append(sub)
            sub.connect('activate', self.raise_wins)
        # separator
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep)
        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        self.menu.append(item_quit)
        self.menu.show_all()

    def get_apps(self):
        # calculate screen resolution
        res_output = get("xrandr").split(); idf = res_output.index("current")
        res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
        # creating window list on current viewport / id's / application names
        w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
        # windows on current viewport
        relevant = [w for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
        # pids
        pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
        matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
        return [m for m in matches if m[1]]

    def check_recent(self):
        self.menu_items1 = []
        while True:
            time.sleep(4)
            self.menu_items2 = self.get_apps()
            for app in self.menu_items2:
                app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
            if self.menu_items2 != self.menu_items1:
                GObject.idle_add(
                    self.set_new, 
                    priority=GObject.PRIORITY_DEFAULT
                    )
            self.menu_items1 = self.menu_items2

    def stop(self, source):
        Gtk.main_quit()

def get(command):
    return subprocess.check_output(command).decode("utf-8")

def execute(command):
    subprocess.Popen(command)

Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
  • L'indicateur a besoin de wmctrlname__

    Sudo apt-get wmctrl
    
  • Copiez l'indicateur dans un fichier vide, enregistrez-le sous raise_apps.py

  • Copiez l'image ci-dessous, enregistrez-la nommée exactement raise.png in un seul et même répertoire que l'indicateur.

    enter image description here

  • Ensuite, lancez-le simplement avec la commande:

    python3 /path/to/raise_apps.py

  • Ajoutez si vous voulez lancer des applications:

    /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 
    

ANCIENNE REPONSE:

À propos de la question

Avec les bons outils, il n’est pas très compliqué de "simplement" lever toutes les fenêtres d’une application. Il est un peu plus compliqué de s’assurer que seulement les fenêtres de la fenêtre courante sont levées. Le véritable défi consiste toutefois à trouver un moyen pratique de rendre l'action accessible à l'utilisateur.

Ci-dessous cinq options pour s’occuper de cela, montrer comment peut être fait. Toutes les options sont prêtes à être utilisées. La dernière option est cependant un peu expérimentale. cela fonctionne bien, mais présente quelques inconvénients cosmétiques mineurs, comme expliqué dans la description de l'option. Je l'ai néanmoins ajouté sous la forme d'un concept .

Étaler les fenêtres automatiquement de manière non imbriquée, comme suggéré dans un commentaire, ne me semble pas une idée pratique; Si vous travaillez dans une configuration de fenêtre groupée (au niveau de l'application), le script pourrait éventuellement réorganiser les fenêtres de manière non souhaitée.

Comment utiliser

Pour toutes les options, vous devez:

  • installez wmctrls'il ne se trouve pas encore sur votre système:

    Sudo apt-get install wmctrl
    
  • créer, s'il n'existe pas encore, le répertoire:

    ~/bin
    

    (explication: le répertoire ~/bin est dans $ PATH, vous pouvez donc exécuter les exécutables par leur nom)

  • Copiez le script correspondant à l'option, collez-le dans un fichier vide, enregistrez-le sous le code raise_app (sans extension) dans ~/bin et exécutez-le.

Dans les différentes options, les étapes supplémentaires possibles seront expliquées.

Option 1: choisissez l'application en entrant un ou plusieurs caractères

  • Appuyez sur une combinaison de touches, une fenêtre zenityapparaîtra
  • Entrez un ou plusieurs caractères du nom de l'application dans la zone de saisie.
  • Appuyez sur Entrée

Cela fera apparaître toutes les fenêtres de l'application correspondante (sur la fenêtre actuelle ).

lève toutes les fenêtres gnome-terminal dans la fenêtre courante:

enter image description here

enter image description here

Comment utiliser:

  • Effectuez la configuration comme décrit dans "Comment utiliser"
  • Testez-le avec la commande:

    raise_app
    
  • Si tout fonctionne correctement, ajoutez-le à une combinaison de touches de raccourci de votre choix: Choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande

Le script:

#!/usr/bin/env python3
import subprocess
import getpass

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
           for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# ask user for first characters
try:
    arg = get('zenity --entry --text "first characters" --title "application"').strip()
except subprocess.CalledProcessError:
    pass
# raise matching windows
try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
except (subprocess.CalledProcessError, NameError):
    pass



Option 2: parcourez les applications et augmentez leurs fenêtres avec une combinaison de touches:

Disons que j'ai le script ci-dessous sous une combinaison de touches Alt+1. J'ai plusieurs fenêtres ouvertes de:

  • firefox
  • gnome-terminal
  • nautile

L'état actuel:

enter image description here

J'appuie une fois Alt+1, toutes les fenêtres nautilussont levées:

<image>

Je presse à nouveau Alt+1, toutes les fenêtres firefoxsont levées:

<image>

Je presse à nouveau Alt+1, toutes les fenêtres gnome-terminal sont relevées, le cycle recommence:

<image>

Comment utiliser

  • Effectuez la configuration comme décrit dans "Comment utiliser"
  • Ajoutez-le à une combinaison de touches de raccourci de votre choix: Choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande

    raise_app
    

Parcourez ensuite vos applications avec des fenêtres d’applications groupées avec votre combinaison de touches.

Le script:

#!/usr/bin/env python3
import subprocess
import getpass

include_single = True # set to False if you only want to cycle through apps with multiple windows

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if\
                 "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
           for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# create application list to cycle through
if include_single == False:
    pre = [it[0] for it in windows]
    apps = sorted(list(set([it for it in pre if pre.count(it) > 1])))
else:
    apps = sorted(list(set([it[0] for it in windows])))
if len(apps) == 0:
    pass
else:
    # get the frontmost window as a last itm in the cycle
    front = get_frontmost()
    front_pid = [l.split()[2] for l in get("wmctrl -lp").splitlines() if front in l][0]
    last_infront = get("ps -u "+getpass.getuser()+" | grep "+front_pid).split()[-1]
    # determine next apllication to raise
    if not last_infront in apps or last_infront == apps[-1]:
        arg = apps[0]
        print(arg)
    else:
        arg = apps[apps.index(last_infront)+1]
    # raise matching windows
    try:
        [execute("wmctrl -ia "+item[1]) for item in windows if item[0] == arg]
    except (subprocess.CalledProcessError, NameError):
        pass



Option 3: appuyez sur la combinaison de touches + cliquez sur l'icône du lanceur - ou - pour ouvrir toutes les fenêtres de la fenêtre d'affichage actuelle

C'est probablement l'option qui se rapproche le plus de ce qui est décrit dans la question/commentaire.

Disons que j'ai un bureau en désordre avec trois fenêtres nautilusenfouies sous d'autres fenêtres.

<image>

Pour lever toutes les fenêtres du nautile (exemple: raccourci: Alt+1):

  • Presse Alt+1, Libération (!)
  • Dans les 3 secondes, soit:

    cliquez sur l'icône de l'application dans le lanceur

    <image>

    ou:

    cliquez sur l'une des fenêtres de l'application

    <image>

    résultat:

    <image>


Comment utiliser:

  • Effectuez la configuration comme décrit dans "Comment utiliser"
  • Testez-le avec la commande:

    raise_app
    
  • Si tout fonctionne correctement, ajoutez-le à une combinaison de touches de raccourci de votre choix: Choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande

Ensuite:

  • Appuyez sur votre combinaison de touches et dans les 3 secondes, soit:

    • cliquez sur l'icône de l'application dans le lanceur
    • cliquez sur l'une des fenêtres de l'application

Le script

#!/usr/bin/env python3
import subprocess
import getpass
import time

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])

def get_frontmost():
    cmd = "xprop -root"
    frontmost = [l for l in get(cmd).splitlines() if\
                 "ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
    return frontmost[:2]+"0"+frontmost[2:]

# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# get window data for various purposes
w_data = get("wmctrl -lpG").splitlines()
non_windows = sum([[l.split()[0] for l in w_data if it in l]\
               for it in ("unity-launcher", "unity-panel", "unity-dash", "Hud")], [])
# get id of current window
curr_window = get_frontmost()
# user gets 3 seconds to pick an application window (or launcher icon)
t = 0
while t < 4:
    w_id1 = get_frontmost()
    time.sleep(1)
    w_id2 = get_frontmost()
    if w_id1 == w_id2 or w_id2 in non_windows+[curr_window]:
        t = t+1
    else:
        new_frontmost = w_id2
        break
# raise
try:
    pid = [l.split()[2] for l in w_data if new_frontmost in l]
    wl_data = [l.split() for l in w_data]
    raise_windows = [l[0] for l in wl_data if pid[0] == l[2] and\
                     0 < int(l[3]) < res[0] and 0 < int(l[4]) < res[1]]
    [execute("wmctrl -ia "+item) for item in raise_windows]
except NameError:
    pass


Option 4: une combinaison de touches appelle une liste d'options indiquant le nombre de fenêtres par application dans la fenêtre d'affichage actuelle.

Celui-ci s'est avéré plus pratique que je suppose:

En appuyant sur la combinaison de touches (à nouveau par exemple) Alt+1 appelle une fenêtre zenityname__, répertoriant toutes les applications et le nombre de leurs fenêtres dans la fenêtre courante:

enter image description here

En appuyant simplement sur  ou  les flèches vous amèneront à la bonne option. presse Enter et toutes les fenêtres de l'application choisie sont levées.

Comment utiliser:

  • Effectuez la configuration comme décrit dans "Comment utiliser"
  • Testez-le avec la commande:

    raise_app
    
  • Si tout fonctionne correctement, ajoutez-le à une combinaison de touches de raccourci de votre choix: Choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande

Le script

#!/usr/bin/env python3
import subprocess
import getpass

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
           for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
# preparing zenity optionlist
apps = [item[0] for item in windows]
# prevent multiple zenity windows
if apps.count("zenity") > 1:
    pass
Elif apps.count("zenity") > 0:
    execute('zenity --info --text "Another Zenity window is open already"')
# preventing empty windowlist
Elif len(apps) > 0:
    applist = [[app, str(apps.count(app))] for app in set(apps)]
    applist.sort(key=lambda x: x[1])
    # calling zenity window
    try:
        arg = get('zenity  --list  --text "Choose an application" '+\
               '--title "Current windows" '+\
               '--column "application" '+\
               '--column "windows" '+\
               '--height 250 '+\
               '--width 250 '+\
               (" ").join(sum(applist, [])))
    except subprocess.CalledProcessError:
        pass
    # raise matching windows
    try:
        [execute("wmctrl -ia "+item[1]) \
         for item in windows if arg.startswith(item[0])]
    except (subprocess.CalledProcessError, NameError):
        pass
else:
    execute('zenity --info --text "No windows to list"')



Option 5: lever les fenêtres des applications en cours à partir d'une icône de lanceur

Cette option existe sous la forme d'une icône de lanceur, avec les applications en cours d'exécution dans une liste rapide. Choisissez-en une et toutes les fenêtres des applications seront levées.

enter image description here

Le lanceur est automatiquement mis à jour lorsque la liste des applications en cours d'exécution (dans la fenêtre d'affichage actuelle) change. La liste rapide affiche une liste différente sur les autres fenêtres, où les fenêtres d’autres applications sont ouvertes (l’adaptation prend 1 à 2 secondes).

Comme mentionné, bien qu’elle soit totalement fonctionnelle, cette option a la signification suivante: un concept . Il a quelques inconvénients cosmétiques mineurs tels qu'ils sont. Le plus important:

  • Le curseur "roue" continue de tourner pendant quelques secondes après une action. Bien que cela n’affecte pas la fonctionnalité, c’est un inconvénient esthétique.
  • Il faut 1 à 2 secondes pour que la liste des applications dans l'icône du programme de lancement soit mise à jour après la modification de la liste des applications en cours d'exécution.

En outre, la configuration est légèrement plus compliquée (bien qu’expliquée en détail ci-dessous):

Comment utiliser

Vous trouverez ci-dessous:

deux scripts/une icône/un fichier .desktop

  1. Préparez la configuration comme dans "Comment utiliser", sauvegardez le premier script sous le raise_app dans le ~/bin
  2. Enregistrez l'icône ci-dessous (clic droit, enregistrer sous) sous le nom raise.png

    <icon>

  3. Copiez le fichier .desktop dans un fichier vide, modifiez la ligne.

        Icon=/path/to/raise.png
    

    vers le chemin réel vers l'icône (chemins avec des espaces entre guillemets)
    Enregistrez-le sous raise.desktop dans ~/.local/share/applications

  4. Faites glisser le fichier .desktop vers le programme de lancement pour l'ajouter.

  5. copiez le deuxième script, collez-le dans un fichier vide, enregistrez-le sous le nom update_apps dans ~/bin, rendez-le exécutable.
  6. Ajoutez la commande suivante à vos applications de démarrage (Dash> Applications de démarrage> Ajouter):

    update_apps
    
  7. Déconnectez-vous et reconnectez-vous pour que cela fonctionne.

Le premier script

#!/usr/bin/env python3
import subprocess
import getpass
import sys

arg = sys.argv[1]

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
           for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
try:
    [execute("wmctrl -ia "+item[1]) for item in windows if item[0].startswith(arg)]
except (subprocess.CalledProcessError, NameError):
    pass

Le deuxième script

#!/usr/bin/env python3
import subprocess
import getpass
import time
import os

dtfile = os.environ["HOME"]+"/.local/share/applications/raise.desktop"

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def execute(command):
    subprocess.Popen(["/bin/bash", "-c", command])
# calculate screen resolution
res_output = get("xrandr").split(); idf = res_output.index("current")
res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
# creating window list on current viewport / id's / application names
def applist():
    try:
        w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
        windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
                   for w in w_data if 0 < int(w[3]) < res[0] and 0 < int(w[4]) < res[1]]
    except subprocess.CalledProcessError:
        return []
    else:
        return set([app[0] for app in windows])

def update_dtfile(applications, text):
    actionline = "Actions="+(";").join(applications)+";\n"
    with open(dtfile) as src:
        lines = src.readlines()
    lines = lines[:[i for i in range(len(lines)) \
                 if lines[i].startswith("Actions=")][0]]+[actionline]
    for item in text:
        for it in item:
            lines.append(it)
    with open(dtfile, "wt") as out:
        for line in lines:
            out.write(line)

while True:
    apps1 = applist()
    time.sleep(1)
    apps2 = applist()
    if apps1 != apps2: 
        text = [["[Desktop Action "+it+"]\n", "Name="+it+"\n",
            "Exec=raise_app "+it+"\n", "OnlyShowIn=Unity;\n\n",
            ]for it in apps2]
        update_dtfile(apps2, text)

Le fichier .desktop

[Desktop Entry]
Name=Raise application windows
Comment=Raise groups of windows
Icon=/path/to/raise.png
Terminal=false
Type=Application
Version=1.0

Actions=



Brève explication

Toutes les solutions ci-dessus utilisent wmctrlpour créer une liste de fenêtres à l'aide de la commande wmctrl -lpG. Cette commande produit des lignes, ressemblant à:

0x044000b3  0 3429   65   24   1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox

Ces lignes comprennent:

  • 1ère colonne: l'identifiant de la fenêtre (que l'on peut utiliser pour la lever)
  • 3ème colonne: le pid qui possède la fenêtre.
  • 4ème/5ème colonne: la géométrie de la fenêtre x-y (que nous utilisons pour voir si la fenêtre est sur la fenêtre courante, i.c.w xrandrname__)

Le pid est recherché dans la sortie de ps -u <username> pour obtenir une identification (nom) "lisible par l'utilisateur" de l'application.
Ainsi, nous pouvons attribuer des fenêtres aux applications. Ensuite, nous pouvons lever les fenêtres d’une application donnée dans une boucle forà l’aide de la commande wmctrl -ia.

dans l'option 3
le script commence une boucle "en attente" de 3 secondes, à l'aide de la commande xprop -root de manière répétée pour voir s'il y a un quelconque changement dans la fenêtre la plus à l'avant-plan; Cela se produira si l'utilisateur clique sur une icône de lanceur pour afficher la fenêtre d'une application ou clique directement sur une fenêtre. Si tel est le cas, la boucle While rompt et recherche la "nouvelle" application la plus en avant, puis lève toutes les autres fenêtres de cette application.

21
Jacob Vlijm

Il y a Super+W raccourci qui affiche l'expo de toutes les fenêtres actuellement ouvertes, mais qui inclura d'autres applications. Cela vient par défaut et ne nécessite aucune modification. C'est donc peut-être l'option la plus simple.

Entre autres choses, vous pouvez positionner les fenêtres sur les moitiés droite et gauche de l’écran avec Ctrl+Super+Left/Right boutons et basculez entre eux avec Alt + ~ (tilde, le numéro suivant la touche numéro un).

1

Si vous appuyez sur Alt + Tab pour parcourir les applications et que vous en avez une avec plusieurs fenêtres, maintenez simplement la touche Alt enfoncée et, après environ une seconde, l'icône sera remplacée par une vue de toutes les fenêtres de cette application.

Cela peut être ou ne pas être ce que vous cherchez, mais cela fonctionne pour moi et est beaucoup plus simple, alors je me suis dit que je partagerais l'option!

1
Sean Colombo

J'ai pris le script raise_apps.py de @ JacobVlijm et y ai apporté quelques améliorations, notamment en le rendant plus robuste.

En particulier, j’avais constaté qu’après un jour ou deux, le script de @ JacobVlijm cesserait de fonctionner et que je devais le redémarrer manuellement pour le faire fonctionner à nouveau. Rétrospectivement, ma meilleure hypothèse est que les nombreux appels à xrandr finissent par poser problème.

Quoi qu'il en soit, j'ai adapté son code, augmenté la fréquence d'interrogation de 5 secondes à toutes les secondes car il n'utilise pas beaucoup de temps processeur et l'a rendu plus robuste. Je peux généralement le faire fonctionner pendant des jours/semaines sans problèmes.

Un inconvénient est que je n’appelle xrandr qu’une fois au démarrage, pour obtenir les dimensions de la résolution de l’écran. Ainsi, si vous changez la résolution de votre écran (par exemple, de 1920x1080 à une autre résolution), vous voudrez probablement redémarrer manuellement raise-apps.py pour qu’il capte la nouvelle résolution. Personnellement, je ne change jamais la résolution de mon écran, ce n’est donc pas un problème pour moi. De plus, j'ai de bonnes raisons de croire que trop d'appels sur xrandr ont été à l'origine de l'arrêt de la version du script de @ JacobVlijm après un jour ou deux, je vous recommande donc vivement de ne pas simplement réintégrer les nombreux appels à xrandr ..

En passant, vous devez placer l’image raise.png dans le répertoire/usr/local/icons /. Ou, si vous souhaitez placer le fichier raise.png dans un autre répertoire, apportez les modifications appropriées au script afin que celui-ci puisse rechercher le fichier image.

Espérons que Ubuntu intégrera ce type de fonctionnalité 'lever toutes les fenêtres' dans leur système le plus tôt possible, car il est très utile:

#!/usr/bin/python2
#
# Note to self:
# You need to add raise.png to /usr/local/icons/ directory.
#
# This script was taken from: https://askubuntu.com/questions/446521/how-to-show-raise-all-windows-of-an-application, 
# (@JacobVlijm's answer), and then improved to fix some
# issues, that were causing it to stop working after a day or two.
#
#
from __future__ import print_function

from sys import stderr, exit
import signal
import gi

gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject, GLib

import logging
import logging.handlers

import time
import os
import subprocess
import getpass

logger = logging.getLogger('MyLogger')
logger.setLevel(logging.DEBUG)

log_handler = logging.handlers.SysLogHandler(address='/dev/log')

logger.addHandler(log_handler)


currpath = os.path.dirname(os.path.realpath(__file__))

class Indicator():
    def __init__(self):
        self.app = 'raise-apps'
        iconpath = '/usr/local/icons/raise.png'
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

        self.prev_menu_item_names = []
        self.menu_items = []

        res_output = get("xrandr").split()
        if (len(res_output) == 0):
            logger.error("raise-apps.py: invocation of xrandr failed! Unable to continue..")
            exit(-1)

        idf = res_output.index("current")
        res = (int(res_output[idf+1]), int(res_output[idf+3].replace(",", "")))
        (self.screen_width, self.screen_height) = res
        logger.info("raise-apps.py: screen resolution is %s x %s" % (self.screen_width, self.screen_height))

        self.indicator.set_menu(self.create_menu())

        GLib.timeout_add_seconds(1.0, self.check_recent)

    def create_menu(self):
        # creates the (initial) menu
        self.menu = Gtk.Menu()
        # separator
        initial = Gtk.MenuItem("Fetching list...")
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(initial)
        self.menu.append(menu_sep)

        self.menu.show_all()
        return self.menu

    def raise_wins(self, *args):
        index = self.menu.get_children().index(self.menu.get_active())
        selection = self.menu_items[index][1]
        for w in selection:
            execute(["wmctrl", "-ia", w])

    def set_new(self):
        # update the list, appearing in the menu
        for i in self.menu.get_children():
            self.menu.remove(i)
        for app in self.menu_items:

            sub = Gtk.MenuItem(app[0])
            self.menu.append(sub)
            sub.connect('activate', self.raise_wins)
        # separator
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep)

        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        self.menu.append(item_quit)
        self.menu.show_all()

    def get_apps(self):
        # creating window list on current viewport / id's / application names
        w_data = [l.split() for l in get(["wmctrl", "-lpG"]).splitlines()]
        # windows on current viewport
        relevant = [w for w in w_data if 0 < int(w[3]) < self.screen_width and 0 < int(w[4]) < self.screen_height]
        # pids
        pids = [l.split() for l in get(["ps", "-u", getpass.getuser()]).splitlines()]
        matches = [[p[-1], [w[0] for w in relevant if w[2] == p[0]]] for p in pids]
        return [m for m in matches if m[1]]

    def check_recent(self):
        # print("in check_recent()", file=stderr)
        self.menu_items = self.get_apps()
        for app in self.menu_items:
            app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]
        # check if menu items have changed:
        has_changed = len(self.menu_items) != len(self.prev_menu_item_names)
        if (not has_changed):
            for i in range(len(self.menu_items)):
                if self.prev_menu_item_names[i] != self.menu_items[i][0]:
                    has_changed = True
                    break

        if has_changed:
            GObject.idle_add(
                self.set_new,
                priority=GObject.PRIORITY_DEFAULT)

            self.prev_menu_item_names = []
            for item in self.menu_items:
                self.prev_menu_item_names.append(item[0])

        GLib.timeout_add_seconds(1.0, self.check_recent)


    def stop(self, source):
        Gtk.main_quit()


    def recreate_menu(self, *args):
        logger.info("in recreate_menu()")
        self.prev_menu_item_names = []
        self.menu_items = []

        self.menu_items = self.get_apps()
        for app in self.menu_items:
            app[0] = "gnome-terminal" if "gnome-terminal" in app[0] else app[0]

        GObject.idle_add(
            self.set_new,
            priority=GObject.PRIORITY_DEFAULT)

        self.prev_menu_item_names = []
        for item in self.menu_items:
            self.prev_menu_item_names.append(item[0])


def get(command):
    # enable to get a feel for what this app is doing..
    # print("get", command, file=stderr)
    try:
        return subprocess.check_output(command).decode("utf-8")

    except subprocess.CalledProcessError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""

    except OSError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""

def execute(command):
    # enable to get a feel for what this app is doing..
    # print("exec", command, file=stderr)
    try:
        subprocess.call(command)

    except subprocess.CalledProcessError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
        return ""
    except OSError as e:
        logger.error("raise-apps.py error: cmd=%s, error=%s" % (command, e))
    return ""


logger.info("(raise-apps.py is starting up..)")
Indicator()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
1
Gino