EDIT - mới trả lời-
Câu trả lời dưới đây là / vẫn hoàn toàn hợp lệ và do đó, các tùy chọn được đề xuất. Tuy nhiên, cái nhìn sâu sắc đang diễn ra khiến tôi thêm tùy chọn này để sử dụng chỉ báo bên dưới, đây có lẽ là giải pháp thanh lịch nhất.
Như vậy, có lẽ nên thay thế tùy chọn 5 (sử dụng tệp .desktop).
Chỉ cần chọn ứng dụng từ danh sách và tất cả các cửa sổ của ứng dụng tương ứng (hiện trên chế độ xem hiện tại) sẽ nâng lên:
Cách sử dụng
từ ppa:
sudo add-apt-repository ppa:vlijm/upfront
sudo apt-get update
sudo apt-get install upfront
... hoặc thủ công:
#!/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()
Các chỉ số cần wmctrl
sudo apt-get wmctrl
Sao chép chỉ báo vào một tệp trống, lưu nó dưới dạng raise_apps.py
Sao chép hình ảnh bên dưới, lưu tên chính xác raise.png
trong một và cùng thư mục với chỉ báo.
Sau đó, chỉ cần chạy nó bằng lệnh:
python3 /path/to/raise_apps.py
Thêm nếu bạn muốn vào Ứng dụng khởi động:
/bin/bash -c "sleep 10 && python3 /path/to/raise_apps.py"
TRẢ LỜI:
Về câu hỏi
Với các công cụ phù hợp, việc "chỉ" nâng tất cả các cửa sổ của một ứng dụng không quá phức tạp. Nó chỉ phức tạp hơn một chút để đảm bảo chỉ các cửa sổ của chế độ xem hiện tại được nâng lên. Tuy nhiên, thách thức thực sự là tìm ra một cách thuận tiện để thực hiện hành động có sẵn cho người dùng.
Dưới năm tùy chọn để chăm sóc điều đó, để cho thấy làm thế nào nó có thể được thực hiện. Tất cả các tùy chọn đã sẵn sàng để được sử dụng. Tuy nhiên, tùy chọn cuối cùng là loại thử nghiệm; Nó hoạt động tốt nhưng có một vài nhược điểm nhỏ về mỹ phẩm, như được giải thích trong mô tả của tùy chọn. Tôi đã thêm nó tuy nhiên như là một khái niệm .
Tự động trải các cửa sổ theo cách không chồng chéo, như được đề xuất trong một nhận xét, dường như không phải là một ý tưởng thực tế đối với tôi; nếu bạn làm việc trong một thiết lập cửa sổ được nhóm (ứng dụng khôn ngoan), tập lệnh có thể sắp xếp lại các cửa sổ không mong muốn.
Cách sử dụng
Đối với tất cả các tùy chọn bạn cần phải:
cài đặt wmctrl
nếu nó chưa có trên hệ thống của bạn:
sudo apt-get install wmctrl
tạo, nếu nó chưa tồn tại, thư mục:
~/bin
(giải thích: thư mục ~/bin
nằm trong $ PATH, vì vậy bạn có thể chạy các tệp thực thi theo tên của họ)
Sao chép tập lệnh, tương ứng với tùy chọn, dán nó vào một tệp trống, lưu nó dưới dạng raise_app
(không có phần mở rộng) ~/bin
và làm cho nó có thể thực thi được
Trong các tùy chọn riêng biệt, các bước bổ sung có thể sẽ được giải thích.
Tùy chọn 1: chọn ứng dụng bằng cách nhập một hoặc nhiều ký tự
- Nhấn tổ hợp phím, một
zenity
cửa sổ sẽ xuất hiện
- Nhập một hoặc nhiều ký tự của tên ứng dụng vào hộp nhập
- Nhấn nút Enter
Điều này sẽ làm cho tất cả các cửa sổ của ứng dụng phù hợp (trên chế độ xem hiện tại ) xuất hiện phía trước.
nâng tất cả các gnome-terminal
cửa sổ trên khung nhìn hiện tại:
Cách sử dụng:
Kịch bản:
#!/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
Tùy chọn 2: quay vòng qua các ứng dụng và nâng cao cửa sổ của chúng bằng tổ hợp phím:
Giả sử tôi có đoạn script bên dưới theo tổ hợp phím Alt+ 1. Tôi có một số cửa sổ mở của:
- lửa
- thiết bị đầu cuối gnome
- nautilus
Trạng thái hiện tại:
Tôi nhấn một lần Alt+ 1, tất cả các nautilus
cửa sổ được nâng lên:
Tôi nhấn lại Alt+ 1, tất cả các firefox
cửa sổ được nâng lên:
Tôi nhấn lại Alt+ 1, tất cả các gnome-terminal
cửa sổ được nâng lên một lần nữa, chu kỳ bắt đầu lại:
Cách sử dụng
Sau đó chuyển qua các ứng dụng của bạn với các cửa sổ ứng dụng được nhóm với tổ hợp phím của bạn.
Kịch bản:
#!/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
Tùy chọn 3: nhấn tổ hợp phím + nhấp vào biểu tượng trình khởi chạy -hoặc cửa sổ ứng dụng để nâng tất cả các cửa sổ trên chế độ xem hiện tại
Đây có lẽ là tùy chọn gần nhất với những gì được mô tả trong câu hỏi / nhận xét.
Giả sử tôi có một máy tính để bàn lộn xộn với ba nautilus
cửa sổ bị chôn vùi dưới các cửa sổ khác.
Để nâng tất cả các cửa sổ nautilus (phím tắt ví dụ: Alt+ 1):
- Nhấn Alt+ 1, phát hành (!)
Trong vòng 3 giây, một trong hai:
nhấp vào biểu tượng của ứng dụng trong trình khởi chạy
hoặc là:
bấm vào một trong các cửa sổ của ứng dụng
kết quả:
Cách sử dụng:
Sau đó:
Kịch bản
#!/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
Tùy chọn 4: tổ hợp phím gọi danh sách tùy chọn, hiển thị số lượng cửa sổ cho mỗi ứng dụng trên chế độ xem hiện tại
Điều này hóa ra là thuận tiện hơn sau đó tôi giả sử:
Nhấn tổ hợp phím (một lần nữa-) Alt+ 1gọi một zenity
cửa sổ, liệt kê tất cả các ứng dụng và số lượng cửa sổ của chúng trên chế độ xem hiện tại:
Chỉ cần nhấn ▴hoặc ▾mũi tên sẽ đưa bạn đến tùy chọn đúng. Nhấn Entervà tất cả các cửa sổ của ứng dụng đã chọn được nâng lên.
Cách sử dụng:
Kịch bản
#!/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"')
Tùy chọn 5: nâng cửa sổ của các ứng dụng đang chạy từ biểu tượng trình khởi chạy
Tùy chọn này tồn tại biểu tượng trình khởi chạy, với các ứng dụng hiện đang chạy trong danh sách nhanh. Chọn một và tất cả các cửa sổ của ứng dụng sẽ được nâng lên.
Trình khởi chạy được tự động cập nhật khi danh sách các ứng dụng đang chạy (trên chế độ xem hiện tại) thay đổi. Danh sách nhanh hiển thị một danh sách khác trên các chế độ xem khác, nơi các cửa sổ của các ứng dụng khác được mở (sẽ mất 1-2 giây để thích ứng).
Như đã đề cập, mặc dù đầy đủ chức năng, tùy chọn này có nghĩa là một khái niệm . Nó có một vài nhược điểm nhỏ như nó là. Điều quan trọng nhất:
- Con trỏ "bánh xe" tiếp tục quay trong vài giây sau khi hành động. Mặc dù nó không ảnh hưởng đến chức năng, nhưng nó là một nhược điểm của mỹ phẩm.
- Phải mất 1-2 giây để danh sách ứng dụng trong biểu tượng trình khởi chạy được cập nhật sau khi danh sách các ứng dụng đang chạy thay đổi.
Hơn nữa, thiết lập phức tạp hơn một chút (mặc dù được giải thích chi tiết bên dưới):
Cách sử dụng
Dưới đây bạn sẽ tìm thấy:
hai tập lệnh / một biểu tượng / một .desktop
tập tin
- Chuẩn bị thiết lập như trong "Cách sử dụng", lưu tập lệnh (chính-) đầu tiên như
raise_app
trong~/bin
Lưu biểu tượng bên dưới (nhấp chuột phải, lưu dưới dạng) dưới dạng raise.png
Sao chép .desktop
tập tin vào một tập tin trống, chỉnh sửa dòng
Icon=/path/to/raise.png
đến đường dẫn thực sự đến biểu tượng (đường dẫn có khoảng trắng giữa các dấu ngoặc kép)
Lưu nó như raise.desktop
trong~/.local/share/applications
Kéo .desktop
tệp vào trình khởi chạy để thêm nó
- sao chép tập lệnh thứ hai, dán nó vào một tập tin trống, lưu nó như
update_apps
trong ~/bin
, làm cho nó thực thi được.
Thêm lệnh sau vào các ứng dụng khởi động của bạn (Dash> Ứng dụng khởi động> Thêm):
update_apps
- Đăng xuất và trở lại để làm cho nó hoạt động.
Kịch bản đầu tiên
#!/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
Kịch bản thứ hai
#!/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)
Tệp .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=
Giải thích ngắn gọn
Tất cả các giải pháp trên sử dụng wmctrl
để tạo một danh sách cửa sổ, sử dụng wmctrl -lpG
lệnh. Lệnh này tạo ra các dòng, trông giống như:
0x044000b3 0 3429 65 24 1615 1026 jacob-System-Product-Name unity - How to show all windows of an application? - Ask Ubuntu - Mozilla Firefox
Những dòng này bao gồm:
- Cột thứ nhất: id của cửa sổ (mà chúng ta có thể sử dụng để nâng cao nó)
- Cột thứ 3: pid sở hữu cửa sổ.
- Cột thứ 4/5: hình học xy của cửa sổ (mà chúng ta sử dụng để xem cửa sổ có ở chế độ xem hiện tại không, icw
xrandr
)
Các pid được tra cứu trong đầu ra ps -u <username>
để có được một nhận dạng (tên) người dùng có thể đọc được của ứng dụng.
Do đó chúng ta có thể phân bổ các cửa sổ cho các ứng dụng. Sau đó, chúng ta có thể nâng các cửa sổ của một ứng dụng nhất định trong một for
vòng lặp bằng lệnhwmctrl -ia
.
Trong tùy chọn 3
, tập lệnh bắt đầu một vòng lặp "chờ" 3 giây, sử dụng xprop -root
lệnh liên tục để xem liệu có bất kỳ thay đổi nào trong cửa sổ ngoài cùng không; điều này sẽ xảy ra nếu người dùng nhấp vào biểu tượng trình khởi chạy để nâng cửa sổ của ứng dụng hoặc nhấp trực tiếp vào cửa sổ. Nếu vậy, vòng lặp while sẽ phá vỡ và tìm kiếm ứng dụng ngoài cùng "mới" và sau đó tăng tất cả các cửa sổ khác của ứng dụng đó.