편집-새로운 답변-
아래의 답변은 여전히 유효하며 제안 된 옵션입니다. 그러나 지속적인 통찰력으로 인해 아래 표시기를 사용하기 위해이 옵션을 추가했습니다.
따라서 옵션 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
창이 나타납니다
- 입력 상자에 응용 프로그램 이름의 문자를 하나 이상 입력하십시오
- 엔터 키를 치시오
이렇게하면 일치하는 응용 프로그램의 모든 창 ( 현재 뷰포트)이 맨 앞에 오게됩니다.
gnome-terminal
현재 뷰포트에서 모든 창을 올리십시오 .
사용하는 방법:
스크립트 :
#!/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. 여러 개의 창이 열려 있습니다.
현재 상태 :
Alt+ 를 한 번 누르면 1모든 nautilus
창이 나타납니다.
다시 Alt+를 누르면 1모든 firefox
창이 나타납니다.
다시 Alt+를 누르면 1모든 gnome-terminal
창이 다시 올라가고 사이클이 다시 시작됩니다.
사용하는 방법
그런 다음 키 조합을 사용하여 그룹화 된 애플리케이션 창으로 애플리케이션을 순환하십시오.
스크립트 :
#!/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
다른 창 아래에 세 개의 창이 묻힌 지저분한 바탕 화면이 있다고 가정 해 봅시다 .
모든 노틸러스 창을 올리려면 (예 : 바로 가기 : Alt+ 1) :
사용하는 방법:
그때:
키 조합을 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선택한 응용 프로그램의 모든 창이 나타납니다.
사용하는 방법:
스크립트
#!/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
파일
- "사용 방법"에서와 같이 설정을 준비하고 다음과 같이 첫 번째 (main-) 스크립트를 저장하십시오
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
이 라인에는 다음이 포함됩니다.
- 첫 번째 열 : 창의 ID (키를 올리는 데 사용할 수 있음)
- 세 번째 열 : 창을 소유 한 pid
- 4/5 번째 열 : 창의 형상 xy (창이 현재 뷰포트에 있는지 확인하는 데 사용되는 icw
xrandr
)
pid는 ps -u <username>
응용 프로그램의 "사용자가 읽을 수있는"식별 (이름)을 얻기 위해 출력에서 조회됩니다 .
따라서 응용 프로그램에 창을 할당 할 수 있습니다. 결과적으로 for
명령 을 사용하여 주어진 응용 프로그램의 창을 루프로 올릴 수 있습니다 wmctrl -ia
.
옵션 3
에서 스크립트는 xprop -root
명령을 반복적으로 사용하여 가장 앞쪽 창에 어떤 변화가 있는지 확인 하기 위해 3 초 "대기"루프를 시작합니다 . 사용자가 실행기 아이콘을 클릭하여 응용 프로그램 창을 올리거나 창을 직접 클릭하면 이런 일이 발생합니다. 그렇다면 while 루프는 "최신"최전방 응용 프로그램을 중단하고 찾은 다음 해당 응용 프로그램의 다른 모든 창을 엽니 다.