창을 하나로 그룹화하려면 어떻게해야합니까?


10

두 개의 창 A와 B가 있습니다. 어떻게 든 두 개의 창을 연결하여 A로 전환하면 B가 증가하거나 B로 전환하면 A가 증가합니까?

여러 작업 공간을 사용하는 것이 대체 옵션이라는 것을 알고 있지만 이것이 가능한지 궁금합니다.


z 순서는 중요하지 않지만 가능하다면 훌륭 할 것입니다
Simon Tong

여러 직장이 가장 간단한 해결책이라고 생각합니다. 당신은 그들 사이를 전환하기위한 주요 조합을 알고 있습니까?
thomasrutter

1
당신은 빠른 수락 자입니다 :) 그럼에도 불구하고, 당신이 내 대답에 대한 의견을 주면 감사하겠습니다.
Jacob Vlijm

답변:


9

소개

다음 스크립트에서는 두 개의 창을 선택할 수 있으며 두 창이 열려있는 동안 사용자가 둘 중 하나에 초점을 맞출 때 두 창을 모두 띄웁니다. 예를 들어, 하나가 미망인 A와 B를 연결하면 A 나 B로 전환하면 둘 다 다른 미망인보다 높아집니다.

스크립트를 중지하려면 killall link_windows.py터미널에서 사용하거나 창 중 하나를 닫았다가 다시 열 수 있습니다. X창 선택 팝업 대화 상자에서 닫기 단추 를 눌러 실행을 취소 할 수도 있습니다 .

잠재적 인 조정 :

  • 스크립트의 여러 인스턴스를 사용하여 두 창 쌍을 그룹화 할 수 있습니다. 예를 들어, A, B, C 및 D 창이있는 경우 A와 B를 서로 연결하고 C와 D를 서로 연결할 수 있습니다.
  • 하나의 창 아래에 여러 개의 창을 그룹화 할 수 있습니다. 예를 들어, 창 B를 A에, C를 A에, D를 A에 연결하면 항상 A로 전환하면 동시에 4 개의 창을 모두 올릴 수 있습니다.

용법

다음과 같이 스크립트를 실행하십시오.

python link_windows.py

이 스크립트는 Python 3과 호환되므로 다음과 같이 실행할 수도 있습니다.

python3 link_windows.py

두 가지 명령 줄 옵션이 있습니다.

  • --quiet또는 -q을 사용하여 GUI 창을 닫을 수 있습니다. 이 옵션을 사용하면 두 창에서 마우스를 클릭하기 만하면 스크립트가 이들을 연결하기 시작합니다.
  • --help또는 -h, 사용법 및 설명 정보를 인쇄합니다.

-h옵션은 다음 정보를 생성합니다.

$ python3 link_windows.py  -h                                                                                            
usage: link_windows.py [-h] [--quiet]

Linker for two X11 windows.Allows raising two user selected windows together

optional arguments:
  -h, --help  show this help message and exit
  -q, --quiet  Blocks GUI dialogs.

추가 기술 정보는을 통해 볼 수 있습니다. pydoc ./link_windows.py여기서 ./스크립트와 동일한 디렉토리에 있어야 함을 나타냅니다.

두 개의 창에 대한 간단한 사용 프로세스 :

  1. 팝업은 윈도우의 # 1를 눌러 지정을 요구 나타납니다 OK또는 히트를 Enter. 마우스 포인터가 십자로 변합니다. 연결하려는 창 중 하나를 클릭하십시오.

  2. 창 2를 선택하거나을 누르 OK거나 누르라는 두 번째 팝업이 나타납니다 Enter. 다시 마우스 포인터가 십자로 변합니다. 연결하려는 다른 창을 클릭하십시오. 그 후 실행이 시작됩니다.

  3. 두 창 중 하나에 초점을 맞출 때마다 스크립트는 다른 창을 위로 올리지 만 원래 선택한 창으로 초점을 되돌립니다 (최고의 성능을 위해 2 분의 1의 지연으로 노트).

동일한 창을 두 번 선택하면 스크립트가 종료됩니다. 팝업 대화 상자의 닫기 버튼을 클릭하면 스크립트가 종료됩니다.

스크립트 소스

GitHub Gist로도 사용 가능

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Sergiy Kolodyazhnyy
Date:  August 2nd, 2016
Written for: https://askubuntu.com/q/805515/295286
Tested on Ubuntu 16.04 LTS
"""
import gi
gi.require_version('Gdk', '3.0')
gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, Gtk
import time
import subprocess
import sys
import argparse


def run_cmd(cmdlist):
    """ Reusable function for running shell commands"""
    try:
        stdout = subprocess.check_output(cmdlist)
    except subprocess.CalledProcessError:
        sys.exit(1)
    else:
        if stdout:
            return stdout


def focus_windows_in_order(first, second, scr):
    """Raise two user-defined windows above others.
       Takes two XID integers and screen object.
       Window with first XID will have the focus"""

    first_obj = None
    second_obj = None

    for window in scr.get_window_stack():
        if window.get_xid() == first:
            first_obj = window
        if window.get_xid() == second:
            second_obj = window

    # When this  function is called first_obj is alread
    # raised. Therefore we must raise second one, and switch
    # back to first
    second_obj.focus(int(time.time()))
    second_obj.get_update_area()
    # time.sleep(0.25)
    first_obj.focus(int(time.time()))
    first_obj.get_update_area()


def get_user_window():
    """Select two windows via mouse. Returns integer value of window's id"""
    window_id = None
    while not window_id:
        for line in run_cmd(['xwininfo', '-int']).decode().split('\n'):
            if 'Window id:' in line:
                window_id = line.split()[3]
    return int(window_id)


def main():
    """ Main function. This is where polling for window stack is done"""

    # Parse command line arguments
    arg_parser = argparse.ArgumentParser(
        description="""Linker for two X11 windows.Allows raising """ +
                    """two user selected windows together""")
    arg_parser.add_argument(
                '-q','--quiet', action='store_true',
                help='Blocks GUI dialogs.',
                required=False)
    args = arg_parser.parse_args()

    # Obtain list of two user windows
    user_windows = [None, None]
    if not args.quiet:
        run_cmd(['zenity', '--info', '--text="select first window"'])
    user_windows[0] = get_user_window()
    if not args.quiet:
        run_cmd(['zenity', '--info', '--text="select second window"'])
    user_windows[1] = get_user_window()

    if user_windows[0] == user_windows[1]:
        run_cmd(
            ['zenity', '--error', '--text="Same window selected. Exiting"'])
        sys.exit(1)

    screen = Gdk.Screen.get_default()
    flag = False

    # begin watching for changes in window stack
    while True:

        window_stack = [window.get_xid()
                        for window in screen.get_window_stack()]

        if user_windows[0] in window_stack and user_windows[1] in window_stack:

            active_xid = screen.get_active_window().get_xid()
            if active_xid not in user_windows:
                flag = True

            if flag and active_xid == user_windows[0]:
                focus_windows_in_order(
                    user_windows[0], user_windows[1], screen)
                flag = False

            elif flag and active_xid == user_windows[1]:
                focus_windows_in_order(
                    user_windows[1], user_windows[0], screen)
                flag = False

        else:
            break

        time.sleep(0.15)


if __name__ == "__main__":
    main()

노트:

  • 명령 행에서 실행할 때 팝업 대화 상자는 다음 메시지를 생성합니다 Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.. 무시할 수 있습니다.
  • Unity에서 수동으로 새 런처 항목을 편집 / 만들려면 어떻게합니까?를 참조하십시오 . 두 번 클릭으로 시작하려면이 스크립트의 실행기 또는 바탕 화면 바로 가기를 작성하십시오.
  • 쉽게 액세스 할 수 있도록이 스크립트를 키보드 단축키에 연결하려면 키보드 단축키 를 추가하는 방법을 참조하십시오 .

건배 정말 감동합니다. time.sleep전환 사이 의 비트는 0으로 설정할 수 있습니까? 지연 이유가 있습니까?
Simon Tong

1
@simontong 당신은 같은 줄을 주석 처리하려고 시도 # time.sleep(0.25)하고 실행되지 않습니다. 그 이유는 각 창을 올바르게 올리는 것입니다. 과거의 경험에서, 나는 창문에서 작동하기 위해 지연이 필요했습니다. 1/4 초 지연은 그렇게 많지 않다고 생각합니다. 실제로 스크립트에 한 줄만 추가하면 속도가 빨라질 수 있습니다. 확인 ?
Sergiy Kolodyazhnyy

@simontong 좋습니다, 스크립트를 업데이트했습니다. 지금 사용해보십시오. 더 빠른 전환이 필요
Sergiy Kolodyazhnyy

@simontong 나는 몇 가지 추가 기능을 추가하기 위해 약간의 추가로 스크립트를 업데이트 할 것입니다. 준비가되면 알려 드리겠습니다.
의견을

@simontong은 스크립트에 추가 옵션을 추가했습니다. 검토하십시오
Sergiy Kolodyazhnyy

6

임의의 수의 창을 하나로 올리십시오

이 솔루션은 아래 당신이 선택하게됩니다 어떤 결합과 키보드 단축키 하나로서 제기되는 두 개, 세 개 이상의 창 조합.

이 스크립트는 세 가지 인수로 작동합니다.

add

그룹에 활성 창을 추가하려면

raise

세트 그룹을 높이기 위해

clear

그룹을 지우고 새 그룹을 정의 할 준비가되었습니다.

스크립트

#!/usr/bin/env python3
import sys
import os
import subprocess

wlist = os.path.join(os.environ["HOME"], ".windowlist")

arg = sys.argv[1]

if arg == "add":
    active = subprocess.check_output([
        "xdotool", "getactivewindow"
        ]).decode("utf-8").strip()
    try:
        currlist = open(wlist).read()
    except FileNotFoundError:
        currlist = []
    if not active in currlist:
        open(wlist, "a").write(active + "\n")
elif arg == "raise":
    group = [w.strip() for w in open(wlist).readlines()]
    [subprocess.call(["wmctrl", "-ia", w]) for w in group]
elif arg == "clear":
    os.remove(wlist)

사용하는 방법

  1. 스크립트가 필요 wmctrl하고 xdotool:

    sudo apt-get install wmctrl xdotool
  2. 위의 스크립트를 빈 파일로 복사하여 다른 이름으로 저장하십시오. groupwindows.py
  3. 스크립트를 테스트 실행하십시오. 두 개의 터미널 창을 열고 다음 명령을 실행하십시오.

    python3 /absolute/path/to/groupwindows.py add

    둘 다. 다른 창으로 덮거나 최소화하십시오. 세 번째 터미널 창을 열고 다음 명령을 실행하십시오.

    python3 /absolute/path/to/groupwindows.py raise

    처음 두 개의 창이 하나로 나타납니다.

  4. 모두 제대로 작동하면 시스템 설정> "키보드"> "바로 가기"> "사용자 정의 바로 가기"를 선택하십시오. "+"를 클릭하고 아래의 명령을 세 개의 바로 가기에 추가하십시오.

    내 시스템에서 다음을 사용했습니다.

    Alt+ A, 명령을 실행 :

    python3 /absolute/path/to/groupwindows.py add

    ... 그룹에 창을 추가합니다.

    Alt+ R, 명령을 실행 :

    python3 /absolute/path/to/groupwindows.py raise

    ... 그룹을 키우기 위해.

    Alt+ C, 명령을 실행 :

    python3 /absolute/path/to/groupwindows.py clear

    ... 그룹을 지우려면

설명

스크립트는 매우 간단하게 작동합니다.

  • 인수로 실행 add하면 스크립트는 활성 창의 window-id를 숨겨진 파일에 저장 / 추가합니다.~/.windowlist
  • 인수로 실행 raise하면 스크립트는 파일을 읽고 다음 명령을 사용하여 목록에서 창을 엽니 다.

    wmctrl -ia <window_id>
  • 인수와 함께 실행 clear하면 스크립트는 숨겨진 파일을 제거합니다 ~/.windowlist.

메모

  • 스크립트는 최소화 된 창에서도 작동하며 최소화 된 창은 최소화하지 않습니다.
  • 창 세트가 다른 뷰포트에있는 경우 스크립트는 해당 뷰포트로 전환됩니다
  • 세트는 flexibel이므로 언제든지 현재 세트에 다른 창을 추가 할 수 있습니다.

더 많은 유연성?

언급 한 바와 같이, 위의 스크립트를 사용하면 언제든지 그룹화 된 창에 창을 추가 할 수 있습니다. 아래 버전을 사용 하면 그룹화 된 목록에서 언제든지 창을 제거 할 수 있습니다 .

#!/usr/bin/env python3
import sys
import os
import subprocess

wlist = os.path.join(os.environ["HOME"], ".windowlist")
arg = sys.argv[1]
# add windows to the group
if arg == "add":
    active = subprocess.check_output([
        "xdotool", "getactivewindow"
        ]).decode("utf-8").strip()
    try:
        currlist = open(wlist).read()
    except FileNotFoundError:
        currlist = []
    if not active in currlist:
        open(wlist, "a").write(active + "\n")
# delete window from the group
if arg == "delete":
    try:
        currlist = [w.strip() for w in open(wlist).readlines()]
    except FileNotFoundError:
        pass
    else:
        currlist.remove(subprocess.check_output([
            "xdotool", "getactivewindow"]).decode("utf-8").strip())      
        open(wlist, "w").write("\n".join(currlist)+"\n")
# raise the grouped windows
elif arg == "raise":
    group = [w.strip() for w in open(wlist).readlines()]
    [subprocess.call(["wmctrl", "-ia", w]) for w in group]
# clear the grouped window list
elif arg == "clear":
    os.remove(wlist)

스크립트를 실행하기위한 추가 인수는 다음과 delete같습니다.

python3 /absolute/path/to/groupwindows.py delete

그룹화 된 창에서 활성 창을 삭제합니다. 이 명령을 실행하려면 시스템에서 Alt+ D를 바로 가기로 설정 했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.