응용 프로그램의 모든 창을 표시하는 방법은 무엇입니까?


21

여러 창을 사용하는 응용 프로그램이 있습니다. 해당 응용 프로그램의 모든 창을 신속하게 포 그라운드로 가져올 수 있습니까?

스크롤 휠로 응용 프로그램을 스크롤하면 하나의 창 만 표시됩니다. 다음 창으로 가면 마지막 창이 다시 배경으로 나타납니다.

응용 프로그램 아이콘을 클릭하면 모든 창에 대한 전체 화면 개요가 나타납니다. 각 창을 수동으로 선택하고 마우스를 화면 절반에서 여러 번 움직여야합니다.

나의 가장 좋은 방법은 지금까지 모든 창을 최소화 (IS Ctrl+ Super+ D) 다음 스크롤 휠을 사용하여 내 응용 프로그램의 창을 보여줍니다.

더 나은 해결책이 있습니까?


@Joschua 응용 프로그램의 모든 창을 맨 앞으로 가져 오는 것은 그리 어렵지 않지만 응용 프로그램을 어떻게 정의 하시겠습니까? 키 조합 + 응용 프로그램 창을 클릭하면 어떻게됩니까?
Jacob Vlijm

@Joschua 또는 mayby보다 우아하고 응용 프로그램 이름의 첫 번째 문자 + 키 조합?
Jacob Vlijm

모든 응용 프로그램에서 동작이 동일하지 않다고 생각합니다. 터미널 창 에서이 기능을 놓치는 경우가 많으며 종종 두 개 이상의 창이 나란히 열립니다. 그런 다음 전체 화면 창 (예 : Firefox)으로 전환하고 두 터미널 창으로 다시 전환하려면 다소 어렵습니다. 지금까지 찾은 가장 좋은 방법은 Firefox 응용 프로그램 표시 줄에서 마우스 가운데 버튼을 클릭하여 Firefox를 백그라운드로 가져와 두 터미널을 다시 전면에 배치하는 것입니다. 그러나 너무 많은 응용 프로그램이
쌓이지

또한 @Joschua 응용 프로그램 창 그룹 을 가져 오기 위해 키 조합을 가질 수 있습니다 . 한 번 누르면-> 모든 파이어 폭스 창이 나타나고, 다시 프레스-> 모든 터미널 창이 나타납니다. 매우 부드럽게 만들 수 있습니다. 흥미 롭군 그것에 노력하고 있습니다. 그래도 약간의 작업이 필요합니다.
Jacob Vlijm

@JacobVlijm 올바른 방향으로 들립니다. :) 가장 중요한 것 같습니다. 아이콘을 클릭하고 키 조합을하면 해당 응용 프로그램의 모든 창 (예 : peq가 언급 한 많은 터미널)이 전면에 표시됩니다. 겹치지 않도록 .. (아마도 이와 같은 것이 Unity의 일부가 될 수
있습니까

답변:


21

편집-새로운 답변-

아래의 답변은 여전히 ​​유효하며 제안 된 옵션입니다. 그러나 지속적인 통찰력으로 인해 아래 표시기를 사용하기 위해이 옵션을 추가했습니다.

따라서 옵션 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현재 뷰포트에서 모든 창을 올리십시오 .

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

사용하는 방법:

  • "사용 방법"에 설명 된대로 설정을 수행하십시오.
  • 다음 명령으로 테스트를 실행하십시오.

    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



옵션 2 : 애플리케이션을 순환하고 키 조합으로 창을 올리십시오.

키 조합 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



옵션 3 : 키를 눌러 조합 + 실행 아이콘을 클릭 - 또는 - 현재 뷰포트에 모든 창을 높이기 위해 응용 프로그램 창

이것은 아마도 질문 / 의견에 설명 된 것과 가장 가까운 옵션 일 것입니다.

nautilus다른 창 아래에 세 개의 창이 묻힌 지저분한 바탕 화면이 있다고 가정 해 봅시다 .

<이미지>

모든 노틸러스 창을 올리려면 (예 : 바로 가기 : Alt+ 1) :

  • 를 눌러 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


옵션 4 : 키 조합은 옵션 목록을 호출하여 현재 뷰포트의 응용 프로그램 당 창 수를 표시합니다

이 것이 더 편리한 것으로 판명되었습니다.

(예시) 키 조합을 누르면 Alt+ 창을 1호출 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"')



옵션 5 : 실행기 아이콘에서 실행중인 애플리케이션의 창 높이기

이 옵션은 빠른 실행 목록에 현재 실행중인 응용 프로그램과 함께 실행기 아이콘이 있습니다. 하나를 선택하면 응용 프로그램의 모든 창이 나타납니다.

여기에 이미지 설명을 입력하십시오

실행기는 현재 뷰포트에서 실행중인 응용 프로그램 목록이 변경되면 자동으로 업데이트됩니다. 빠른 목록은 다른 응용 프로그램의 창을 여는 다른 뷰포트의 다른 목록을 표시합니다 (적응하는 데 1-2 초 소요).

언급 한 바와 같이,이 옵션은 완벽하게 기능하지만 개념으로 사용 됩니다. 그것은 몇 가지 사소한 화장품 단점이 있습니다. 가장 중요한:

  • 동작 후 몇 초 동안 커서 "바퀴"가 계속 회전합니다. 기능에는 영향을 미치지 않지만 외관상의 단점입니다.
  • 실행중인 응용 프로그램 목록이 변경된 후 시작 관리자 아이콘의 응용 프로그램 목록이 업데이트 되려면 1-2 초가 걸립니다.

또한 설정이 약간 더 복잡합니다 (아래에 자세히 설명되어 있음).

사용하는 방법

아래에서 찾을 수 있습니다 :

두 개의 스크립트 / 아이콘 / .desktop파일

  1. "사용 방법"에서와 같이 설정을 준비하고 다음과 같이 첫 번째 (main-) 스크립트를 저장하십시오 raise_app.~/bin
  2. 아래 아이콘을 다음과 같이 저장하십시오 (오른쪽 클릭, 다른 이름으로 저장). raise.png

    <아이콘>

  3. .desktop파일을 빈 파일로 복사하고 줄을 편집하십시오.

        Icon=/path/to/raise.png
    

    아이콘에 대한 실제 경로 (인용 부호 사이의 공백 경로)
    이 저장 등 raise.desktop~/.local/share/applications

  4. .desktop파일을 런처로 드래그하여 추가하십시오

  5. 두 번째 스크립트를 복사 빈 파일에 붙여로 저장 update_apps에서 ~/bin그것을 실행 확인.
  6. 시작 응용 프로그램에 다음 명령을 추가하십시오 (대시> 시작 응용 프로그램> 추가).

    update_apps
    
  7. 로그 아웃했다가 다시 작동하십시오.

첫 스크립트

#!/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=



간단한 설명

위의 모든 솔루션 wmctrlwmctrl -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 루프는 "최신"최전방 응용 프로그램을 중단하고 찾은 다음 해당 응용 프로그램의 다른 모든 창을 엽니 다.


동의합니다. 모든 노력에 다시 한번 감사드립니다! :) || 전에는 눈치 채지 못한 이상한 것이 있습니다. 때로는 Option 2스크립트를 사용한 후 응용 프로그램 창에 초점을 맞추고 (최대화되지 않음) "아래"로 보이는 다른 창을 클릭하면 아래의 응용 프로그램에 초점이 맞지 않습니다.
Joschua

@Joschua이 질문의 OP : askubuntu.com/questions/575830/… 는 최신 "기능"업데이트에서 소개 된 버그에 대해 나에게 참석했습니다. True / False가 혼합되어 하나 이상의 창을 가진 응용 프로그램이 없을 때 스크립트가 중단됩니다. option2를 사용하는 경우 최신 버전으로 업데이트하십시오.
Jacob Vlijm

옵션 1이 우분투 제니 얼에서 작동하지 않습니다. something @ something : ~ / bin $ ./raise_app Gtk-Message : GtkDialog가 일시적인 부모없이 매핑되었습니다. 이것은 권장되지 않습니다. 터미널 창을 열려고했습니다. 아무 일도하지.
xtrinch

@Nirri 어떤 응용 프로그램 이름을 사용 했습니까? zenity 창이 Gtk 부모없이 실행되면 메시지는 정상적인 것입니다. "Discouraged"는 오류가 아닙니다.
Jacob Vlijm

터미널의 첫 문자. 그것은 작동 -의 종류 - 모든 이들의 @ user72216 예상대로,하지만 그들 중 하나 - 그것은 모든 응용 프로그램의 창을 제기
xtrinch

1

Super+W 이 다른 응용 프로그램을 포함하지만, 모든 현재 열려있는 창 엑스포를 표시합니다 바로 가기. 기본적으로 제공되며 변경이 필요하지 않으므로 가장 간단한 옵션 일 수 있습니다.

무엇보다도 Ctrl+ Super+ Left/ Right버튼으로 화면의 좌우 절반에 창을 배치 하고 Alt + ~ (물결표, 1 번 키 옆에있는 하나)로 창을 전환 할 수 있습니다.


그래도 응용 프로그램의 모든 창을 맨 위로 가져 오지는 않습니다. 당신은 그들을 볼 수 있지만 많이 클릭하지 않고도 사용할 수 없습니다.
Joschua

1

Alt + Tab을 눌러 응용 프로그램을 순환하고 여러 개의 창이있는 창을 찾으면 Alt 키를 계속 누르고 있으면 약 1 초 후에 아이콘이 해당 응용 프로그램의 모든 창보기로 바뀝니다.

그것은 당신이 찾고있는 것이거나 아닐 수도 있지만, 그것은 나를 위해 일하고 훨씬 간단합니다. 그래서 나는 옵션을 공유 할 것이라고 생각했습니다!


1
아래쪽 화살표 키를 눌러 응용 프로그램 창이 바로 표시되도록 할 수도 있습니다.
Kris

1

@JacobVlijm의 raise_apps.py 스크립트를 가져 와서 좀 더 강력하게 만드는 것을 포함하여 약간 개선했습니다.

특히, 하루나 이틀 후에 @JacobVlijm의 스크립트가 작동을 멈추고 스크립트를 다시 시작하려면 수동으로 스크립트를 다시 시작해야한다는 것을 알았습니다. 돌이켜 보면, xrandr에 대한 수많은 호출은 결국 문제를 일으킨다는 것입니다.

어쨌든, 그의 코드를 조정하고, CPU를 많이 사용하지 않기 때문에 폴링 빈도를 5 초에서 1 초마다 증가 시켰으며 더욱 강력 해졌습니다. 일반적으로 문제없이 며칠 / 주 동안 실행할 수 있습니다.

한 가지주의 사항은 시작 중에 xrandr를 한 번만 호출하여 화면 해상도를 측정한다는 것입니다. 따라서 화면 해상도를 변경하면 (예 : 1920x1080에서 다른 해상도로), 새 해상도를 선택하기 위해 raise-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: /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()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.