Запустіть додаток, лише якщо його ще не відкрито


16

Я хотів би імітувати використання Альфреда на Mac OS X, де, якщо ви спробуєте відкрити додаток після його пошуку, воно відкриє нове вікно, лише якщо програма ще не запущена, інакше встановить фокус на на даний момент запущений екземпляр цієї програми. Чи варто змінити поведінку пускача за замовчуванням, щоб перевірити це, перш ніж відкрити нове вікно?


Також @pidge Це зробити не буде складно, але це також вплине на поведінку правою кнопкою миші "відкрити". Я думаю, що це неприйнятний побічний ефект.
Яків Влійм

1
Я думаю, ви повинні мати можливість створити скрипт, який може перевірити, чи вже запущений конкретний процес, і вирішити, чи запускати новий процес, чи надавати фокус існуючому вікну. На жаль, я ще не дуже хороший у написанні сценаріїв ... Але @JacobVlijm відомий як хлопець зі сценаріями для будь-яких цілей;) Вам доведеться замінити всі оригінальні запуски відповідним сценарієм. Не впевнений, чи хочете ви / можете це зробити - я б не ...
Байт командир

2
Якщо ви рухаєтесь маршрутом сценарію, ви можете використовувати цей скрипт як вихідну точку. Я писав це для LXDE / Openbox спочатку, але він також повинен працювати в Unity. Більше інформації про сценарій та його використання тут .
Glutanimate

1
@ByteCommander саме так мав на увазі. Можна навіть сценарій - замінити команди у .desktopфайлах. Якщо замінити команду в .desktopфайлі , однак, права кнопка миші відкрити з варіантом зламаний.
Яків Влійм

1
Для якого робочого середовища?
j0h

Відповіді:


6

Оновлення 7 квітня: Додана інша версія та знайдено Альберта, дивіться оновлення та Бонус нижче !!!

Що стосується функцій тире : Ви запитали " Чи все-таки можна змінити поведінку запуску за замовчуванням, щоб перевірити це перед відкриттям нового вікна ". Основна відповідь - ні, як звичайний користувач, ви не можете додати цю поведінку до тире. Однак, якщо є розробник сфери єдності, який був би готовий реалізувати це, ви можете підійти до них або розробити його самостійно, якщо ви вирішите і хочете вчитися. Мої навички кодування дуже скромні, тому я використовую сценарій оболонки та наявний графічний фронт для сценаріїв як вирішення.

Супутня інформація

Оригінальна публікація:

Я написав сценарій, який використовує діалог із зенності та wmctrl для досягнення того, про що ви просили. Зауважте, що це графічний скрипт, тобто він працюватиме лише з windows, в графічному інтерфейсі, і він не працюватиме, якщо ви спробуєте запустити щось у tty. Крім того, з того, що я розумію, Альфред робить саме те саме. Ви можете створити ярлик на робочому столі до нього або ярлик запуску, як описано тут і тут .

Сценарій:

#!/bin/bash
# Author: Serg Kolo
# Description: A launcher script that checks whether
#       or not a window of a particular program already exists
#       If a window of such program is open, bring it to focus
#       Otherwise - launch a new window
#       Written for /ubuntu//q/440142/295286
# Date: April 6 , 2015
#


MYPROG=$( zenity --entry --title='MY LAUNCHER' --text='Type the name of application to run' )
sleep 0.5
wmctrl -lx | awk '{print $3}' | grep -i "$MYPROG"

if [ $? -eq 0 ]; then
    sleep 1         
    wmctrl -xa $MYPROG
   #as an alternative try the line bellow
   #wmctrl -a $MYPROG
    exit 1
else 
    $MYPROG &
    exit 0
fi

Бічні примітки: у попередній версії сценарій використовувався echo $ ?, щоб перевірити, чи попередні вирази успішно вийшли. Згідно з пропозицією Муру (з редагування), я змінив код на дещо більш компактну версію, тому пропоную вам переглянути попередню версію та поточну.

Також раніше wmctrl -a $MYPROGне працювали з тестуванням google-chrome або Chrome-браузера; з якоїсь дурної причини деякі програми мають властивість WM_CLASS вікна з великої літери, тоді як програма, зазначена у списку, dpkg --get-selectionsє малі регістри (просто читайте man wmctrlта запускайте wmctrl -lx, ви знаєте). Додаючи, що -ax повинен подбати про це. Сценарій відкриває вже відкрите вікно хрому, як слід

Інша річ - wmctlr дещо дивний у тому, що він потребує іноді затримки (мав досвід роботи з іншим сценарієм), тому мені довелося додати sleep 1рядок. Раніше це було б вимкненням та вимиканням Firefox, але зараз працює плавно.

Сценарій в дії

У нижній частині анімації ви бачите, що під час першого запуску сценарію відкривається один екземпляр firefox, і сценарій перемикає фокус на це вікно; у другому тесті я відкриваю новий екземпляр google-chrome, який раніше не був відкритий. (Бічна примітка. Якщо вам цікаво робочий стіл, до речі, це openbox з доступом до Каїру)

За пропозицією в коментарях вбудовану анімацію видалено, розміщено лише посилання. Повідомте, якщо це порушено, будь ласка! http://i.stack.imgur.com/puuPZ.gif

Оновлення, 7 квітня

Я дещо вдосконалив сценарій, щоб зробити всі програми, перелічені у спадному вікні zenity. Тепер користувачеві не потрібно запам'ятовувати кожну програму, а можна просто прокрутити їх список за допомогою клавіш зі стрілками або просто відкрити випадаюче меню. Крім того, ця покращена версія піднімає вікна не за назвою, а за ідентифікатором вікна, що дає значно кращі показники. Зауважте, що я проходжу файли .desktop - це щось надлишкове, використовуючи команду cut двічі, але оскільки мій скрипт-фу поки що не так добре, це все, що я можу зробити. Пропозиції щодо вдосконалення вітаються!

#!/bin/bash
# Author: Serg Kolo
# Description: Second version of a launcher script that checks whether
#       or not a window of a particular program already exists
#       If a window of such program is open, bring it to focus
#       Otherwise - launch a new window
#       Written for /ubuntu//q/440142/295286
# Date: April 7 , 2015
#

set -x

MYPROG=$(zenity --entry --text 'Select program from list' --entry-text $(ls /usr/share/applications/*.desktop | cut -d'/' -f5 | cut -d'.' -f1 | xargs echo))
sleep 0.5
# Do we have a window of such program ?
wmctrl -lx| awk '{print $3}'  | grep -i $MYPROG

if [ $? -eq 0 ]; then
    sleep 0.5 # if yes, find that window id, and raise it
    WINID=$(wmctrl -lx | grep -i $MYPROG | awk 'NR==1{print $1}')
    wmctrl -ia $WINID &
 #  exit 0  
else
    echo $MYPROG | grep -i libreoffice
    if [ $? -eq 0  ]
    then
        MYPROG=$(echo $MYPROG | sed 's/-/ --/g')
    fi
    $MYPROG &

#  exit 0 
fi

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

Бонус:

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

Існує додаток під назвою Gnome-Do, який графічно схожий на Альфреда, однак він не має такої ж функціональності, як цей сценарій.

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

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


До речі, зауважте, як я набираю назви програм - саме так, як зазначено в dpkg --get-selectons. Запустіть програму свободного введення, ввівши "письменницьку" звичайну роботу, але ви можете зробити посилання на неї у папці ~ / bin, / bin або / usr / bin або використовувати псевдонім у .bashrc або .profile.
Сергій Колодяжний

Зауважте також, що вам знадобиться встановити wmctl, він не за замовчуванням, але досить зручний. Я також використав його , щоб зробити це
Sergiy Kolodyazhnyy

Чи можете ви замінити анімацію зображенням, посилаючись на анімацію? Мій браузер продовжує "завантажувати" сторінку, тому я не можу її оновити. (а анімація не запускається :))
Яків Влійм

Спасибі! Посилання добре працює в Chrome, а не в Firefox.
Яків Влійм

@JacobVlijm Цьфу, так це і робиться. Не впевнений, чому Firefox відмовляється відтворювати його. Це просто незрозуміле посилання на те, що я спочатку завантажив
Сергій Колодяжний

5

1. Тире Друге

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

Існує вікно з тим же функціоналом, що і Dash; якщо введіть один або кілька символів програми, програма з’явиться у списку. Натисніть, Enterщоб запустити або підняти програму, залежно від того, вона вже запущена чи ні.

Ви можете зателефонувати за нею із комбінації клавіш швидкого доступу або встановити піктограму в панелі запуску, щоб використовувати її аналогічно тире (див. Далі нижче) або обом.

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

Сценарій

#!/usr/bin/env python3
import subprocess
import os
import getpass
import time

user = getpass.getuser()
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
skip = ["%F", "%U", "%f", "%u"]; trim = ["chrome", "chromium", "nautilus"]

def apply(command):
    if "libreoffice" in command:
        proc = [l.split()[0] for l in get("ps -u "+user).splitlines() if "soffice.bin" in l]
        module = command.split("--")[-1]
        time.sleep(0.1)
        try:
            ws = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if process in w and module in w.lower()] for process in proc], [])[0]
            subprocess.call(["wmctrl", "-ia", ws])
        except IndexError:
            subprocess.Popen(["/bin/bash", "-c", command+"&"])
    else:
        check = command.split("/")[-1][:14]
        proc = [p.split()[0] for p in get("ps -u "+user).splitlines() if check in p]
        time.sleep(0.5)
        try:
            ws = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if process in w] for process in proc], [])
            if command == "nautilus":
                real_window = [w for w in ws if "_NET_WM_WINDOW_TYPE_NORMAL" in get("xprop -id "+w)][0]
            else:
                real_window = ws[0]
            subprocess.call(["wmctrl", "-ia", real_window])
        except IndexError:
            subprocess.Popen(["/bin/bash", "-c", command+"&"])
# default directories of .desktop files; globally, locally, LibreOffice- specific when separately installed
globally = "/usr/share/applications"; locally = os.environ["HOME"]+"/.local/share/applications"; lo_dir = "/opt/libreoffice4.4/share/xdg"
# create list of .desktop files; local ones have preference
local_files = [it for it in os.listdir(locally) if it.endswith(".desktop")]
global_files = [it for it in os.listdir(globally) if it.endswith(".desktop")]
lo_spec = [it for it in os.listdir(lo_dir) if it.endswith(".desktop")] if os.path.exists(lo_dir) else []
for f in [f for f in local_files if f in global_files]:
    global_files.remove(f)
for f in [f for f in local_files if f in lo_spec]:
    lo_spec.remove(f)
dtfiles = [globally+"/"+f for f in global_files]+[locally+"/"+f for f in local_files]+[lo_dir+"/"+f for f in lo_spec]
# create list of application names / commands
valid = []
for f in dtfiles:
    content = open(f).read()
    if all(["NoDisplay=true" not in content,"Exec=" in content]):
        lines = content.splitlines()
        name = [l.replace("Name=", "") for l in lines if "Name=" in l][0]
        command = [l.replace("Exec=", "") for l in lines if all(["Exec=" in l, not "TryExec=" in l])][0]
        valid.append((name, command))
valid.sort(key=lambda x: x[0])
# create zenity list + window
list_items = '"'+'" "'.join([f[0] for f in valid])+'"'
proposed = 'zenity --list --text "Type one or more characters... " --column="Application List" '+\
           '--title="Dash the Second" --height 450 --width 300 '+list_items
try:
    choice = subprocess.check_output(["/bin/bash", "-c", proposed]).decode("utf-8").strip().split("|")[0]
    command = [r[1] for r in valid if r[0] == choice][0]
    # command fixes:
    for s in skip:
        command = command.replace(" "+s, "")
    for t in trim:
        if t in command:
            command = t
    apply(command)
except subprocess.CalledProcessError:
    pass

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

Сценарій потрібно wmctrlвстановити:

sudo apt-get install wmctrl

Потім:

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

    python3 /path/to/dash_alternative.py
    

Пояснення

Коли сценарій запускається, у ньому перераховані всі програми, представлені в /usr/share/applications. Він здійснює пошук .dektopфайлів, створюючи список усіх назв додатків (з першого рядка "Ім'я =") та команду для запуску програми (з першого рядка "Exec =").

Згодом створюється список Zenity, який представляє всі програми впорядкованому порядку.

Щоразу, коли вибрано додаток, сценарій відображається у списку запущених процесів, якщо програма запущена. Якщо так, відповідне вікно піднімається. Якщо ні, відкривається новий примірник.

Примітки

  1. Для запуску сценарію 12.04 (оскільки початкове запитання було позначене 12.04просто змініть shebang на #!/usr/bin/env pythonта запустіть його командою

    python /path/to/dash_alternative.py
    
  2. Наскільки я тестував це, сценарій працює чудово. Команди та їх (не) відповідні назви процесів (наприклад, LibreOffice<> soffice.bin), різні типи вікон ( nautilusмає кілька різних типів вікон, окрім "справжніх" вікон), кілька підказок на додаток ( Chromium, Google-chrome) можуть спричинити винятки, які я зафіксував у прикладах вище. Якщо хтось стикається з проблемою, будь ласка, зазначте її.

2. Додатково: встановлення його як альтернативи "справжньому" тире для запущених програм

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

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

  3. Скопіюйте код нижче в порожній файл, збережіть його ~/.local/share/applicationsяк dash_thesecond.desktop. Встановіть правильні шляхи для /path/to/dash_alternative.py(сценарій) та /path/to/dash_alternative.png(значок)

    [Desktop Entry]
    Name=Dash the Second
    Exec=python3 /path/to/dash_alternative.py
    Icon=/path/to/dash_alternative.png
    Type=Application
    Hidden=false
    
  4. Перетягніть .desktopфайл на панель запуску:


1
Приємно знати, що є ціла папка файлів .desktop! Мені було цікаво, як місцеві програми, встановлені apt, перераховуються по імені замість команд. Гарної роботи там!
Сергій Колодяжний

@ Сергій Дякую! і те саме вам :). Існує також локальний каталог для .desktopфайлів: ~/.local/share/applications. Я думав, що обмежу пошук глобально встановлених програм.
Яків Влійм

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

@ Сергій Дякую! це цікава публікація, безумовно, добре погляньте на неї!
Яків Влійм

0

Для запуску (вертикальна панель зліва на екрані) це вже поведінка за замовчуванням, оскільки це інтерфейс перемикання задач.

Для тире (великий біт, який відкривається при натисканні на логотип Ubuntu), неможливо змінити поведінку таким чином, без імовірно значної модифікації самого вихідного коду.

Деякі програми, однак, вже можуть це зробити, оскільки вони розроблені таким чином. Однак усі додатки не повинні і не повинні бути реалізовані таким чином.

Як ще одна функція, якщо ви відкриєте вікно, розповсюджене знаком Super+ W, і почнете вводити ім'я програми, вікна для цього додатка будуть єдиними показаними.


Я фактично знайшов версію Linux того, чого хотів ОП, дивіться свій пост, розділ про бонуси. Мабуть, у когось іншого виникла ідея привезти Альфреда до Linux
Сергій Колодяжний

1
@Serg, будь ласка, спробуй Альберта; У Альберта все ще є "помилка LibreOffice", "помилка Chromium" та "помилка Chrome". Навіть "помилка файлів" ... Альберт завжди завжди відкриває новий екземпляр цих програм. LibreOffice просто не працює взагалі. Також у коментарях під вашим посиланням ви можете знайти ряд питань.
Яків Влійм

@Serg Ні, ви знайшли вирішення, додавши додатковий фрагмент програмного забезпечення, що працює у фоновому режимі, що забезпечує зовсім інший досвід користувача та вимагає перенавчання, як шукати програми. Питання, що задається, було, як зробити цю роботу в тирі Єдності. Можливо, ви зможете отримати подібну функцію за межами самого Unity, але єдиний спосіб змінити Unity для цього - змінити вихідний код.
dobey

@dobey Ну, це правда; зміна функцій тире поза межами нашого досяжності, тому. . .Гота робити з тим, що у нас є вільний, правда? Якщо тільки не існує розробника, який буде готовий кодувати область об'єднання з такою функціональністю. . .
Сергій Колодяжний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.