Làm thế nào để hiển thị (nâng) tất cả các cửa sổ của một ứng dụng?


21

Tôi có một ứng dụng sử dụng nhiều cửa sổ. Làm thế nào tôi có thể nhanh chóng đưa tất cả các cửa sổ của ứng dụng đó lên nền trước?

Khi tôi cuộn qua các ứng dụng bằng bánh xe cuộn, nó chỉ hiển thị một cửa sổ. Khi đi đến cửa sổ tiếp theo, cửa sổ cuối cùng được đưa trở lại nền.

Khi tôi nhấp vào biểu tượng ứng dụng, tôi có được tổng quan toàn màn hình của tất cả các cửa sổ. Tôi phải chọn từng cửa sổ một cách thủ công và di chuyển chuột trên một nửa màn hình nhiều lần.

Giải pháp tốt nhất của tôi cho đến nay là thu nhỏ tất cả các cửa sổ ( Ctrl+ Super+ D) và sau đó hiển thị các cửa sổ của ứng dụng của tôi bằng cách sử dụng bánh xe cuộn.

Có một giải pháp tốt hơn?


@Joschua Đưa tất cả các cửa sổ của một ứng dụng lên phía trước không quá khó, nhưng bạn muốn xác định ứng dụng như thế nào? một tổ hợp phím + nhấp vào cửa sổ của ứng dụng sẽ làm gì?
Jacob Vlijm

@Joschua hoặc mayby ​​thanh lịch hơn, một combo chính + ký tự đầu tiên của tên ứng dụng?
Jacob Vlijm

Tôi nghĩ rằng hành vi ist giống nhau với tất cả các ứng dụng. Tôi thường bỏ lỡ tính năng này với các cửa sổ đầu cuối, nơi tôi thường có hai hoặc nhiều cửa sổ mở cạnh nhau. Sau đó, tôi chuyển sang một cửa sổ toàn màn hình (ví dụ Firefox) và khi tôi muốn chuyển trở lại hai cửa sổ đầu cuối thì thật khó khăn. Cách tốt nhất mà tôi tìm thấy cho đến nay là nhấp chuột vào thanh ứng dụng Firefox để đưa Firefox xuống nền để tôi có hai thiết bị đầu cuối ở phía trước. Tuy nhiên, điều này chỉ hoạt động tốt, khi không có quá nhiều ứng dụng được xếp chồng lên nhau: D
peq

Ngoài ra @Joschua Có thể có một tổ hợp phím để đưa đến các nhóm cửa sổ ứng dụng phía trước ; nhấn một lần -> tất cả các cửa sổ firefox hiển thị, đặt lại -> tất cả các cửa sổ đầu cuối hiển thị, vv có thể được thực hiện trơn tru. hấp dẫn. làm việc trên đó. sẽ mất một chút công việc mặc dù.
Jacob Vlijm

@JacobVlijm Nghe có vẻ đúng hướng .. :) Điều có vẻ quan trọng nhất đối với tôi, đó là một tổ hợp phím cộng với nhấp vào biểu tượng mang tất cả các cửa sổ của ứng dụng đó (ví dụ: nhiều thiết bị đầu cuối như peq đã đề cập) ở phía trước ra ngoài, để chúng không chồng chéo .. (Có lẽ, thứ gì đó như thế này có thể trở thành một phần của Unity?!)
Joschua

Câu trả lời:


21

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:

nhập mô tả hình ảnh ở đây

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.

    nhập mô tả hình ảnh ở đây

  • 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 wmctrlnế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 ~/binnằ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) ~/binvà 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-terminalcửa sổ trên khung nhìn hiện tại:

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Cách sử dụng:

  • Thực hiện cài đặt như được mô tả trong "Cách sử dụng"
  • Chạy thử nó bằng lệnh:

    raise_app
    
  • Nếu tất cả đều hoạt động tốt, hãy thêm nó vào tổ hợp phím tắt mà bạn chọn: Chọn: Cài đặt hệ thống> "Bàn phím"> "Phím tắt"> "Phím tắt tùy chỉnh". Nhấp vào "+" và thêm lệnh

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:

nhập mô tả hình ảnh ở đây

Tôi nhấn một lần Alt+ 1, tất cả các nautiluscửa sổ được nâng lên:

<hình ảnh>

Tôi nhấn lại Alt+ 1, tất cả các firefoxcửa sổ được nâng lên:

<hình ảnh>

Tôi nhấn lại Alt+ 1, tất cả các gnome-terminalcửa sổ được nâng lên một lần nữa, chu kỳ bắt đầu lại:

<hình ảnh>

Cách sử dụng

  • Thực hiện cài đặt như được mô tả trong "Cách sử dụng"
  • Thêm nó vào tổ hợp phím tắt mà bạn chọn: Chọn: Cài đặt hệ thống> "Bàn phím"> "Phím tắt"> "Phím tắt tùy chỉnh". Nhấp vào "+" và thêm lệnh

    raise_app
    

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 nautiluscửa sổ bị chôn vùi dưới các cửa sổ khác.

<hình ảnh>

Để 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

    <hình ảnh>

    hoặc là:

    bấm vào một trong các cửa sổ của ứng dụng

    <hình ảnh>

    kết quả:

    <hình ảnh>


Cách sử dụng:

  • Thực hiện cài đặt như được mô tả trong "Cách sử dụng"
  • Chạy thử nó bằng lệnh:

    raise_app
    
  • Nếu tất cả đều hoạt động tốt, hãy thêm nó vào tổ hợp phím tắt mà bạn chọn: Chọn: Cài đặt hệ thống> "Bàn phím"> "Phím tắt"> "Phím tắt tùy chỉnh". Nhấp vào "+" và thêm lệnh

Sau đó:

  • Nhấn tổ hợp phím của bạn và trong vòng 3 giây:

    • nhấp vào biểu tượng của ứng dụng trong trình khởi chạy
    • bấm vào một trong các cửa sổ của ứng dụng

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 zenitycử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:

nhập mô tả hình ảnh ở đây

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:

  • Thực hiện cài đặt như được mô tả trong "Cách sử dụng"
  • Chạy thử nó bằng lệnh:

    raise_app
    
  • Nếu tất cả đều hoạt động tốt, hãy thêm nó vào tổ hợp phím tắt mà bạn chọn: Chọn: Cài đặt hệ thống> "Bàn phím"> "Phím tắt"> "Phím tắt tùy chỉnh". Nhấp vào "+" và thêm lệnh

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.

nhập mô tả hình ảnh ở đây

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 .desktoptập tin

  1. 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_apptrong~/bin
  2. 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

    <biểu tượng>

  3. Sao chép .desktoptậ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.desktoptrong~/.local/share/applications

  4. Kéo .desktoptệp vào trình khởi chạy để thêm nó

  5. 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_appstrong ~/bin, làm cho nó thực thi được.
  6. 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
    
  7. Đă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 -lpGlệ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 forvò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 -rootlệ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 đó.


Tôi đồng ý, và cảm ơn một lần nữa cho tất cả nỗ lực của bạn! :) || Có một điều kỳ lạ mà tôi đã không nhận thấy trước đây. Đôi khi sau khi sử dụng Option 2tập lệnh, khi một cửa sổ ứng dụng được tập trung (không được tối đa hóa) và tôi nhấp vào một cửa sổ khác có thể nhìn thấy "bên dưới", ứng dụng bên dưới không lấy được trọng tâm.
Joschua

@Joschua OP của câu hỏi này: Askubfox.com/questions/575830/ đã tham dự với tôi về một lỗi được giới thiệu tại bản cập nhật "tính năng" mới nhất. Đúng / Sai được trộn lẫn, khiến tập lệnh bị sập khi không có ứng dụng nào có nhiều hơn một cửa sổ. Nếu bạn sử dụng tùy chọn2, vui lòng cập nhật lên phiên bản mới nhất.
Jacob Vlijm

Tùy chọn 1 không hoạt động đối với tôi trên xen kẽ Ubuntu. một cái gì đó @ cái gì đó: ~ / bin $ ./raise_app Gtk-Message: GtkDialog được ánh xạ mà không có cha mẹ thoáng qua. Điều này được khuyến khích. Tôi đã cố gắng để mở các cửa sổ thiết bị đầu cuối. Không có chuyện gì xảy ra.
xtrinch

@Nirri bạn đã sử dụng tên ứng dụng nào? Thông báo này khá bình thường nếu một cửa sổ tiện ích chạy mà không có cha mẹ Gtk. "Không khuyến khích" không phải là một lỗi.
Jacob Vlijm

Ký tự đầu tiên của thiết bị đầu cuối. Nó hoạt động - loại - nó làm tăng một cửa sổ của bất kỳ ứng dụng nào - nhưng chỉ một trong số chúng, không phải tất cả chúng như mong đợi @ user72216
xtrinch

1

Super+ Wphím tắt sẽ hiển thị expo của tất cả các cửa sổ hiện đang mở, mặc dù điều đó sẽ bao gồm các ứng dụng khác. Điều này được mặc định và không yêu cầu bất kỳ thay đổi nào, vì vậy có lẽ đó là một tùy chọn đơn giản nhất có sẵn.

Trong số những thứ khác, bạn có thể đặt các cửa sổ ở nửa bên phải và bên trái của màn hình bằng các nút Ctrl+ Super+ Left/ Rightvà chuyển đổi giữa chúng bằng Alt + ~ (dấu ngã, bên cạnh phím số một).


Điều đó không đưa tất cả các cửa sổ của một ứng dụng lên hàng đầu. Bạn có thể nhìn thấy chúng, nhưng bạn không thể sử dụng chúng mà không cần phải nhấp nhiều.
Joschua

1

Nếu bạn nhấn Alt + Tab để duyệt qua các ứng dụng và bạn đến một cửa sổ có nhiều cửa sổ, chỉ cần giữ phím alt và sau khoảng 1 giây, biểu tượng sẽ được thay thế bằng chế độ xem tất cả các cửa sổ cho ứng dụng đó.

Đó có thể hoặc không phải là những gì bạn đang tìm kiếm, nhưng nó hoạt động với tôi và đơn giản hơn rất nhiều, vì vậy tôi nghĩ rằng tôi sẽ chia sẻ tùy chọn này!


1
Bạn cũng có thể nhấn phím mũi tên xuống để cửa sổ ứng dụng hiển thị ngay lập tức.
Kris

1

Tôi đã lấy tập lệnh grow_apps.py của @ JacobVlijm và thực hiện một số cải tiến cho nó, bao gồm làm cho nó mạnh mẽ hơn.

Cụ thể, tôi đã thấy rằng sau một hoặc hai ngày, tập lệnh của @ JacobVlijm sẽ ngừng hoạt động và tôi phải tự khởi động lại tập lệnh, để nó hoạt động trở lại. Nhìn lại, dự đoán tốt nhất của tôi là nhiều cuộc gọi đến xrandr cuối cùng gây ra vấn đề.

Dù sao, tôi đã điều chỉnh mã của anh ấy, tăng tần số bỏ phiếu từ 5 giây lên mỗi 1 giây, vì dù sao nó cũng không sử dụng nhiều CPU và làm cho nó mạnh mẽ hơn. Tôi thường có thể có nó chạy trong nhiều ngày / tuần mà không có vấn đề.

Một lưu ý là tôi chỉ gọi xrandr một lần trong khi khởi động, để có được kích thước độ phân giải màn hình. Vì vậy, nếu bạn thay đổi độ phân giải màn hình của mình (ví dụ: từ 1920x1080 sang một số độ phân giải khác), có thể bạn sẽ muốn tự khởi động lại nâng cao -apps.py để nó sẽ nhận độ phân giải mới. Cá nhân, tôi không bao giờ thay đổi độ phân giải màn hình của mình, vì vậy đây không phải là vấn đề đối với tôi. Ngoài ra, tôi có lý do mạnh mẽ để tin rằng có quá nhiều cuộc gọi đến xrandr là nguyên nhân khiến phiên bản kịch bản của @ JacobVlijm ngừng hoạt động sau một hoặc hai ngày, vì vậy tôi khuyên bạn không nên đơn giản đưa nhiều cuộc gọi đến xrandr trở lại ..

BTW, bạn cần đặt hình ảnh grow.png trong thư mục / usr / local / icon /. Hoặc nếu bạn muốn đặt nâng.png vào một thư mục khác, hãy thực hiện thay đổi phù hợp với tập lệnh, để tập lệnh có thể tìm thấy tệp hình ảnh.

Hy vọng, Ubuntu sẽ tích hợp loại chức năng 'nâng tất cả các cửa sổ' này vào hệ thống của họ sớm hơn vì nó rất hữu ích:

#!/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()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.