MODIFICA -nuova risposta-
Le risposte che seguono sono / sono ancora totalmente valide, quindi le opzioni suggerite. L'analisi continua mi ha fatto aggiungere questa opzione per utilizzare l'indicatore di seguito, che è probabilmente la soluzione più elegante.
Pertanto, dovrebbe probabilmente sostituire l'opzione 5 (utilizzando un file .desktop).
Basta scegliere l'applicazione dall'elenco e tutte le finestre dell'applicazione corrispondente (presente nella finestra corrente) genereranno:
Come usare
da ppa:
sudo add-apt-repository ppa:vlijm/upfront
sudo apt-get update
sudo apt-get install upfront
... o manualmente:
#!/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'indicatore ha bisogno wmctrl
sudo apt-get wmctrl
Copia l'indicatore in un file vuoto, salvalo come raise_apps.py
Copia l'immagine qui sotto, salvala esattamente con il nome raise.png
in una stessa directory dell'indicatore.
Quindi eseguilo semplicemente con il comando:
python3 /path/to/raise_apps.py
Aggiungi se vuoi Applicazioni di avvio:
/bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py"
VECCHIA RISPOSTA:
Sulla domanda
Con gli strumenti giusti, non è molto complicato "solo" alzare tutte le finestre di un'applicazione. È un po 'più complicato accertarsene solo le finestre della finestra corrente siano sollevate. La vera sfida, tuttavia, è trovare un modo conveniente per rendere l'azione disponibile all'utente.
Di seguito cinque opzioni per occuparsene, per mostrare come si può fare. Tutte le opzioni sono pronte per essere utilizzate. L'ultima opzione è comunque un po 'sperimentale; funziona benissimo ma presenta alcuni piccoli svantaggi estetici, come spiegato nella descrizione dell'opzione. L'ho aggiunto comunque come concetto .
Diffondere automaticamente le finestre in modo non sovrapposto, come suggerito in un commento, non mi sembra un'idea pratica; se lavori in una configurazione di finestre raggruppate (per quanto riguarda le applicazioni), lo script potrebbe riorganizzare involontariamente le finestre.
Come usare
Per tutte le opzioni è necessario:
installa wmctrl
se non è ancora sul tuo sistema:
sudo apt-get install wmctrl
creare, se non esiste ancora, la directory:
~/bin
(spiegazione: la directory ~/bin
è in $ PATH, quindi puoi eseguire eseguibili con il loro nome)
Copia lo script, corrispondente all'opzione, incollalo in un file vuoto, salvalo come raise_app
(senza estensione) ~/bin
e rendilo eseguibile
Nelle opzioni separate, verranno spiegati eventuali passaggi aggiuntivi.
Opzione 1: scegli l'applicazione inserendo uno o più caratteri
- Premere una combinazione di tasti,
zenity
verrà visualizzata una finestra
- Immettere uno o più caratteri del nome dell'applicazione nella casella di inserimento
- Premere Invio
Ciò farà apparire tutte le finestre dell'applicazione corrispondente (nella finestra corrente ).
solleva tutte le gnome-terminal
finestre nella finestra corrente:
Come usare:
- Eseguire l'installazione come descritto in "Come usare"
Test-eseguirlo con il comando:
raise_app
Se tutto funziona correttamente, aggiungilo a una combinazione di tasti di scelta rapida a tua scelta: Scegli: Impostazioni di sistema> "Tastiera"> "Scorciatoie"> "Scorciatoie personalizzate". Fai clic su "+" e aggiungi il comando
Il copione:
#!/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
Opzione 2: scorrere le applicazioni e aumentare le finestre con una combinazione di tasti:
Diciamo che ho lo script qui sotto sotto una combinazione di tasti Alt+ 1. Ho diverse finestre aperte su:
- firefox
- gnome-terminal
- nautilo
Lo stato attuale:
Premo una volta Alt+ 1, tutte le nautilus
finestre vengono sollevate:
Premo di nuovo Alt+ 1, tutte le firefox
finestre sono sollevate:
Premo di nuovo Alt+ 1, tutte le gnome-terminal
finestre vengono nuovamente sollevate, il ciclo ricomincia:
Come usare
Quindi scorrere le applicazioni con finestre di applicazioni raggruppate con la combinazione di tasti.
Il copione:
#!/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
Opzione 3: premere la combinazione di tasti + fare clic sull'icona di avvio -oppure- finestra dell'applicazione per aumentare tutte le finestre nella finestra corrente
Questa è probabilmente l'opzione più vicina a quanto descritto nella domanda / commento.
Diciamo che ho un desktop disordinato con tre nautilus
finestre sepolte sotto altre finestre.
Per alzare tutte le finestre di nautilus (esempio scorciatoia: Alt+ 1):
Come usare:
- Eseguire l'installazione come descritto in "Come usare"
Test-eseguirlo con il comando:
raise_app
Se tutto funziona correttamente, aggiungilo a una combinazione di tasti di scelta rapida a tua scelta: Scegli: Impostazioni di sistema> "Tastiera"> "Scorciatoie"> "Scorciatoie personalizzate". Fai clic su "+" e aggiungi il comando
Poi:
Il copione
#!/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
Opzione 4: una combinazione di tasti chiama un elenco di opzioni, mostrando il numero di finestre per applicazione nella finestra corrente
Questo si è rivelato più conveniente di quanto pensassi:
Premendo la combinazione di tasti (ancora un esempio-) Alt+ si 1richiama una zenity
finestra, elencando tutte le applicazioni e il numero delle loro finestre nella finestra corrente:
Basta premere le frecce ▴o per ▾accedere all'opzione giusta. Premere Entere tutte le finestre dell'applicazione selezionata vengono sollevate.
Come usare:
- Eseguire l'installazione come descritto in "Come usare"
Test-eseguirlo con il comando:
raise_app
Se tutto funziona correttamente, aggiungilo a una combinazione di tasti di scelta rapida a tua scelta: Scegli: Impostazioni di sistema> "Tastiera"> "Scorciatoie"> "Scorciatoie personalizzate". Fai clic su "+" e aggiungi il comando
Il copione
#!/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"')
Opzione 5: alzare le finestre delle applicazioni in esecuzione da un'icona di avvio
Questa opzione esiste di un'icona di avvio, con le applicazioni attualmente in esecuzione in un elenco rapido. Scegli uno e tutte le finestre delle applicazioni verranno sollevate.
Il programma di avvio viene automaticamente aggiornato quando cambia l'elenco delle applicazioni in esecuzione (nella finestra corrente). L'elenco rapido mostra un elenco diverso su altri viewport, in cui vengono aperte le finestre di altre applicazioni (occorreranno 1-2 secondi per adattarsi).
Come accennato, sebbene pienamente funzionale, questa opzione è intesa come concetto . Ha alcuni piccoli svantaggi cosmetici come è. Il più importante:
- Il cursore "rotellina" continua a girare per alcuni secondi dopo un'azione. Sebbene non influisca sulla funzionalità, è un aspetto negativo estetico.
- Sono necessari 1-2 secondi per l'aggiornamento dell'elenco delle applicazioni nell'icona di avvio dopo che l'elenco delle applicazioni in esecuzione cambia.
Inoltre, l'installazione è leggermente più complicata (sebbene spiegata in dettaglio di seguito):
Come usare
Di seguito troverai:
due script / un'icona / un .desktop
file
- Preparare l'installazione come in "Come usare", salvare il primo (main-) script come
raise_app
in~/bin
Salvare l'icona in basso (tasto destro, salva con nome) come raise.png
Copia il .desktop
file in un file vuoto, modifica la riga
Icon=/path/to/raise.png
al percorso reale dell'icona (percorsi con spazi tra virgolette)
Salvalo come raise.desktop
in~/.local/share/applications
Trascina il .desktop
file nel programma di avvio per aggiungerlo
- copia il secondo script, incollalo in un file vuoto, salvalo come
update_apps
in ~/bin
, rendilo eseguibile.
Aggiungi il seguente comando alle applicazioni di avvio (Dash> Applicazioni di avvio> Aggiungi):
update_apps
- Esci e rientra per farlo funzionare.
La prima sceneggiatura
#!/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
La seconda sceneggiatura
#!/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)
Il file .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=
Breve spiegazione
Tutte le soluzioni precedenti utilizzano wmctrl
per creare un elenco di finestre, utilizzando il wmctrl -lpG
comando. Questo comando produce linee, simile a:
0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox
Queste linee includono:
- 1a colonna: l'id della finestra (che possiamo usare per sollevarlo)
- 3a colonna: il pid proprietario della finestra.
- 4a / 5a colonna: la geometria della finestra xy (che usiamo per vedere se la finestra è nella finestra corrente, icw
xrandr
)
Il pid viene cercato nell'output di ps -u <username>
per ottenere un'identificazione (nome) "leggibile dall'utente" dell'applicazione.
Quindi possiamo allocare Windows alle applicazioni. Successivamente possiamo alzare le finestre di una data applicazione in un for
ciclo con il comandowmctrl -ia
.
Nell'opzione 3
lo script avvia un ciclo di "attesa" di 3 secondi, usando xprop -root
ripetutamente il comando per vedere se c'è qualche cambiamento nella finestra in primo piano; questo accadrà se l'utente fa clic sull'icona di un programma di avvio per aprire la finestra di un'applicazione o fa clic direttamente su una finestra. In tal caso, il ciclo while si interrompe e cerca la "nuova" applicazione in primo piano e successivamente solleva tutte le altre finestre di tale applicazione.