Come mostrare (aumentare) tutte le finestre di un'applicazione?


21

Ho un'applicazione che utilizza più finestre. Come posso portare rapidamente in primo piano tutte le finestre di quell'applicazione?

Quando scorro le applicazioni con la rotellina del mouse, mostra solo una finestra. Quando si passa alla finestra successiva, l'ultima finestra viene nuovamente visualizzata sullo sfondo.

Quando faccio clic sull'icona dell'applicazione, ottengo una panoramica a schermo intero di tutte le finestre. Devo selezionare manualmente ciascuna finestra e spostare il mouse su metà dello schermo più volte.

La mia migliore soluzione finora è minimizzare tutte le finestre ( Ctrl+ Super+ D) e quindi mostrare le finestre della mia applicazione usando la rotella di scorrimento.

C'è una soluzione migliore?


@Joschua Portare tutte le finestre di un'applicazione in primo piano non è troppo difficile, ma come vorresti definire l'applicazione? farebbe una combinazione di tasti + facendo clic sulla finestra di un'applicazione?
Jacob Vlijm,

@ Joschua o forse più elegante, una combinazione di tasti + 1 ° carattere del nome dell'applicazione?
Jacob Vlijm,

Penso che il comportamento sia lo stesso con tutte le applicazioni. Molto spesso mi manca questa funzione con le finestre dei terminali, dove spesso ho due o più finestre aperte affiancate. Quindi passo a una finestra a schermo intero (ad esempio Firefox) e quando voglio tornare alle due finestre del terminale è un po 'difficile. Il modo migliore che ho trovato finora è un clic del mouse sulla barra delle applicazioni di Firefox che porta Firefox in background in modo da avere di nuovo i due terminali nella parte anteriore. Tuttavia, questo funziona solo quando non ci sono troppe applicazioni sovrapposte: D
peq

anche @Joschua Sarebbe possibile avere una combinazione di tasti per portare in primo piano i gruppi di finestre delle applicazioni ; premere una volta -> tutte le finestre di Firefox vengono visualizzate, di nuovo pres -> tutte le finestre dei terminali visualizzate, ecc. potrebbero essere rese davvero fluide. interessante. lavorando su di esso. ci vorrà un po 'di lavoro però.
Jacob Vlijm,

@JacobVlijm Sembra la giusta direzione .. :) Quello che mi sembra più importante, è che una combinazione di tasti più un clic sull'icona porta in primo piano tutte le finestre di quell'applicazione (ad esempio, molti terminali come peq), preferibilmente distribuite fuori, in modo che non si sovrappongano .. (Forse qualcosa del genere potrebbe diventare parte di Unity ?!)
Joschua,

Risposte:


21

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:

inserisci qui la descrizione dell'immagine

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.

    inserisci qui la descrizione dell'immagine

  • 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 wmctrlse 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) ~/bine 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, zenityverrà 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-terminalfinestre nella finestra corrente:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

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:

inserisci qui la descrizione dell'immagine

Premo una volta Alt+ 1, tutte le nautilusfinestre vengono sollevate:

<Image>

Premo di nuovo Alt+ 1, tutte le firefoxfinestre sono sollevate:

<Image>

Premo di nuovo Alt+ 1, tutte le gnome-terminalfinestre vengono nuovamente sollevate, il ciclo ricomincia:

<Image>

Come usare

  • Eseguire l'installazione come descritto in "Come usare"
  • 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

    raise_app
    

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 nautilusfinestre sepolte sotto altre finestre.

<Image>

Per alzare tutte le finestre di nautilus (esempio scorciatoia: Alt+ 1):

  • Premi Alt+ 1, rilascia (!)
  • Entro 3 secondi:

    fai clic sull'icona dell'applicazione nel programma di avvio

    <Image>

    o:

    fai clic su una delle finestre dell'applicazione

    <Image>

    risultato:

    <Image>


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:

  • Premi la combinazione di tasti e entro 3 secondi:

    • fai clic sull'icona dell'applicazione nel programma di avvio
    • fai clic su una delle finestre dell'applicazione

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 zenityfinestra, elencando tutte le applicazioni e il numero delle loro finestre nella finestra corrente:

inserisci qui la descrizione dell'immagine

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.

inserisci qui la descrizione dell'immagine

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 .desktopfile

  1. Preparare l'installazione come in "Come usare", salvare il primo (main-) script come raise_appin~/bin
  2. Salvare l'icona in basso (tasto destro, salva con nome) come raise.png

    <Icona>

  3. Copia il .desktopfile 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.desktopin~/.local/share/applications

  4. Trascina il .desktopfile nel programma di avvio per aggiungerlo

  5. copia il secondo script, incollalo in un file vuoto, salvalo come update_appsin ~/bin, rendilo eseguibile.
  6. Aggiungi il seguente comando alle applicazioni di avvio (Dash> Applicazioni di avvio> Aggiungi):

    update_apps
    
  7. 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 wmctrlper creare un elenco di finestre, utilizzando il wmctrl -lpGcomando. 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 forciclo con il comandowmctrl -ia .

Nell'opzione 3
lo script avvia un ciclo di "attesa" di 3 secondi, usando xprop -rootripetutamente 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.


Sono d'accordo e grazie ancora per tutti i tuoi sforzi! :) || C'è una cosa strana che non avevo notato prima. A volte dopo aver usato lo Option 2script, quando una finestra dell'applicazione è focalizzata (che non è ingrandita) e faccio clic su un'altra finestra che è visibile "sotto", l'applicazione sotto non ottiene lo stato attivo.
Joschua,

@Joschua l'OP di questa domanda: askubuntu.com/questions/575830/… mi ha assistito a un bug che è stato introdotto all'ultimo aggiornamento delle "funzionalità". Vero / Falso sono stati confusi, causando l'arresto anomalo dello script quando nessuna applicazione ha più di una finestra. Se si utilizza option2, si prega di aggiornare all'ultima versione.
Jacob Vlijm,

Opzione 1 non funziona per me su Ubuntu Xenial. qualcosa @ qualcosa: ~ / bin $ ./raise_app Messaggio Gtk: GtkDialog mappato senza un genitore temporaneo. Questo è scoraggiato. Stavo cercando di aprire le finestre del terminale. Non è successo niente.
xtrinch,

@Nirri quale nome dell'applicazione hai usato? Il messaggio è abbastanza normale se una finestra zenity viene eseguita senza un genitore Gtk. "Scoraggiato" non è un errore.
Jacob Vlijm,

Primi caratteri del terminale. Funziona - in un certo senso - solleva una finestra di qualsiasi app - ma solo una di esse, non tutte come previsto @ user72216
xtrinch

1

C'è Super+ Wscorciatoia che mostrerà l'expo di tutte le finestre attualmente aperte, sebbene includerà altre applicazioni. Questo viene di default e non richiede alcuna modifica, quindi forse è un'opzione più semplice disponibile.

Tra le altre cose, puoi posizionare le finestre sulla metà destra e sinistra dello schermo con i pulsanti Ctrl+ Super+ Left/ Righte passare da una all'altra con Alt + ~ (tilde, quella accanto al tasto numero uno).


Ciò non porta in primo piano tutte le finestre di un'applicazione. Puoi vederli, ma non puoi usarli senza fare molto clic.
Joschua,

1

Se si preme Alt + Tab per scorrere le applicazioni e si arriva a una con più finestre, tenere semplicemente premuto il tasto Alt e dopo circa 1 secondo intero l'icona verrà sostituita con una vista di tutte le finestre per quell'applicazione.

Potrebbe essere questo o meno quello che stai cercando, ma funziona per me ed è molto più semplice, quindi ho pensato di condividere l'opzione!


1
Puoi anche premere il tasto freccia giù per visualizzare immediatamente le finestre dell'applicazione.
Kris

1

Ho preso lo script raise_apps.py di @ JacobVlijm e ho apportato alcuni miglioramenti, incluso renderlo più robusto.

In particolare, avevo scoperto che dopo un giorno o due, la sceneggiatura di @ JacobVlijm avrebbe smesso di funzionare e avrei dovuto riavviare manualmente la sceneggiatura per farla funzionare di nuovo. In retrospettiva, la mia ipotesi migliore è che le numerose chiamate a xrandr alla fine causino problemi.

Ad ogni modo, ho adattato il suo codice, aumentato la frequenza di polling da 5 secondi a ogni 1 secondo, in quanto non utilizza comunque molta CPU e lo ha reso più robusto. In genere posso farlo funzionare per giorni / settimane senza problemi.

Un avvertimento è che chiamo xrandr solo una volta durante l'avvio, per ottenere le dimensioni di risoluzione dello schermo. Quindi, se modifichi la risoluzione dello schermo (ad esempio da 1920x1080 ad un'altra risoluzione), probabilmente vorrai riavviare manualmente raise-apps.py in modo che raccolga la nuova risoluzione. Personalmente, non cambio mai la risoluzione dello schermo, quindi questo non è un problema per me. Inoltre, ho forti ragioni per credere che troppe chiamate a xrandr stessero causando l'interruzione della versione dello script di @ JacobVlijm dopo un giorno o due, quindi consiglierei vivamente di non semplicemente rimettere le numerose chiamate a xrandr ..

A proposito, è necessario posizionare l'immagine raise.png nella directory / usr / local / icons /. Oppure, se si desidera inserire raise.png in una directory diversa, apportare le modifiche appropriate allo script, in modo che lo script possa trovare il file immagine.

Si spera che Ubuntu integrerà questo tipo di funzionalità "alza tutte le finestre" nel loro sistema prima o poi poiché è molto utile:

#!/usr/bin/python2
#
# Note to self:
# You need to add raise.png to /usr/local/icons/ directory.
#
# This script was taken from: /ubuntu/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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.