Jak wyświetlić (podnieść) wszystkie okna aplikacji?

21

Mam aplikację korzystającą z wielu okien. Jak mogę szybko przenieść wszystkie okna tej aplikacji na pierwszy plan?

Kiedy przeglądam aplikacje za pomocą kółka przewijania, pokazuje tylko jedno okno. Przechodząc do następnego okna, ostatnie okno jest ponownie przenoszone do tła.

Po kliknięciu ikony aplikacji uzyskuję przegląd pełnoekranowy wszystkich okien. Muszę ręcznie wybrać każde okno i kilkakrotnie przesunąć kursor myszy na połowę ekranu.

Moim najlepszym rozwiązaniem do tej pory jest zminimalizowanie wszystkich okien ( Ctrl+ Super+ D), a następnie wyświetlenie okien mojej aplikacji za pomocą kółka przewijania.

Czy jest lepsze rozwiązanie?

peq
źródło
@Joschua Przeniesienie wszystkich okien aplikacji do przodu nie jest zbyt trudne, ale jak chcesz zdefiniować aplikację? czy wystarczy kombinacja klawiszy + kliknięcie okna aplikacji?
Jacob Vlijm,
@Joschua czy Mayby bardziej elegancki, kombinacja klawiszy + 1. znak nazwy aplikacji?
Jacob Vlijm,
Myślę, że zachowanie jest takie samo dla wszystkich aplikacji. Najczęściej tęsknię za tą funkcją w oknach terminali, gdzie często mam dwa lub więcej okien otwartych obok siebie. Następnie przełączam się na okno pełnoekranowe (np. Firefox) i kiedy chcę wrócić do dwóch okien terminalu, jest to trochę trudne. Najlepszym sposobem, jaki do tej pory znalazłem, jest kliknięcie środkowym przyciskiem myszy na pasku aplikacji Firefox, który przenosi Firefoksa w tło, dzięki czemu znów mam dwa terminale z przodu. Działa to jednak dobrze tylko wtedy, gdy na górze nie ma zbyt wielu aplikacji: D
peq
także @Joschua Możliwe byłoby wprowadzenie kombinacji klawiszy, aby przenieść do grup okien aplikacji z przodu ; naciśnij raz -> pokażą się wszystkie okna Firefoksa, naciśnij ponownie -> pokażą się wszystkie okna terminalu itp. można sprawić, by było naprawdę gładkie. ciekawy. pracuję nad tym. zajmie trochę pracy.
Jacob Vlijm
@JacobVlijm Brzmi jak właściwy kierunek .. :) Najważniejsze wydaje mi się to, że kombinacja klawiszy plus kliknięcie ikony powoduje przeniesienie wszystkich okien tej aplikacji (na przykład wielu terminali, jak wspomniano w peq) na przód, najlepiej rozłożonych na zewnątrz, aby się nie nakładały ... (Może coś takiego może stać się częścią Unity ?!)
Joschua

Odpowiedzi:

21

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ę:

wprowadź opis zdjęcia tutaj

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.

    wprowadź opis zdjęcia tutaj

  • 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, wmctrljeśli nie ma go jeszcze w systemie:

    sudo apt-get install wmctrl
    
  • utwórz, jeśli jeszcze nie istnieje, katalog:

    ~/bin
    

    (wyjaśnienie: katalog ~/binznajduje 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) ~/bini 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, zenitypojawi 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-terminalokna w bieżącej rzutni:

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

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:

wprowadź opis zdjęcia tutaj

Naciskam raz Alt+ 1, wszystkie nautilusokna są podnoszone:

<image>

Naciskam ponownie Alt+ 1, wszystkie firefoxokna są podnoszone:

<image>

Naciskam ponownie Alt+ 1, wszystkie gnome-terminalokna są ponownie podnoszone, cykl zaczyna się od nowa:

<image>

Jak używać

  • Wykonaj konfigurację zgodnie z opisem w „Jak używać”
  • Dodaj go do wybranej kombinacji klawiszy skrótu: Wybierz: Ustawienia systemu> „Klawiatura”> „Skróty”> „Skróty niestandardowe”. Kliknij „+” i dodaj polecenie

    raise_app
    

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 nautilusoknami ukrytymi pod innymi oknami.

<image>

Aby podnieść wszystkie okna nautilusa (przykładowy skrót: Alt+ 1):

  • Naciśnij Alt+ 1, puść (!)
  • W ciągu 3 sekund:

    kliknij ikonę aplikacji w programie uruchamiającym

    <image>

    lub:

    kliknij jedno z okien aplikacji

    <image>

    wynik:

    <image>


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:

  • Naciśnij kombinację klawiszy i w ciągu 3 sekund:

    • kliknij ikonę aplikacji w programie uruchamiającym
    • kliknij jedno z okien aplikacji

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 zenityokno, wyświetlając listę wszystkich aplikacji i liczbę ich okien w bieżącej rzutni:

wprowadź opis zdjęcia tutaj

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.

wprowadź opis zdjęcia tutaj

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 / .desktopplik

  1. Przygotuj konfigurację jak w „Jak używać”, zapisz pierwszy (główny-) skrypt jak raise_appw~/bin
  2. Zapisz ikonę poniżej (kliknij prawym przyciskiem myszy, zapisz jako) jako raise.png

    <icon>

  3. Skopiuj .desktopplik 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.desktopw~/.local/share/applications

  4. Przeciągnij .desktopplik do programu uruchamiającego, aby go dodać

  5. skopiuj drugi skrypt, wklej go do pustego pliku, zapisz go jako update_appsw ~/bin, zrób to.
  6. Dodaj następujące polecenie do aplikacji startowych (Dash> Aplikacje startowe> Dodaj):

    update_apps
    
  7. 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żą wmctrldo utworzenia listy okien za pomocą wmctrl -lpGpolecenia. 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 forpętli za pomocą polecenia wmctrl -ia.

W opcji 3
skrypt uruchamia 3-sekundową pętlę „oczekiwania”, przy użyciu xprop -rootpolecenia 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.

Jacob Vlijm
źródło
Zgadzam się i jeszcze raz dziękuję za cały twój wysiłek! :) || Jest dziwna rzecz, której wcześniej nie zauważyłem. Czasami po użyciu Option 2skryptu, gdy okno aplikacji jest skupione (które nie jest zmaksymalizowane) i klikam inne okno, które jest widoczne „poniżej”, aplikacja poniżej poniżej nie jest aktywna.
Joschua
@Joschua OP tego pytania: askubuntu.com/questions/575830 /... zgłosił się do mnie z błędem, który został wprowadzony w najnowszej aktualizacji „funkcji”. Prawda / fałsz zostały pomieszane, powodując awarię skryptu, gdy żadna aplikacja nie ma więcej niż jednego okna. Jeśli używasz opcji 2, zaktualizuj do najnowszej wersji.
Jacob Vlijm
Opcja 1 nie działa dla mnie na Ubuntu Xenial. coś @ coś: ~ / bin $ ./raise_app Wiadomość Gtk: GtkDialog zmapowany bez tymczasowego rodzica. To jest odradzane. Próbowałem otworzyć okna terminala. Nic się nie stało.
xtrinch
@Nirri, jakiej nazwy aplikacji użyłeś? Komunikat jest całkiem normalny, jeśli okno zenity działa bez rodzica Gtk. „Zniechęcony” nie jest błędem.
Jacob Vlijm,
Pierwsze znaki terminalu. Działa - w pewnym sensie
xtrinch 17.09.16
1

Jest Super+W skrót, który pokaże expo wszystkich aktualnie otwartych okien, choć będzie to obejmować inne aplikacje. Jest to domyślnie i nie wymaga żadnych zmian, więc być może jest to najprostsza dostępna opcja.

Między innymi można ustawić okna na prawej i lewej połowie ekranu za pomocą przycisków Ctrl+ Super+ Left/ Righti przełączać się między nimi za pomocą Alt + ~ (tylda, ta obok klawisza numer jeden).

Sergiy Kolodyazhnyy
źródło
To jednak nie podnosi wszystkich okien aplikacji. Możesz je zobaczyć, ale nie możesz ich używać bez konieczności częstego klikania.
Joschua
1

Jeśli naciśniesz Alt + Tab, aby przechodzić między aplikacjami i przejdziesz do jednego z wieloma oknami, po prostu przytrzymaj klawisz Alt i po około 1 pełnej sekundzie ikona zostanie zastąpiona widokiem wszystkich okien dla tej aplikacji.

To może, ale nie musi być to, czego szukasz, ale działa dla mnie i jest o wiele prostsze, więc pomyślałem, że podzielę się tą opcją!

Sean Colombo
źródło
1
Możesz także nacisnąć klawisz strzałki w dół, aby od razu wyświetlić okna aplikacji.
Kris,
1

Wziąłem skrypt rai_apps.py autorstwa JacobVlijm i wprowadziłem kilka ulepszeń, w tym ulepszenie.

W szczególności odkryłem, że po dniu lub dwóch skrypt @ JacobVlijm przestałby działać i musiałbym ręcznie zrestartować skrypt, aby ponownie go uruchomić. Patrząc z perspektywy czasu, przypuszczam, że liczne wywołania xrandr ostatecznie powodują problemy.

W każdym razie dostosowałem jego kod, zwiększyłem częstotliwość odpytywania z 5 sekund do 1 sekundy, ponieważ i tak nie zużywa dużo procesora, i uczyniłem go bardziej niezawodnym. Zwykle mogę pracować bez problemu przez kilka dni / tygodni.

Jednym zastrzeżeniem jest to, że dzwonię do xrandr tylko raz podczas uruchamiania, aby uzyskać wymiary rozdzielczości ekranu. Więc jeśli zmienisz rozdzielczość ekranu (np. Z 1920x1080 na inną rozdzielczość), prawdopodobnie prawdopodobnie będziesz chciał ręcznie zrestartować raise-apps.py, aby wybrał nową rozdzielczość. Osobiście nigdy nie zmieniam rozdzielczości ekranu, więc nie stanowi to dla mnie problemu. Ponadto mam silny powód, by sądzić, że zbyt wiele wywołań xrandr spowodowało, że wersja skryptu @ JacobVlijm przestała działać po dniu lub dwóch, więc zdecydowanie zalecałbym nie odkładanie licznych wywołań do xrandr.

BTW, musisz umieścić obraz rai.png w katalogu / usr / local / icons /. Lub jeśli chcesz umieścić raise.png w innym katalogu, dokonaj odpowiedniej zmiany w skrypcie, aby skrypt mógł znaleźć plik obrazu.

Mamy nadzieję, że Ubuntu zintegruje tego typu funkcje „podniesienia wszystkich okien” do swojego systemu wcześniej niż później, ponieważ jest to bardzo przydatne:

#!/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()
Gino
źródło