Як показати (підняти) всі вікна програми?


21

У мене є додаток, що використовує кілька вікон. Як я можу швидко винести на перший план усі вікна цієї програми?

Коли я прокручую додатки за допомогою колеса прокрутки, воно показує лише одне вікно. Переходячи до наступного вікна, останнє вікно знову виводиться на задній план.

Коли я натискаю на піктограму програми, я отримую повний екран огляду всіх вікон. Доводиться вибирати кожне вікно вручну і кілька разів переміщувати мишу по половині екрана.

Моє найкраще рішення поки що - мінімізувати всі вікна ( Ctrl+ Super+ D), а потім показати вікна мого додатка за допомогою колеса прокрутки.

Чи є краще рішення?


@Joschua Вивести всі вікна програми на передню частину не надто складно, але як би ви хотіли визначити програму? чи буде комбінація клавіш + натискання вікна програми?
Яків Влійм

@Joschua або, можливо, більш елегантний, ключовий комбо + перший символ назви програми?
Яків Влійм

Я думаю, що поведінка однакова з усіма програмами. Я найчастіше пропускаю цю функцію з термінальними вікнами, де у мене часто два або більше вікон, відкритих поруч. Потім я переходжу на повне екранне вікно (наприклад, Firefox), і коли я хочу переключитися назад на два вікна терміналу, це якось важко. Найкращий спосіб, який я знайшов поки що, - це клацання мишею середнього клавіші на панелі додатків Firefox, яка приносить Firefox на задній план, щоб у мене знову були два термінали спереду. Однак це добре працює лише тоді, коли зверху
набрано

також @Joschua Можна було б отримати комбінацію клавіш для залучення до груп вікон передньої програми ; натисніть один раз -> відображаються всі вікна Firefox, натисніть знову -> всі вікна терміналів відображаються тощо. цікаво. працюю над цим. буде потрібно трохи працювати.
Яків Влійм

@JacobVlijm Звучить як правильний напрямок .. :) Найбільш важливим для мене є те, що комбінація клавіш плюс натискання на піктограму приносить усі вікна цієї програми (наприклад, багато терміналів, як згадується peq) на передню частину, бажано поширюється назовні, щоб вони не перетиналися .. (Можливо, щось подібне могло б стати частиною Єдності ?!)
Джошуа

Відповіді:


21

EDIT - нова відповідь-

Відповіді, які наведено нижче, є і надалі є абсолютно достовірними, тому пропоновані варіанти. Постійне розуміння, однак, змусило мене додати цей варіант, щоб використовувати індикатор нижче, який, мабуть, є найелегантнішим рішенням.

Як такий, він, ймовірно, повинен замінити варіант 5 (використовуючи файл .desktop).

Просто виберіть програму зі списку, і всі вікна відповідної програми (присутні в поточному вікні перегляду) піднімуть:

введіть тут опис зображення

Як користуватись

від ppa:

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

... або вручну:

#!/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()
  • Індикатор потребує wmctrl

    sudo apt-get wmctrl
    
  • Скопіюйте індикатор у порожній файл, збережіть його як raise_apps.py

  • Скопіюйте зображення внизу, збережіть його саме raise.png в одному і тому ж каталозі , що й індикатор.

    введіть тут опис зображення

  • Потім просто запустіть його командою:

    python3 /path/to/raise_apps.py

  • Додати, якщо ви хочете запустити програми:

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

СТАРИЙ ВІДПОВІДЬ:

Про питання

За допомогою правильних інструментів "не просто" підняти всі вікна програми не дуже складно. Трохи складніше переконатися, що підняті лише вікна поточного вікна перегляду. Однак справжньою проблемою є пошук зручного способу зробити дію доступним для користувача.

Нижче п’ять варіантів, щоб подбати про це, щоб показати, як це можна зробити. Усі варіанти готові до використання. Останній варіант, проте, є експериментальним; він працює чудово, але має кілька незначних косметичних недоліків, як пояснено в описі варіанту. Я додав це все-таки як концепцію .

Автоматичне розповсюдження вікон автоматичним способом, що не перекривається, як це запропоновано в коментарі, для мене не представляється практичною ідеєю; якщо ви працюєте в налаштованому на додаток вікні (з урахуванням додатків), сценарій, можливо, небажано буде переставляти вікна.

Як користуватись

Для всіх варіантів вам потрібно:

  • встановіть, wmctrlякщо його ще немає у вашій системі:

    sudo apt-get install wmctrl
    
  • створити, якщо він ще не існує, каталог:

    ~/bin
    

    (пояснення: каталог ~/binзнаходиться в $ PATH, тому ви можете запускати виконувані файли за їх іменем)

  • Скопіюйте скрипт, що відповідає параметру, вставте його в порожній файл, збережіть його як raise_app(без розширення) ~/binі зробіть його виконуваним

В окремих варіантах пояснюються можливі додаткові кроки.

Варіант 1: виберіть додаток, ввівши один або кілька символів

  • Натисніть комбінацію клавіш, з'явиться zenityвікно
  • Введіть один або кілька символів імені програми у поле введення
  • Натисніть Enter

Це призведе до того, що всі вікна відповідної програми (у поточному вікні перегляду) будуть передні.

підняти всі gnome-terminalвікна в поточному вікні перегляду:

введіть тут опис зображення

введіть тут опис зображення

Як користуватись:

  • Виконайте налаштування, як описано в "Як користуватися"
  • Перевірте його за допомогою команди:

    raise_app
    
  • Якщо все працює добре, додайте його до комбінації клавіш швидкого вибору за вибором: Виберіть: Налаштування системи> "Клавіатура"> "Ярлики"> "Спеціальні ярлики". Клацніть "+" і додайте команду

Сценарій:

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



Варіант 2: прокручуйте програми та піднімайте їх вікна за допомогою комбінації клавіш:

Скажімо, у мене є сценарій нижче під комбінацією клавіш Alt+ 1. У мене відкрито кілька вікон:

  • firefox
  • гном-термінал
  • nautilus

Поточний стан:

введіть тут опис зображення

Я натискаю один раз Alt+ 1, всі nautilusвікна піднімаються:

<зображення>

Я знову натискаю Alt+ 1, усі firefoxвікна піднімаються:

<зображення>

Я знову натискаю Alt+ 1, всі gnome-terminalвікна знову піднімаються, цикл починається з початку:

<зображення>

Як користуватись

  • Виконайте налаштування, як описано в "Як користуватися"
  • Додайте його до комбінації клавіш швидкого вибору: виберіть: Налаштування системи> "Клавіатура"> "Ярлики"> "Спеціальні ярлики". Клацніть "+" і додайте команду

    raise_app
    

Потім оберіть свої програми за допомогою згрупованих вікон додатків із комбінацією клавіш.

Сценарій:

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



Варіант 3: натисніть комбінацію клавіш + натисніть на значок запуску або вікно програми, щоб підняти всі вікна в поточному вікні перегляду

Це, мабуть, варіант, найбільш близький до того, що описано у питанні / коментарі.

Скажімо, у мене безладний робочий стіл із трьома nautilusвікнами, закопаними під іншими вікнами.

<зображення>

Підняти всі nautilus windows (приклад ярлика: Alt+ 1):

  • Натисніть Alt+ 1, відпустіть (!)
  • Протягом 3 секунд:

    натисніть на піктограму програми на панелі запуску

    <зображення>

    або:

    натисніть на одне з вікон програми

    <зображення>

    результат:

    <зображення>


Як користуватись:

  • Виконайте налаштування, як описано в "Як користуватися"
  • Перевірте його за допомогою команди:

    raise_app
    
  • Якщо все працює добре, додайте його до комбінації клавіш швидкого вибору за вибором: Виберіть: Налаштування системи> "Клавіатура"> "Ярлики"> "Спеціальні ярлики". Клацніть "+" і додайте команду

Потім:

  • Натисніть комбінацію клавіш і протягом 3 секунд або:

    • натисніть на піктограму програми на панелі запуску
    • натисніть на одне з вікон програми

Сценарій

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


Варіант 4: комбінація клавіш викликає список опцій, що показує кількість вікон для програми в поточному вікні перегляду

Цей виявився зручнішим, тоді я припустив:

Натискаючи (знову приклад-) комбінацію клавіш Alt+ 1викликає zenityвікно, перелічуючи всі програми та кількість їхніх вікон у поточному вікні перегляду:

введіть тут опис зображення

Просто натискання стрілок або стрілок приведе вас до потрібного варіанту. Натисніть Enterі всі вікна вибраної програми підняті.

Як користуватись:

  • Виконайте налаштування, як описано в "Як користуватися"
  • Перевірте його за допомогою команди:

    raise_app
    
  • Якщо все працює добре, додайте його до комбінації клавіш швидкого вибору за вибором: Виберіть: Налаштування системи> "Клавіатура"> "Ярлики"> "Спеціальні ярлики". Клацніть "+" і додайте команду

Сценарій

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



Варіант 5: підніміть вікна запущених програм із піктограми запуску

Ця опція існує піктограмою запуску, з поточно запущеними програмами у швидкому списку. Виберіть один, і всі вікна програм будуть підняті.

введіть тут опис зображення

Запуск автоматично оновлюється, коли список запущених програм (у поточному вікні перегляду) змінюється. Швидкий список показує інший список в інших областях перегляду, де відкриваються вікна інших програм (на адаптацію знадобиться 1-2 секунди).

Як вже було сказано, хоча цілком функціональні, цей варіант розуміється як концепція . Він має кілька незначних косметичних недоліків, як це є. Найбільш важливим:

  • Курсор "колесо" продовжує обертатися протягом декількох секунд після дії. Хоча це не впливає на функціональність, це косметичний мінус.
  • Після оновлення списку запущених додатків для оновлення списку додатків у значку запуску потрібно 1-2 секунди.

Крім того, налаштування трохи складніше (хоча це детально пояснено нижче):

Як користуватись

Нижче ви знайдете:

два сценарії / значок / .desktopфайл

  1. Підготуйте налаштування як у "Як користуватися", збережіть перший (основний) скрипт як raise_appу~/bin
  2. Збережіть піктограму нижче (клацніть правою кнопкою миші, збережіть як) як raise.png

    <icon>

  3. Скопіюйте .desktopфайл у порожній файл, відредагуйте рядок

        Icon=/path/to/raise.png
    

    до реального шляху до піктограми (шляхи з пробілами між цитатами)
    Збережіть її як raise.desktopв~/.local/share/applications

  4. Перетягніть .desktopфайл до панелі запуску, щоб додати його

  5. скопіюйте другий скрипт, вставте його в порожній файл, збережіть як update_appsу ~/bin, зробіть його виконуваним.
  6. Додайте таку команду до своїх програм запуску (тире> програми запуску> Додати):

    update_apps
    
  7. Вийдіть і поверніться, щоб він працював.

Перший сценарій

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

Другий сценарій

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

Файл .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=



Коротке пояснення

Усі рішення, описані вище, використовують wmctrlдля створення списку вікон за допомогою wmctrl -lpGкоманди. Ця команда створює рядки, виглядаючи так:

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

Ці рядки включають:

  • 1-й стовпець: ідентифікатор вікна (який ми можемо використовувати для його підвищення)
  • 3-й стовпець: pid, який володіє вікном.
  • 4-й / 5-й стовпець: геометрія вікна xy (яку ми використовуємо, щоб побачити, чи вікно знаходиться у поточному вікні перегляду, icw xrandr)

Pid шукається у висновку, ps -u <username>щоб отримати "читабельну для користувача" ідентифікацію (ім'я) програми.
Таким чином ми можемо виділити вікна для додатків. Згодом ми можемо піднімати вікна даної програми в forциклі за допомогою команди wmctrl -ia.

У варіанті 3
сценарій запускає 3-секундний цикл "очікування", використовуючи xprop -rootкоманду кілька разів, щоб побачити, чи є якась зміна в тому, що є переднім вікном; це станеться, якщо користувач або натисне піктограму запуску, щоб підняти вікно програми, або безпосередньо натисне на вікно. Якщо так, цикл while розбиває і шукає "новий" передній додаток, а згодом піднімає всі інші вікна цього додатка.


Я згоден, і ще раз дякую за всі ваші зусилля! :) || Є дивна річ, яку я раніше не помічав. Іноді після використання Option 2сценарію, коли вікно програми фокусується (це не максимально) і я натискаю на інше вікно, яке видно "внизу", додаток нижче не фокусується.
Джошуа

@Joschua ОП цього питання: askubuntu.com/questions/575830/… відвідав мене про помилку, яка була представлена ​​останнім оновленням "функції". True / False були змішані, що спричинило збій сценарію, коли жодна програма не має більше одного вікна. Якщо ви використовуєте option2, оновіть її до останньої версії.
Яків Влійм

Варіант 1 не працює для мене на ubuntu xenial. щось @ щось: ~ / bin $ ./raise_app Gtk-Повідомлення: GtkDialog відображається без перехідних батьків. Це відлякує. Я намагався відкрити вікна терміналів. Нічого не сталося.
xtrinch

@Nirri, яке ім'я програми ви використовували? Повідомлення є цілком нормальним, якщо вікно zenity працює без батьківського Gtk. "Охоплений" - це не помилка.
Яків Влійм

Перші символи терміналу. Він працює - начебто - він відкриває вікно будь-якої програми, але лише одного з них, не всіх, як очікувалося @ user72216
xtrinch

1

Є ярлик Super+, Wякий покаже експозицію всіх відкритих вікон, хоча це буде включати інші програми. Це відбувається за замовчуванням і не потребує змін, тому, можливо, це найпростіший варіант.

Крім усього іншого, ви можете розташувати вікна на правій та лівій половинах екрана за допомогою кнопок Ctrl+ Super+ Left/ Rightта переключитися між ними за допомогою Alt + ~ (tilde, той, що знаходиться поруч із клавішею номер один).


Це не приносить усі вікна програми на початок. Ви можете їх бачити, але ви не можете їх використовувати без того, щоб багато натискати.
Джошуа

1

Якщо ви натискаєте клавішу Alt + Tab, щоб переходити через програми, і ви потрапляєте на одне з кількома вікнами, просто продовжуйте утримувати клавішу alt, і приблизно через 1 повну секунду піктограма буде замінена, щоб переглянути всі вікна для цього додатка.

Це може бути або не бути тим, що ви шукаєте, але це працює для мене і є на тонну простішим, тому я зрозумів, що поділюсь цим варіантом!


1
Ви також можете натиснути клавішу зі стрілкою вниз, щоб вікна програми відображалися відразу.
Кріс

1

Я взяв сценарій підвищення_apps.py @ JacobVlijm і вніс деякі вдосконалення, зокрема зробив його більш надійним.

Зокрема, я виявив, що через день чи два сценарій @ JacobVlijm перестане працювати, і мені доведеться вручну перезапустити сценарій, щоб він знову працював. Зрештою, я найкраще здогадуюсь, що численні дзвінки до xrandr врешті-решт викликають проблеми.

У будь-якому випадку, я адаптував його код, збільшував частоту опитування з 5 секунд на кожну 1 секунду, оскільки він все одно не використовує багато процесора, і зробив його більш надійним. Я, як правило, без проблем працює протягом днів / тижнів.

Одним із застережень є те, що я закликаю xrandr лише один раз під час запуску, щоб отримати розміри роздільної здатності екрана. Отже, якщо ви зміните роздільну здатність екрана (наприклад, з 1920x1080 на якусь іншу роздільну здатність), ви, ймовірно, захочете вручну перезапустити файл підвищення-apps.py, щоб він підбирав нову роздільну здатність. Особисто я ніколи не змінюю роздільну здатність екрана, тому для мене це не проблема. Крім того, у мене є вагомі підстави вважати, що занадто багато дзвінків до xrandr були причиною того, що версія сценарію @ JacobVlijm припинила роботу через день-два, тому я настійно рекомендую не просто повертати численні дзвінки до xrandr ..

BTW, вам потрібно розмістити image.png в каталозі / usr / local / icons /. Або якщо ви хочете поставити на індекс каталог.dng в інший каталог, внесіть відповідні зміни до сценарію, щоб сценарій міг знайти файл зображення.

Сподіваємось, Ubuntu інтегрує цей тип функціональних можливостей "підняти всі вікна" в свою систему раніше, ніж пізніше, оскільки це дуже корисно:

#!/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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.