BEARBEITEN -neue Antwort-
Die Antwort (en) unten sind immer noch gültig, und daher die vorgeschlagenen Optionen. Aufgrund der fortwährenden Erkenntnisse habe ich diese Option hinzugefügt, um den folgenden Indikator zu verwenden, der wahrscheinlich die eleganteste Lösung ist.
Als solches sollte es wahrscheinlich Option 5 ersetzen (unter Verwendung einer .desktop-Datei).
Wählen Sie einfach die Anwendung aus der Liste aus, und alle Fenster der entsprechenden Anwendung (im aktuellen Ansichtsfenster vorhanden) werden geöffnet:
Wie benutzt man
von ppa:
sudo add-apt-repository ppa:vlijm/upfront
sudo apt-get update
sudo apt-get install upfront
... oder manuell:
#!/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()
Der Indikator benötigt wmctrl
sudo apt-get wmctrl
Kopieren Sie den Indikator in eine leere Datei und speichern Sie ihn als raise_apps.py
Kopieren Sie das Bild unten und speichern Sie es genau mit dem Namen raise.png
in ein und demselben Verzeichnis wie der Indikator.
Dann führen Sie es einfach mit dem Befehl:
python3 /path/to/raise_apps.py
Hinzufügen, wenn Sie Anwendungen starten möchten:
/bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py"
ALTE ANTWORT:
Über die Frage
Mit den richtigen Tools ist es nicht sehr kompliziert, "nur" alle Fenster einer Anwendung zu öffnen. Es ist etwas komplizierter sicherzustellen, dass nur die Fenster des aktuellen Ansichtsfensters geöffnet sind. Die eigentliche Herausforderung besteht jedoch darin, einen bequemen Weg zu finden, um die Aktion dem Benutzer zur Verfügung zu stellen.
Nachfolgend fünf Optionen, um das zu erledigen und zu zeigen, wie es gemacht werden kann. Alle Optionen können jetzt verwendet werden. Die letzte Option ist jedoch eher experimentell. es funktioniert gut, hat aber ein paar kleinere kosmetische Nachteile, wie in der Beschreibung der Option erläutert. Ich habe es trotzdem als Konzept hinzugefügt .
Das automatische Verbreiten der Fenster in nicht überlappender Weise, wie in einem Kommentar vorgeschlagen, scheint mir keine praktische Idee zu sein. Wenn Sie in einer (anwendungsspezifisch) gruppierten Fensterkonfiguration arbeiten, ordnet das Skript möglicherweise Fenster ungewollt neu an.
Wie benutzt man
Für alle Optionen müssen Sie:
installieren, wmctrl
wenn es noch nicht auf Ihrem System ist:
sudo apt-get install wmctrl
erstelle, falls noch nicht vorhanden, das Verzeichnis:
~/bin
(Erklärung: Das Verzeichnis ~/bin
befindet sich in $ PATH, so dass Sie ausführbare Dateien nach ihrem Namen ausführen können.)
Kopieren Sie das Skript entsprechend der Option, fügen Sie es in eine leere Datei ein, speichern Sie es unter raise_app
(keine Erweiterung) ~/bin
und machen Sie es ausführbar
In den separaten Optionen werden mögliche zusätzliche Schritte erläutert.
Option 1: Wählen Sie die Anwendung aus, indem Sie ein oder mehrere Zeichen eingeben
- Durch Drücken einer Tastenkombination wird ein
zenity
Fenster angezeigt
- Geben Sie ein oder mehrere Zeichen des Anwendungsnamens in das Eingabefeld ein
- Drücken Sie Enter
Dadurch werden alle Fenster der entsprechenden Anwendung (im aktuellen Ansichtsfenster) in den Vordergrund gerückt.
Heben Sie alle gnome-terminal
Fenster im aktuellen Ansichtsfenster an:
Wie benutzt man:
- Führen Sie die Einrichtung wie unter "Verwendung" beschrieben durch.
Führen Sie es mit dem folgenden Befehl aus:
raise_app
Wenn alles funktioniert, fügen Sie es einer Tastenkombination Ihrer Wahl hinzu: Wählen Sie: Systemeinstellungen> "Tastatur"> "Tastenkombinationen"> "Benutzerdefinierte Tastenkombinationen". Klicken Sie auf das "+" und fügen Sie den Befehl hinzu
Das Drehbuch:
#!/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: Anwendungen durchlaufen und Fenster mit einer Tastenkombination öffnen:
Angenommen, ich habe das folgende Skript unter einer Tastenkombination Alt+ 1. Ich habe mehrere Fenster geöffnet von:
- Feuerfuchs
- gnome-terminal
- Nautilus
Der momentane Zustand:
Ich drücke einmal Alt+ 1, alle nautilus
Fenster werden geöffnet:
Ich drücke erneut Alt+ 1, alle firefox
Fenster werden geöffnet:
Ich drücke erneut Alt+ 1, alle gnome-terminal
Fenster werden wieder geöffnet, der Zyklus beginnt von vorne:
Wie benutzt man
Wechseln Sie dann mit Ihrer Tastenkombination durch Ihre Anwendungen mit gruppierten Anwendungsfenstern.
Das Drehbuch:
#!/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: Drücken Sie die Tastenkombination und klicken Sie auf das Startsymbol -oder- das Anwendungsfenster, um alle Fenster im aktuellen Ansichtsfenster zu öffnen
Dies ist wahrscheinlich die Option, die der Beschreibung in Frage / Kommentar am nächsten kommt.
Angenommen, ich habe einen unordentlichen Desktop mit drei nautilus
Fenstern, die unter anderen Fenstern verborgen sind.
So heben Sie alle Nautilus-Fenster an (Beispielverknüpfung: Alt+ 1):
- Drücken Sie Alt+ 1, lassen Sie (!) Los
Innerhalb von 3 Sekunden entweder:
Klicken Sie im Launcher auf das Anwendungssymbol
oder:
Klicken Sie auf eines der Fenster der Anwendung
Ergebnis:
Wie benutzt man:
- Führen Sie die Einrichtung wie unter "Verwendung" beschrieben durch.
Führen Sie es mit dem folgenden Befehl aus:
raise_app
Wenn alles funktioniert, fügen Sie es einer Tastenkombination Ihrer Wahl hinzu: Wählen Sie: Systemeinstellungen> "Tastatur"> "Tastenkombinationen"> "Benutzerdefinierte Tastenkombinationen". Klicken Sie auf das "+" und fügen Sie den Befehl hinzu
Dann:
Das Drehbuch
#!/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: Eine Tastenkombination ruft eine Optionsliste auf, in der die Anzahl der Fenster pro Anwendung im aktuellen Ansichtsfenster angezeigt wird
Dieser erwies sich als praktischer, als ich angenommen hatte:
Durch Drücken der (erneuten Beispiel-) Tastenkombination Alt+ wird 1ein zenity
Fenster aufgerufen , in dem alle Anwendungen und die Anzahl ihrer Fenster im aktuellen Ansichtsfenster aufgelistet sind:
Durch einfaches Drücken der Pfeiltasten ▴oder gelangen ▾Sie zur richtigen Option. Drücken Sie Enterund alle Fenster der gewählten Anwendung werden geöffnet.
Wie benutzt man:
- Führen Sie die Einrichtung wie unter "Verwendung" beschrieben durch.
Führen Sie es mit dem folgenden Befehl aus:
raise_app
Wenn alles funktioniert, fügen Sie es einer Tastenkombination Ihrer Wahl hinzu: Wählen Sie: Systemeinstellungen> "Tastatur"> "Tastenkombinationen"> "Benutzerdefinierte Tastenkombinationen". Klicken Sie auf das "+" und fügen Sie den Befehl hinzu
Das Drehbuch
#!/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: Öffnen Sie die Fenster ausgeführter Anwendungen über ein Startsymbol
Diese Option besteht aus einem Startsymbol, in dem sich die derzeit ausgeführten Anwendungen in einer Schnellliste befinden. Wenn Sie eines auswählen, werden alle Fenster der Anwendungen geöffnet.
Der Starter wird automatisch aktualisiert, wenn sich die Liste der ausgeführten Anwendungen (im aktuellen Ansichtsfenster) ändert. Die Schnellliste zeigt eine andere Liste in anderen Ansichtsfenstern an, in denen Fenster anderer Anwendungen geöffnet sind (die Anpassung dauert 1-2 Sekunden).
Wie bereits erwähnt, ist diese Option, obwohl sie voll funktionsfähig ist, als Konzept gedacht . Es hat ein paar kleinere kosmetische Nachteile, wie es ist. Das wichtigste:
- Nach einer Aktion dreht sich das Cursor- "Rad" einige Sekunden lang. Obwohl es die Funktionalität nicht beeinträchtigt, ist es ein kosmetischer Nachteil.
- Es dauert 1-2 Sekunden, bis die Anwendungsliste im Launcher-Symbol aktualisiert ist, nachdem sich die Liste der ausgeführten Anwendungen geändert hat.
Darüber hinaus ist das Setup etwas komplizierter (obwohl im Folgenden ausführlich erläutert):
Wie benutzt man
Nachfolgend finden Sie:
zwei Skripte / ein Icon / eine .desktop
Datei
- Bereiten Sie das Setup wie in "How to use" vor, speichern Sie das erste (Haupt-) Skript wie
raise_app
in~/bin
Speichern Sie das unten stehende Symbol (Rechtsklick, Speichern unter) unter raise.png
Kopieren Sie die .desktop
Datei in eine leere Datei und bearbeiten Sie die Zeile
Icon=/path/to/raise.png
den realen Pfad zum Symbol (Pfade mit Leerzeichen zwischen Anführungszeichen)
speichern Sie es als raise.desktop
in~/.local/share/applications
Ziehen Sie die .desktop
Datei in den Launcher, um sie hinzuzufügen
- Kopieren Sie das zweite Skript, fügen Sie ihn in eine leere Datei, speichern Sie es als
update_apps
in ~/bin
, machen es ausführbar.
Fügen Sie Ihren Startanwendungen den folgenden Befehl hinzu (Dash> Startanwendungen> Hinzufügen):
update_apps
- Melden Sie sich ab und wieder an, damit es funktioniert.
Das erste Drehbuch
#!/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
Das zweite Drehbuch
#!/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)
Die .desktop-Datei
[Desktop Entry]
Name=Raise application windows
Comment=Raise groups of windows
Icon=/path/to/raise.png
Terminal=false
Type=Application
Version=1.0
Actions=
Kurze Erklärung
Alle oben genannten Lösungen werden verwendet wmctrl
, um mit dem wmctrl -lpG
Befehl eine Fensterliste zu erstellen . Dieser Befehl erzeugt Zeilen, die wie folgt aussehen:
0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox
Diese Zeilen umfassen:
- 1. Spalte: die ID des Fensters (mit der wir es erhöhen können)
- 3. Spalte: Die PID, die das Fenster besitzt.
- 4./5. Spalte: Die Fenstergeometrie xy (anhand derer wir sehen, ob sich das Fenster im aktuellen Ansichtsfenster befindet, icw
xrandr
)
Die pid wird in der Ausgabe von nachgeschlagen ps -u <username>
, um eine "benutzerlesbare" Identifikation (Name) der Anwendung zu erhalten.
So können wir den Anwendungen Fenster zuweisen. Anschließend können wir for
mit dem Befehl die Fenster einer bestimmten Anwendung in einer Schleife öffnenwmctrl -ia
.
In Option 3
startet das Skript eine Warteschleife von 3 Sekunden, wobei der xprop -root
Befehl wiederholt verwendet wird, um festzustellen, ob sich am vordersten Fenster etwas geändert hat. Dies geschieht, wenn der Benutzer entweder auf ein Startsymbol klickt, um das Fenster einer Anwendung zu öffnen, oder direkt auf ein Fenster klickt. In diesem Fall unterbricht die while-Schleife die "neue" vorderste Anwendung, schlägt sie nach und öffnet anschließend alle anderen Fenster dieser Anwendung.