EDYCJA - nowa odpowiedź -
Poniższe odpowiedzi są nadal aktualne, dlatego sugerowane opcje. Ciągły wgląd sprawił jednak, że dodałem tę opcję, aby użyć poniższego wskaźnika, który jest prawdopodobnie najbardziej eleganckim rozwiązaniem.
Jako taki powinien prawdopodobnie zastąpić opcję 5 (przy użyciu pliku .desktop).
Po prostu wybierz aplikację z listy, a wszystkie okna odpowiedniej aplikacji (obecne w bieżącej rzutni) pojawią się:
Jak używać
z ppa:
sudo add-apt-repository ppa:vlijm/upfront
sudo apt-get update
sudo apt-get install upfront
... lub ręcznie:
#!/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()
Wskaźnik potrzebuje wmctrl
sudo apt-get wmctrl
Skopiuj wskaźnik do pustego pliku i zapisz go jako raise_apps.py
Skopiuj poniższy obraz, zapisz go dokładnie raise.png
w jednym i tym samym katalogu co wskaźnik.
Następnie po prostu uruchom go za pomocą polecenia:
python3 /path/to/raise_apps.py
Dodaj, jeśli chcesz uruchomić aplikacje:
/bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py"
STARA ODPOWIEDŹ:
O pytaniu
Dzięki odpowiednim narzędziom „po prostu” podniesienie wszystkich okien aplikacji nie jest bardzo skomplikowane. Trochę bardziej skomplikowane jest upewnienie się, że podniesione są tylko okna bieżącej rzutni. Prawdziwym wyzwaniem jest jednak znalezienie wygodnego sposobu udostępnienia akcji użytkownikowi.
Poniżej pięć opcji, aby się tym zająć, aby pokazać, jak można to zrobić. Wszystkie opcje są gotowe do użycia. Ostatnia opcja jest jednak trochę eksperymentalna; działa dobrze, ale ma kilka drobnych wad kosmetycznych, jak wyjaśniono w opisie opcji. Dodałem to jednak jako koncepcję .
Automatyczne rozkładanie okien w sposób nienakładający się, jak sugerowano w komentarzu, nie wydaje mi się praktycznym pomysłem; jeśli pracujesz w konfiguracji okna zgrupowanej pod względem aplikacji, skrypt prawdopodobnie niechcianie zmieni kolejność okien.
Jak używać
W przypadku wszystkich opcji musisz:
zainstaluj, wmctrl
jeśli nie ma go jeszcze w systemie:
sudo apt-get install wmctrl
utwórz, jeśli jeszcze nie istnieje, katalog:
~/bin
(wyjaśnienie: katalog ~/bin
znajduje się w $ PATH, więc można uruchamiać pliki wykonywalne według ich nazw)
Skopiuj skrypt, odpowiadający opcji, wklej go do pustego pliku, zapisz jako raise_app
(bez rozszerzenia) ~/bin
i uczyń z niego wykonywalnym
W osobnych opcjach wyjaśnione zostaną możliwe dodatkowe kroki.
Opcja 1: wybierz aplikację, wprowadzając jeden lub więcej znaków
- Naciśnij kombinację klawiszy,
zenity
pojawi się okno
- Wprowadź co najmniej jeden znak nazwy aplikacji w polu wprowadzania
- Naciśnij enter
Spowoduje to, że wszystkie okna pasującej aplikacji (w bieżącej rzutni) znajdą się na pierwszym planie .
podnieś wszystkie gnome-terminal
okna w bieżącej rzutni:
Jak używać:
- Wykonaj konfigurację zgodnie z opisem w „Jak używać”
Uruchom go testowo za pomocą polecenia:
raise_app
Jeśli wszystko działa poprawnie, dodaj go do wybranej kombinacji klawiszy skrótu: Wybierz: Ustawienia systemu> „Klawiatura”> „Skróty”> „Skróty niestandardowe”. Kliknij „+” i dodaj polecenie
Scenariusz:
#!/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
Opcja 2: przełączaj między aplikacjami i podnoś okna za pomocą kombinacji klawiszy:
Powiedzmy, że mam poniższy skrypt pod kombinacją klawiszy Alt+ 1. Mam kilka otwartych okien:
- Firefox
- terminal gnome
- łodzik
Aktualny stan:
Naciskam raz Alt+ 1, wszystkie nautilus
okna są podnoszone:
Naciskam ponownie Alt+ 1, wszystkie firefox
okna są podnoszone:
Naciskam ponownie Alt+ 1, wszystkie gnome-terminal
okna są ponownie podnoszone, cykl zaczyna się od nowa:
Jak używać
Następnie przeglądaj aplikacje za pomocą zgrupowanych okien aplikacji i kombinacji klawiszy.
Scenariusz:
#!/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
Opcja 3: naciśnij kombinację klawiszy + kliknij ikonę programu uruchamiającego lub okno aplikacji, aby podnieść wszystkie okna w bieżącej rzutni
Prawdopodobnie jest to opcja najbliższa opisanemu w pytaniu / komentarzu.
Powiedzmy, że mam brudny pulpit z trzema nautilus
oknami ukrytymi pod innymi oknami.
Aby podnieść wszystkie okna nautilusa (przykładowy skrót: Alt+ 1):
Jak używać:
- Wykonaj konfigurację zgodnie z opisem w „Jak używać”
Uruchom go testowo za pomocą polecenia:
raise_app
Jeśli wszystko działa poprawnie, dodaj go do wybranej kombinacji klawiszy skrótu: Wybierz: Ustawienia systemu> „Klawiatura”> „Skróty”> „Skróty niestandardowe”. Kliknij „+” i dodaj polecenie
Następnie:
Scenariusz
#!/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
Opcja 4: kombinacja klawiszy wywołuje listę opcji, pokazującą liczbę okien na aplikację w bieżącej rzutni
Ten okazał się wygodniejszy niż się spodziewałem:
Naciśnięcie kombinacji klawiszy (ponownie przykład-) Alt+ 1wywołuje zenity
okno, wyświetlając listę wszystkich aplikacji i liczbę ich okien w bieżącej rzutni:
Wystarczy nacisnąć strzałki ▴lub ▾, aby przejść do właściwej opcji. Naciśnij Enteri wszystkie okna wybranej aplikacji zostaną podniesione.
Jak używać:
- Wykonaj konfigurację zgodnie z opisem w „Jak używać”
Uruchom go testowo za pomocą polecenia:
raise_app
Jeśli wszystko działa poprawnie, dodaj go do wybranej kombinacji klawiszy skrótu: Wybierz: Ustawienia systemu> „Klawiatura”> „Skróty”> „Skróty niestandardowe”. Kliknij „+” i dodaj polecenie
Scenariusz
#!/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"')
Opcja 5: podnieś okna uruchomionych aplikacji z ikony programu uruchamiającego
Ta opcja istnieje z ikoną programu uruchamiającego, z aktualnie uruchomionymi aplikacjami na szybkiej liście. Wybierz jedno, a wszystkie okna aplikacji zostaną podniesione.
Program uruchamiający jest automatycznie aktualizowany, gdy zmienia się lista uruchomionych aplikacji (w bieżącej rzutni). Skrócona lista pokazuje inną listę w innych rzutniach, w których otwierane są okna innych aplikacji (dostosowanie zajmie 1-2 sekundy).
Jak wspomniano, chociaż w pełni funkcjonalna, ta opcja jest pomyślana jako koncepcja . Ma kilka drobnych wad kosmetycznych. Najważniejsze:
- „Koło” kursora obraca się przez kilka sekund po akcji. Chociaż nie wpływa to na funkcjonalność, jest kosmetycznym minusem.
- Aktualizacja listy aplikacji na ikonie programu uruchamiającego zajmuje 1-2 sekundy po zmianie listy uruchomionych aplikacji.
Ponadto konfiguracja jest nieco bardziej skomplikowana (choć szczegółowo wyjaśniona poniżej):
Jak używać
Poniżej znajdziesz:
dwa skrypty / ikona / .desktop
plik
- Przygotuj konfigurację jak w „Jak używać”, zapisz pierwszy (główny-) skrypt jak
raise_app
w~/bin
Zapisz ikonę poniżej (kliknij prawym przyciskiem myszy, zapisz jako) jako raise.png
Skopiuj .desktop
plik do pustego pliku, edytuj wiersz
Icon=/path/to/raise.png
do rzeczywistej ścieżki do ikony (ścieżki ze spacjami cudzysłowie)
zapisać go jako raise.desktop
w~/.local/share/applications
Przeciągnij .desktop
plik do programu uruchamiającego, aby go dodać
- skopiuj drugi skrypt, wklej go do pustego pliku, zapisz go jako
update_apps
w ~/bin
, zrób to.
Dodaj następujące polecenie do aplikacji startowych (Dash> Aplikacje startowe> Dodaj):
update_apps
- Wyloguj się i zaloguj ponownie, aby to działało.
Pierwszy skrypt
#!/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
Drugi skrypt
#!/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)
Plik .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=
Krótkie wyjaśnienie
Wszystkie powyższe rozwiązania służą wmctrl
do utworzenia listy okien za pomocą wmctrl -lpG
polecenia. To polecenie tworzy linie wyglądające jak:
0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox
Te linie obejmują:
- Pierwsza kolumna: identyfikator okna (którego możemy użyć do podniesienia go)
- Trzecia kolumna: identyfikator właściciela okna.
- 4/5 kolumna: geometria okna xy (używamy, aby sprawdzić, czy okno znajduje się w bieżącej rzutni, icw
xrandr
)
Pid jest sprawdzany na wyjściu, ps -u <username>
aby uzyskać identyfikację (nazwę) aplikacji „czytelną dla użytkownika”.
W ten sposób możemy przydzielić okna do aplikacji. Następnie możemy podnieść okna danej aplikacji w for
pętli za pomocą polecenia wmctrl -ia
.
W opcji 3
skrypt uruchamia 3-sekundową pętlę „oczekiwania”, przy użyciu xprop -root
polecenia wielokrotnie, aby sprawdzić, czy jest jakaś zmiana w oknie znajdującym się z przodu; stanie się tak, jeśli użytkownik kliknie ikonę programu uruchamiającego, aby podnieść okno aplikacji, lub kliknie okno bezpośrednio. Jeśli tak, pętla while przerywa działanie i wyszukuje „nową” aplikację z przodu, a następnie podnosi wszystkie inne okna tej aplikacji.