EDIT -nouvelle réponse-
La ou les réponses ci-dessous sont / sont toujours totalement valables, et donc les options suggérées. Cependant, un aperçu continu m'a fait 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).
Choisissez simplement l'application dans la liste et toutes les fenêtres de l'application correspondante (présentes dans la fenêtre courante) afficheront:
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 wmctrl
sudo apt-get wmctrl
Copiez l'indicateur dans un fichier vide, enregistrez-le sous raise_apps.py
Copiez l'image ci-dessous, enregistrez-la exactement raise.png
dans un seul et même répertoire que l'indicateur.
Ensuite, exécutez-le simplement par la commande:
python3 /path/to/raise_apps.py
Ajoutez si vous souhaitez démarrer des applications:
/bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py"
ANCIENNE RÉPONSE:
À propos de la question
Avec les bons outils, il n'est pas très compliqué de "simplement" soulever toutes les fenêtres d'une application. Il est un peu plus compliqué de s'assurer que seules les fenêtres de la fenêtre courante sont levées. Le vrai défi est cependant de trouver un moyen pratique de mettre l'action à la disposition de l'utilisateur.
Ci-dessous cinq options pour prendre soin de cela, pour montrer comment cela peut être fait. Toutes les options sont prêtes à être utilisées. Cependant, la dernière option est plutôt expérimentale; cela fonctionne bien mais a quelques inconvénients cosmétiques mineurs, comme expliqué dans la description de l'option. Je l'ai quand même ajouté comme concept .
Répartir les fenêtres automatiquement de manière non superposé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.
Comment utiliser
Pour toutes les options, vous devez:
installer wmctrl
s'il n'est 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 raise_app
(sans extension) ~/bin
et rendez-le exécutable
Dans les options séparées, les étapes supplémentaires possibles seront expliquées.
Option 1: choisissez l'application en saisissant un ou plusieurs caractères
- Appuyez sur une combinaison de touches, une
zenity
fenêtre apparaî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 (dans la fenêtre courante ).
ouvrir toutes les gnome-terminal
fenêtres de la fenêtre courante:
Comment utiliser:
- Effectuez la configuration comme décrit dans "Comment utiliser"
Testez-le par 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: parcourir les applications et augmenter 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:
J'appuie une fois Alt+ 1, toutes les nautilus
fenêtres sont levées:
J'appuie à nouveau sur Alt+ 1, toutes les firefox
fenêtres sont relevées:
J'appuie à nouveau sur Alt+ 1, toutes les gnome-terminal
fenêtres se relèvent, le cycle recommence:
Comment utiliser
Parcourez ensuite vos applications avec des fenêtres d'applications regroupé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- fenêtre d'application pour afficher toutes les fenêtres de la fenêtre courante
C'est probablement l'option qui se rapproche le plus de ce qui est décrit dans la question / le commentaire.
Disons que j'ai un bureau en désordre avec trois nautilus
fenêtres enfouies sous d'autres fenêtres.
Pour ouvrir toutes les fenêtres nautilus (exemple de raccourci: Alt+ 1):
- Appuyez sur Alt+ 1, relâchez (!)
Dans les 3 secondes, soit:
cliquez sur l'icône de l'application dans le lanceur
ou:
cliquez sur l'une des fenêtres de l'application
résultat:
Comment utiliser:
- Effectuez la configuration comme décrit dans "Comment utiliser"
Testez-le par 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
Alors:
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 courante
Celui-ci s'est avéré plus pratique que j'ai supposé:
En appuyant sur (encore une fois l'exemple-) combinaison de touches Alt+ 1appelle une zenity
fenêtre, répertoriant toutes les applications et le nombre de leurs fenêtres dans la fenêtre actuelle:
Une simple pression sur les flèches ▴ou ▾vous amènera à la bonne option. Appuyez sur Enteret toutes les fenêtres de l'application choisie sont ouvertes.
Comment utiliser:
- Effectuez la configuration comme décrit dans "Comment utiliser"
Testez-le par 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: augmenter les fenêtres des applications en cours d'exécution à partir d'une icône de lancement
Cette option existe 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 ouvertes.
Le lanceur est automatiquement mis à jour lorsque la liste des applications en cours d'exécution (dans la fenêtre actuelle) change. La liste rapide affiche une liste différente sur d'autres fenêtres, où les fenêtres d'autres applications sont ouvertes (cela prendra 1 à 2 secondes pour s'adapter).
Comme mentionné, bien que pleinement fonctionnelle, cette option est conçue comme un concept . Il a quelques inconvénients cosmétiques mineurs. 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 cosmétique.
- Il faut 1 à 2 secondes pour que la liste des applications de l'icône du lanceur soit mise à jour après la modification de la liste des applications en cours d'exécution.
De plus, 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 .desktop
fichier
- Préparez la configuration comme dans "Comment utiliser", enregistrez le premier script (principal) comme
raise_app
dans~/bin
Enregistrez l'icône ci-dessous (clic droit, enregistrer sous) sous raise.png
Copiez le .desktop
fichier 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 comme raise.desktop
dans~/.local/share/applications
Faites glisser le .desktop
fichier vers le lanceur pour l'ajouter
- copier le second script, collez - le dans un fichier vide, enregistrez comme
update_apps
dans ~/bin
, le rendre exécutable.
Ajoutez la commande suivante à vos applications de démarrage (Dash> Applications de démarrage> Ajouter):
update_apps
- Déconnectez-vous et reconnectez-vous pour le faire fonctionner.
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 wmctrl
pour créer une liste de fenêtres, à l'aide de la wmctrl -lpG
commande. 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 nous pouvons utiliser pour l'augmenter)
- 3ème colonne: le pid propriétaire de la fenêtre.
- 4ème / 5ème colonne: la géométrie de la fenêtre xy (que nous utilisons pour voir si la fenêtre est sur la fenêtre courante, icw
xrandr
)
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 allouer des fenêtres aux applications. Par la suite, nous pouvons soulever les fenêtres d'une application donnée en for
boucle avec la commande wmctrl -ia
.
Dans l'option 3,
le script démarre une boucle "en attente" de 3 secondes, en utilisant la xprop -root
commande à plusieurs reprises pour voir s'il y a un changement dans la fenêtre la plus en avant; cela se produira si l'utilisateur clique sur une icône de lanceur pour ouvrir la fenêtre d'une application ou clique directement sur une fenêtre. Si c'est le cas, la boucle while se rompt et recherche la "nouvelle" application la plus en avant, puis ouvre toutes les autres fenêtres de cette application.