У меня есть приложение с помощью нескольких окон. Как я могу быстро принести все окна того приложения к переднему плану?
Когда я просматриваю приложения путем прокрутки с колесиком прокрутки, оно только показывает одно окно. При движении в следующее окно последнее окно принесено к фону снова.
Когда я нажимаю на значок приложения, я получаю полноэкранный обзор всех окон. Я должен выбрать каждое окно вручную и переместить мою мышь через половину экрана несколько раз.
Мое лучшее решение до сих пор минимизирует все окна (Ctrl+Super+D), и затем покажите окна моего приложения с помощью колесика прокрутки.
Существует ли лучшее решение?
Ответ (ответы) ниже все еще полностью действителен, и таким образом, предложенные опции. Продолжающееся понимание однако заставило меня добавить эту опцию использовать индикатор ниже, который является, вероятно, самым изящным решением.
По сути, это должно, вероятно, заменить опцию 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
и сделайте это исполняемым файлом
В отдельных опциях будут объяснены возможные дополнительные шаги.
zenity
окно появитсяЭто сделает все окна приложения соответствия (на текущей области просмотра), прибывают в переднюю сторону.
повысьте все 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
Скажем, у меня есть сценарий ниже под сочетанием клавиш Alt+1. У меня есть несколько окон, открытых из:
Текущее состояние:
Я нажимаю однажды 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
Это - вероятно, опция, которая является самой близкой к тому, что описано в вопросе / комментарий.
Скажем, у меня есть грязный рабочий стол с три nautilus
окна прокладываются под землей под другими окнами.
Повысить все окна наутилуса (ярлык в качестве примера: 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
Этот оказался более удобным затем, я принял:
При нажатии (снова пример-) сочетание клавиш Alt+1 называет a 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"')
Эта опция существует значка средства запуска с в настоящее время запущенными приложениями в quicklist. Выберите один, и все окна приложений будут повышены.
Средство запуска автоматически обновляется, когда список запущенных приложений (на текущей области просмотра) изменяется. quicklist показывает другой список на других областях просмотра, где окна других приложений открыты (займет 1-2 секунды для адаптации).
Как упомянуто, хотя полностью функциональный, эта опция является предназначенным как понятием. Это имеет несколько незначительных косметических оборотных сторон как есть. Самое важное:
Кроме того, установка немного более сложна (хотя объяснено подробно ниже):
Как использовать
Ниже Вас найдет:
два сценария / значок / a .desktop
файл
raise_app
в ~/bin
Сохраните значок ниже (щелкните правой кнопкой, сохраните как), как raise.png
Скопируйте .desktop
файл в пустой файл, отредактируйте строку
Icon=/path/to/raise.png
к реальному пути к значку (соединяет каналом с пробелами между кавычками),
Сохраните его как raise.desktop
в ~/.local/share/applications
Перетащите .desktop
файл к средству запуска для добавления его
update_apps
в ~/bin
, сделайте это исполняемым файлом.Добавьте следующую команду к своим приложениям запуска (Тире>, Приложения Запуска> Добавляют):
update_apps
Первый сценарий
#!/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
Эти строки включают:
xrandr
)Pid ищется в выводе ps -u <username>
получить "читаемую пользователем" идентификацию (название) приложения.
Таким образом мы можем выделить окна приложениям. Впоследствии мы можем повысить окна данного приложения в a for
цикл с командой wmctrl -ia
.
В опции 3
сценарий запускает 3-вторых циклов "ожидания", с помощью xprop -root
управляйте неоднократно, чтобы видеть, существует ли какое-либо изменение в том, что является frontmost окном; это произойдет, если пользователь или нажмет на значок средства запуска для повышения окна приложения или нажмет на окно непосредственно. Если так, цикл с условием продолжения повреждается и ищет "новое" frontmost приложение и впоследствии повышает все другие окна того приложения.
Если Вы нажимаете Alt+Tab для циклического повторения через приложения, и Вы добираетесь до одного с несколькими окнами, просто продолжаете удерживать клавишу Alt и приблизительно после 1 целой секунды, значок будет заменен в целях всех окон для того приложения.
, Который может или не может быть тем, что Вы ищете, но это работает на меня и является более простой тонной, таким образом, я полагал, что совместно использую опцию!
Существует , Супер + W ярлык, который покажет экспо всех в настоящее время открытых окон, хотя это будет включать другие приложения. Это прибывает по умолчанию и не требует никаких изменений, поэтому возможно, это - самая простая доступная опция.
Среди прочего, Вы могли расположить окна на правые и левые половины экрана с Ctrl + Супер + Левый / кнопки Right и переключиться между ними с Высоким звуком + ~ (тильда, та рядом с ключом номер один).
Я взял raise_apps.py сценарий @JacobVlijm и сделал некоторые улучшения к нему, включая создание его более устойчивыми.
А именно, я нашел, что после дня или два, сценарий @JacobVlijm прекратит работать, и я должен был бы вручную перезапустить сценарий, для получения его работающий снова. Ретроспективно, мое лучшее предположение - то, что многочисленные вызовы к xrandr в конечном счете вызывают проблемы.
Так или иначе я адаптировал его код, увеличил частоту запросов с 5 секунд до каждой 1 секунды, поскольку это не использует много ЦП так или иначе и сделало это более устойчивым. У меня может обычно быть он работающий в течение дней/недели без проблем.
Один протест состоит в том, что я только называю xrandr однажды во время запуска, для получения размеров разрешения экрана. Таким образом, при изменении разрешения экрана (например, от 1920x1080 до некоторого другого разрешения), Вы, вероятно, захотите вручную перезапустить повышение-apps.py так, чтобы оно взяло новое разрешение. Лично, я никогда не изменяю свое разрешение экрана, таким образом, это - надуманный вопрос для меня. Кроме того, у меня есть веская причина полагать, что слишком много вызовов к xrandr были тем, что заставляло версию @JacobVlijm сценария прекращать работать после дня или два, таким образом, я настоятельно рекомендую не просто поместить многочисленные вызовы в xrandr, въезжают задним ходом..
BTW, необходимо поместить изображение raise.png в/usr/local/icons/каталог. Или если Вы хотите поместить raise.png в другой каталог, вносят соответствующее изменение в сценарий, так, чтобы сценарий мог найти файл изображения.
Хотелось бы надеяться, Ubuntu интегрирует этот тип 'повышения все окна' функциональность в их систему раньше, чем позже, поскольку это очень полезно:
#!/usr/bin/python2
#
# Note to self:
# You need to add raise.png to /usr/local/icons/ directory.
#
# This script was taken from: https://askubuntu.com/questions/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()