Bagaimana cara menampilkan (menaikkan) semua jendela aplikasi?

21

Saya punya aplikasi menggunakan banyak windows. Bagaimana saya bisa dengan cepat membawa semua jendela aplikasi itu ke latar depan?

Ketika saya menggulir aplikasi dengan roda-gulir itu hanya menampilkan satu jendela. Saat pergi ke jendela berikutnya, jendela terakhir dibawa ke latar belakang lagi.

Ketika saya mengklik ikon aplikasi, saya mendapatkan gambaran umum layar penuh dari semua jendela. Saya harus memilih setiap jendela secara manual dan memindahkan mouse saya melintasi setengah layar beberapa kali.

Solusi terbaik saya sejauh ini adalah meminimalkan semua jendela ( Ctrl+ Super+ D) dan kemudian menampilkan windows aplikasi saya menggunakan scroll-wheel.

Apakah ada solusi yang lebih baik?

peq
sumber
@Joschua Membawa semua jendela aplikasi ke depan tidak terlalu sulit, tetapi bagaimana Anda ingin mendefinisikan aplikasi? akankah kombinasi kunci + mengklik jendela aplikasi lakukan?
Jacob Vlijm
@Joschua atau mayby ​​lebih elegan, kombo kunci + karakter pertama dari nama aplikasi?
Jacob Vlijm
Saya pikir perilaku itu sama dengan semua aplikasi. Saya paling sering melewatkan fitur ini dengan jendela terminal, di mana saya sering memiliki dua atau lebih jendela yang terbuka berdampingan. Lalu saya beralih ke jendela layar penuh (misalnya Firefox) dan ketika saya ingin beralih kembali ke dua terminal windows itu agak sulit. Cara terbaik yang saya temukan sejauh ini adalah klik tengah mouse pada bilah aplikasi Firefox yang membawa Firefox ke latar belakang sehingga saya memiliki dua terminal di depan lagi. Namun ini hanya bekerja dengan baik, ketika Tidak ada terlalu banyak aplikasi yang ditumpuk di atas: D
peq
juga @Joschua Mungkin untuk memiliki kombinasi tombol untuk membawa ke depan jendela kelompok aplikasi ; tekan sekali -> semua jendela firefox muncul, pres kembali -> semua jendela terminal muncul dll. dapat dibuat sangat halus. menarik. sedang mengerjakannya. akan membutuhkan sedikit kerja.
Jacob Vlijm
@JacobVlijm Kedengarannya seperti arah yang benar .. :) Apa yang tampaknya paling penting bagi saya, adalah bahwa kombinasi tombol plus mengklik ikon membawa semua jendela aplikasi itu (misalnya, banyak terminal seperti yang disebutkan peq) ke depan, sebaiknya menyebar keluar, sehingga mereka tidak tumpang tindih .. (Mungkin, sesuatu seperti ini bisa menjadi bagian dari Unity ?!)
Joschua

Jawaban:

21

EDIT -new answer-

Jawaban di bawah ini masih benar-benar valid, dan demikianlah opsi yang disarankan. Namun wawasan yang sedang berlangsung membuat saya menambahkan opsi ini untuk menggunakan indikator di bawah ini, yang mungkin merupakan solusi paling elegan.

Karena itu, mungkin harus mengganti opsi 5 (menggunakan file .desktop).

Cukup pilih aplikasi dari daftar, dan semua jendela aplikasi yang sesuai (ada pada viewport saat ini) akan menaikkan:

masukkan deskripsi gambar di sini

Bagaimana cara menggunakan

dari ppa:

sudo add-apt-repository ppa:vlijm/upfront
sudo apt-get update
sudo apt-get install upfront

... atau secara manual:

#!/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()
  • Kebutuhan indikator wmctrl

    sudo apt-get wmctrl
    
  • Salin indikator ke file kosong, simpan sebagai raise_apps.py

  • Salin gambar di bawah ini, simpan persis namanya raise.png dalam satu dan direktori yang sama dengan indikator.

    masukkan deskripsi gambar di sini

  • Maka jalankan saja dengan perintah:

    python3 /path/to/raise_apps.py

  • Tambah jika Anda ingin Aplikasi Permulaan:

    /bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py" 
    

JAWABAN TUA:

Tentang pertanyaan itu

Dengan alat yang tepat, tidak terlalu rumit untuk "hanya" menaikkan semua jendela aplikasi. Ini sedikit lebih rumit untuk memastikan hanya jendela viewport saat ini yang dinaikkan. Namun tantangan sebenarnya adalah menemukan cara yang nyaman untuk membuat tindakan tersedia bagi pengguna.

Di bawah lima opsi untuk mengatasinya, untuk menunjukkan bagaimana hal itu bisa dilakukan. Semua opsi siap digunakan. Namun opsi terakhir adalah jenis eksperimental; itu berfungsi dengan baik tetapi memiliki beberapa kerugian kosmetik kecil, seperti yang dijelaskan dalam deskripsi opsi. Saya menambahkannya sebagai konsep .

Menyebarkan jendela secara otomatis dengan cara yang tidak tumpang tindih, seperti yang disarankan dalam komentar, tampaknya bukan ide yang praktis bagi saya; jika Anda bekerja dalam pengaturan jendela grup (aplikasi-bijaksana), skrip mungkin akan mengatur ulang windows yang tidak diinginkan.

Bagaimana cara menggunakan

Untuk semua opsi, Anda perlu:

  • instal wmctrljika belum ada di sistem Anda:

    sudo apt-get install wmctrl
    
  • buat, jika belum ada, direktori:

    ~/bin
    

    (penjelasan: direktori ~/bindalam $ PATH, sehingga Anda dapat menjalankan executable dengan namanya)

  • Salin skrip, sesuai dengan opsi, tempel ke file kosong, simpan sebagai raise_app(tanpa ekstensi) ~/bindan buat itu dapat dieksekusi

Dalam opsi terpisah, langkah-langkah tambahan yang mungkin akan dijelaskan.

Opsi 1: pilih aplikasi dengan memasukkan satu atau lebih karakter

  • Tekan kombinasi tombol, sebuah zenityjendela akan muncul
  • Masukkan satu atau lebih karakter dari nama aplikasi di kotak entri
  • Tekan enter

Ini akan membuat semua jendela aplikasi yang cocok (pada viewport saat ini ) tampil ke depan.

naikkan semua gnome-terminaljendela di viewport saat ini:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Bagaimana cara menggunakan:

  • Lakukan pengaturan seperti yang dijelaskan dalam "Cara menggunakan"
  • Tes-jalankan dengan perintah:

    raise_app
    
  • Jika semuanya berfungsi dengan baik, tambahkan ke kombinasi tombol pintas pilihan Anda: Pilih: Pengaturan Sistem> "Keyboard"> "Pintasan"> "Pintasan Khusus". Klik "+" dan tambahkan perintah

Naskah:

#!/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



Opsi 2: menelusuri aplikasi dan meningkatkan windows mereka dengan kombinasi tombol:

Katakanlah saya memiliki skrip di bawah ini di bawah kombinasi kunci Alt+ 1. Saya memiliki beberapa jendela terbuka:

  • firefox
  • terminal gnome
  • nautilus

Keadaan saat ini:

masukkan deskripsi gambar di sini

Saya menekan sekali Alt+ 1, semua nautilusjendela dinaikkan:

<gambar>

Saya menekan lagi Alt+ 1, semua firefoxjendela dinaikkan:

<gambar>

Saya menekan lagi Alt+ 1, semua gnome-terminaljendela dinaikkan lagi, siklus dimulai lagi:

<gambar>

Bagaimana cara menggunakan

  • Lakukan pengaturan seperti yang dijelaskan dalam "Cara menggunakan"
  • Tambahkan ke kombinasi tombol pintas pilihan Anda: Pilih: Pengaturan Sistem> "Keyboard"> "Pintasan"> "Pintasan Khusus". Klik "+" dan tambahkan perintah

    raise_app
    

Kemudian putar aplikasi Anda dengan jendela aplikasi yang dikelompokkan dengan kombinasi tombol Anda.

Naskah:

#!/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



Opsi 3: tekan kombinasi tombol + klik ikon peluncur - atau - jendela aplikasi untuk menaikkan semua jendela pada viewport saat ini

Ini mungkin opsi yang paling dekat dengan apa yang dijelaskan dalam pertanyaan / komentar.

Katakanlah saya memiliki desktop yang berantakan dengan tiga nautilusjendela terkubur di bawah jendela lain.

<gambar>

Untuk menaikkan semua jendela nautilus (contoh pintasan: Alt+ 1):

  • Tekan Alt+ 1, lepaskan (!)
  • Dalam 3 detik, baik:

    klik ikon aplikasi di peluncur

    <gambar>

    atau:

    klik pada salah satu jendela aplikasi

    <gambar>

    hasil:

    <gambar>


Bagaimana cara menggunakan:

  • Lakukan pengaturan seperti yang dijelaskan dalam "Cara menggunakan"
  • Tes-jalankan dengan perintah:

    raise_app
    
  • Jika semuanya berfungsi dengan baik, tambahkan ke kombinasi tombol pintas pilihan Anda: Pilih: Pengaturan Sistem> "Keyboard"> "Pintasan"> "Pintasan Khusus". Klik "+" dan tambahkan perintah

Kemudian:

  • Tekan kombinasi tombol Anda dan dalam 3 detik, baik:

    • klik ikon aplikasi di peluncur
    • klik pada salah satu jendela aplikasi

Naskah

#!/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


Opsi 4: kombinasi tombol memanggil daftar opsi, menunjukkan jumlah jendela per aplikasi pada viewport saat ini

Yang ini ternyata lebih nyaman daripada yang saya duga:

Menekan kombinasi tombol (lagi contoh-) Alt+ 1memanggil zenityjendela, mendaftar semua aplikasi dan jumlah windows mereka pada viewport saat ini:

masukkan deskripsi gambar di sini

Cukup dengan menekan atau panah akan membawa Anda ke opsi yang tepat. Tekan Enterdan semua jendela aplikasi yang dipilih dinaikkan.

Bagaimana cara menggunakan:

  • Lakukan pengaturan seperti yang dijelaskan dalam "Cara menggunakan"
  • Tes-jalankan dengan perintah:

    raise_app
    
  • Jika semuanya berfungsi dengan baik, tambahkan ke kombinasi tombol pintas pilihan Anda: Pilih: Pengaturan Sistem> "Keyboard"> "Pintasan"> "Pintasan Khusus". Klik "+" dan tambahkan perintah

Naskah

#!/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"')



Opsi 5: meningkatkan windows menjalankan aplikasi dari ikon peluncur

Opsi ini ada dari ikon peluncur, dengan aplikasi yang sedang berjalan dalam daftar cepat. Pilih satu, dan semua jendela aplikasi akan dinaikkan.

masukkan deskripsi gambar di sini

Peluncur diperbarui secara otomatis ketika daftar aplikasi yang berjalan (pada viewport saat ini) berubah. Daftar cepat menunjukkan daftar yang berbeda pada viewports lain, di mana jendela aplikasi lain dibuka (akan memakan waktu 1-2 detik untuk beradaptasi).

Sebagaimana disebutkan, meskipun berfungsi penuh, opsi ini dimaksudkan sebagai konsep . Ini memiliki beberapa kerugian kecil kosmetik seperti itu. Yang paling penting:

  • "Roda" kursor terus berputar selama beberapa detik setelah suatu tindakan. Meskipun tidak memengaruhi fungsionalitas, ini adalah kerugian kosmetik.
  • Diperlukan 1-2 detik untuk daftar aplikasi dalam ikon peluncur untuk diperbarui setelah daftar aplikasi yang berjalan berubah.

Selanjutnya pengaturannya sedikit lebih rumit (meskipun dijelaskan secara rinci di bawah):

Bagaimana cara menggunakan

Di bawah ini Anda akan menemukan:

dua skrip / ikon / .desktopfile

  1. Siapkan pengaturan seperti pada "Cara menggunakan", simpan skrip pertama (utama) seperti raise_apppada~/bin
  2. Simpan ikon di bawah ini (klik kanan, simpan sebagai) sebagai raise.png

    <icon>

  3. Salin .desktopfile ke file kosong, edit baris

        Icon=/path/to/raise.png
    

    ke jalan nyata untuk ikon (jalur dengan spasi antara tanda kutip)
    Simpan sebagai raise.desktopdi~/.local/share/applications

  4. Seret .desktopfile ke peluncur untuk menambahkannya

  5. salin script kedua, paste ke file kosong, simpan sebagai update_appsdi ~/bin, membuatnya menjadi executable.
  6. Tambahkan perintah berikut ke aplikasi startup Anda (Dash> Startup Applications> Add):

    update_apps
    
  7. Logout dan kembali untuk membuatnya berfungsi.

Script pertama

#!/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

Naskah kedua

#!/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)

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=



Penjelasan singkat

Semua solusi di atas digunakan wmctrluntuk membuat daftar jendela, menggunakan wmctrl -lpGperintah. Perintah ini menghasilkan baris, seperti:

0x044000b3  0 3429   65   24   1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox

Garis-garis ini termasuk:

  • Kolom 1: id jendela (yang bisa kita gunakan untuk menaikkannya)
  • Kolom ke-3: pid yang memiliki jendela.
  • Kolom 4/5: geometri jendela xy (yang kita gunakan untuk melihat apakah jendela tersebut ada di viewport saat ini, icw xrandr)

Pid itu mencari dalam output ps -u <username>untuk mendapatkan identifikasi (nama) aplikasi yang "dapat dibaca pengguna".
Dengan demikian kita dapat mengalokasikan windows ke aplikasi. Selanjutnya kita dapat menaikkan jendela aplikasi yang diberikan dalam satu forlingkaran dengan perintah wmctrl -ia.

Dalam opsi 3
, skrip memulai loop "menunggu" selama 3 detik, menggunakan xprop -rootperintah berulang kali untuk melihat apakah ada perubahan pada apa yang merupakan jendela paling depan; ini akan terjadi jika pengguna mengklik ikon peluncur untuk menaikkan jendela aplikasi, atau mengklik jendela secara langsung. Jika demikian, loop sementara memecah dan mencari aplikasi paling depan "baru", dan kemudian memunculkan semua jendela lain dari aplikasi itu.

Yakub Vlijm
sumber
Saya setuju, dan terima kasih lagi untuk semua usaha Anda! :) || Ada hal aneh yang tidak saya perhatikan sebelumnya. Kadang-kadang setelah menggunakan Option 2skrip, ketika jendela aplikasi difokuskan (yang tidak dimaksimalkan) dan saya mengklik jendela lain yang terlihat "di bawah", aplikasi di bawah ini tidak mendapatkan fokus.
Joschua
@Joschua OP dari pertanyaan ini: askubuntu.com/questions/575830/... menghadiri saya tentang bug yang diperkenalkan pada pembaruan "fitur" terbaru. Benar / Salah digabungkan, menyebabkan skrip mogok ketika tidak ada aplikasi yang memiliki lebih dari satu jendela. Jika Anda menggunakan option2, silakan perbarui ke versi terbaru.
Jacob Vlijm
Opsi 1 tidak berfungsi untuk saya di ubuntu xenial. something @ something: ~ / bin $ ./raise_app Gtk-Message: GtkDialog dipetakan tanpa orangtua sementara. Ini tidak dianjurkan. Saya sedang mencoba membuka terminal windows. Tidak ada yang terjadi.
xtrinch
@Nirri nama aplikasi apa yang Anda gunakan? Pesannya cukup normal jika jendela zenity berjalan tanpa orangtua Gtk. "Diremehkan" bukan kesalahan.
Jacob Vlijm
Karakter pertama terminal. Ini berfungsi - semacam - ini memunculkan jendela aplikasi apa pun - tetapi hanya satu di antaranya, tidak semuanya seperti yang diharapkan @ user72216
xtrinch
1

Ada Super+ Wjalan pintas yang akan menampilkan pameran semua jendela yang sedang terbuka, meskipun itu akan mencakup aplikasi lain. Ini datang secara default, dan tidak memerlukan perubahan apa pun, jadi mungkin ini pilihan paling sederhana yang tersedia.

Di antara hal-hal lain, Anda dapat memposisikan jendela di sisi kanan dan kiri layar dengan tombol Ctrl+ Super+ Left/ Right, dan beralih di antaranya dengan Alt + ~ (tilde, tombol di sebelah tombol nomor satu).

Sergiy Kolodyazhnyy
sumber
Itu tidak membawa semua jendela aplikasi ke atas sekalipun. Anda dapat melihatnya, tetapi Anda tidak dapat menggunakannya tanpa harus mengklik banyak.
Joschua
1

Jika Anda menekan Alt + Tab untuk menelusuri aplikasi, dan Anda mendapatkan satu dengan beberapa jendela, cukup tahan tombol alt ke bawah dan setelah sekitar 1 detik penuh ikon akan diganti dengan tampilan semua jendela untuk aplikasi itu.

Itu mungkin atau mungkin bukan yang Anda cari, tetapi itu bekerja untuk saya dan lebih sederhana, jadi saya pikir saya akan berbagi opsi!

Sean Colombo
sumber
1
Anda juga dapat menekan tombol panah ke bawah untuk segera menampilkan jendela aplikasi.
Kris
1

Saya mengambil skrip kenaikan_apps.py @ JacobVlijm dan membuat beberapa peningkatan padanya, termasuk membuatnya lebih kuat.

Secara khusus, saya telah menemukan bahwa setelah satu atau dua hari, skrip @ JacobVlijm akan berhenti bekerja, dan saya harus me-restart skrip secara manual, untuk membuatnya berfungsi kembali. Dalam retrospeksi, tebakan terbaik saya adalah bahwa banyak panggilan ke xrandr akhirnya menyebabkan masalah.

Bagaimanapun, saya mengadaptasi kodenya, meningkatkan frekuensi pemungutan suara dari 5 detik menjadi setiap 1 detik, karena tidak menggunakan banyak CPU, dan membuatnya lebih kuat. Saya biasanya dapat menjalankannya selama berhari-hari / minggu tanpa masalah.

Satu peringatan adalah bahwa saya hanya memanggil xrandr sekali selama startup, untuk mendapatkan dimensi resolusi layar. Jadi, jika Anda mengubah resolusi layar Anda (mis. Dari 1920x1080 ke beberapa resolusi lain), Anda mungkin ingin me-restart secara manual kenaikan-apps.py sehingga itu akan mengambil resolusi baru. Secara pribadi, saya tidak pernah mengubah resolusi layar saya, jadi ini bukan masalah bagi saya. Selain itu, saya memiliki alasan kuat untuk percaya bahwa terlalu banyak panggilan ke xrandr yang menyebabkan versi skrip @ JacobVlijm berhenti bekerja setelah satu atau dua hari, jadi saya akan sangat menyarankan tidak hanya meletakkan banyak panggilan ke xrandr kembali.

BTW, Anda perlu menempatkan gambar rais.png di direktori / usr / local / icons /. Atau jika Anda ingin menempatkan rais.png di direktori yang berbeda, lakukan perubahan yang sesuai pada skrip, sehingga skrip dapat menemukan file gambar.

Mudah-mudahan, Ubuntu akan mengintegrasikan jenis fungsi 'naikkan semua jendela' ini ke dalam sistem mereka lebih cepat daripada nanti karena sangat berguna:

#!/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
sumber