Làm thế nào tôi có thể nhóm các cửa sổ để được nâng lên như một?


10

Tôi có hai cửa sổ, A và B. Có thể bằng cách nào đó liên kết hai cửa sổ lại với nhau, như vậy việc chuyển sang A cũng làm tăng B, hoặc chuyển sang B cũng tăng A?

Tôi hiểu rằng sử dụng nhiều không gian làm việc là một lựa chọn thay thế nhưng đã tự hỏi nếu điều này cũng có thể?


thứ tự z không phải là siêu quan trọng nhưng nếu có thể thì đó sẽ là điều tuyệt vời
Simon Tong

Tôi nghĩ rằng nhiều nơi làm việc là giải pháp đơn giản nhất. Bạn biết các tổ hợp phím để chuyển đổi giữa chúng?
thomasrutter

1
Bạn là người chấp nhận nhanh chóng :) Tuy nhiên, sẽ đánh giá cao nếu bạn đưa ra một số nhận xét về câu trả lời của tôi.
Jacob Vlijm

5
Có thể trùng lặp cửa sổ 'nhóm'?

Câu trả lời:


9

Giới thiệu

Kịch bản sau đây cho phép chọn hai cửa sổ và trong khi cả hai cửa sổ đều mở, nó sẽ nâng cả hai cửa sổ khi người dùng tập trung vào một trong hai cửa sổ. Chẳng hạn, nếu một liên kết góa phụ A và B, phù hợp với A hoặc B sẽ khiến cả hai nâng cao hơn các góa phụ khác.

Để dừng tập lệnh, bạn có thể sử dụng killall link_windows.pytrong thiết bị đầu cuối hoặc đóng và mở lại một trong các cửa sổ. Bạn cũng có thể hủy thực thi bằng cách nhấn nút đóng Xtrên một trong các hộp thoại bật lên chọn cửa sổ.

Điều chỉnh tiềm năng:

  • nhiều phiên bản của tập lệnh có thể được sử dụng để nhóm các cặp của hai cửa sổ. Ví dụ: nếu chúng ta có các cửa sổ A, B, C và D, chúng ta có thể liên kết A và B với nhau và liên kết C và D với nhau.
  • nhiều cửa sổ có thể được nhóm lại dưới một cửa sổ duy nhất. Ví dụ: nếu tôi liên kết cửa sổ B với A, C với A và D với A, điều đó có nghĩa là nếu tôi luôn chuyển sang A, tôi có thể nâng cả 4 cửa sổ cùng một lúc.

Sử dụng

Chạy tập lệnh dưới dạng:

python link_windows.py

Kịch bản tương thích với Python 3, vì vậy nó cũng có thể chạy như

python3 link_windows.py

Có hai tùy chọn dòng lệnh:

  • --quiethoặc -q, cho phép tắt các cửa sổ GUI. Với tùy chọn này, bạn có thể chỉ cần nhấp chuột vào bất kỳ hai cửa sổ nào và tập lệnh sẽ bắt đầu liên kết các cửa sổ đó.
  • --helphoặc -h, in thông tin sử dụng và mô tả.

Các -htùy chọn tạo ra các thông tin sau:

$ 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.

Thông tin kỹ thuật bổ sung có thể được xem qua pydoc ./link_windows.py, trong đó ./biểu thị rằng bạn phải ở cùng thư mục với tập lệnh.

Quy trình sử dụng đơn giản cho hai cửa sổ:

  1. Một cửa sổ bật lên sẽ xuất hiện yêu cầu bạn chọn cửa sổ số 1, nhấn OKhoặc nhấn Enter. Con trỏ chuột sẽ chuyển sang hình chữ thập. Nhấp vào một trong những cửa sổ bạn muốn liên kết.

  2. Một cửa sổ bật lên thứ hai sẽ xuất hiện yêu cầu bạn chọn cửa sổ số 2, nhấn OKhoặc nhấn Enter. Một lần nữa, con trỏ chuột sẽ biến thành hình chữ thập. Bấm vào cửa sổ khác mà bạn muốn liên kết. Sau đó thực hiện sẽ bắt đầu.

  3. Bất cứ khi nào bạn tập trung vào một trong hai cửa sổ, tập lệnh sẽ nâng cửa sổ khác lên, nhưng trả lại tiêu điểm cho cửa sổ được chọn ban đầu (lưu ý - với một phần tư độ trễ thứ hai để có hiệu suất tốt nhất), do đó tạo cảm giác các cửa sổ được liên kết với nhau.

Nếu bạn chọn cùng một cửa sổ cả hai lần, tập lệnh sẽ thoát. Nếu bất cứ lúc nào bạn nhấp vào nút đóng của hộp thoại bật lên, tập lệnh sẽ thoát.

Nguồn kịch bản

Cũng có sẵn như GitHub Gist

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Sergiy Kolodyazhnyy
Date:  August 2nd, 2016
Written for: /ubuntu//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()

Ghi chú


Chúc mừng tôi thực sự ấn tượng. Các time.sleepchút giữa chuyển đổi, tôi có thể đưa đến không? Có một lý do cho sự chậm trễ?
Simon Tong

1
@simontong bạn có thể thử bình luận dòng đó như thế nào # time.sleep(0.25)và nó sẽ không thực thi. Lý do cho điều đó là để đảm bảo rằng mỗi cửa sổ được nâng lên đúng cách. Theo kinh nghiệm của tôi trong quá khứ, tôi cần phải có sự chậm trễ để vận hành trên windows. Tôi nghĩ rằng sự chậm trễ một phần tư không phải là nhiều. Trên thực tế, hãy để tôi thêm một dòng nữa vào kịch bản, điều đó có thể tăng tốc nó. ĐỒNG Ý ?
Sergiy Kolodyazhnyy

@simontong OK, tôi đã cập nhật tập lệnh. Thử ngay bây giờ. Nên chuyển đổi nhanh hơn
Sergiy Kolodyazhnyy

@simontong Tôi sẽ cập nhật tập lệnh với một vài bổ sung nhỏ để thêm một vài tính năng bổ sung. Tôi sẽ cho bạn biết khi nó sẵn sàng, xin vui lòng cho tôi biết bạn nghĩ gì
Sergiy Kolodyazhnyy

@simontong đã thêm tùy chọn bổ sung vào tập lệnh, vui lòng xem lại
Sergiy Kolodyazhnyy

6

Tăng số lượng cửa sổ tùy ý làm một

Giải pháp dưới đây sẽ cho phép bạn chọn bất kỳ sự kết hợp nào của hai, ba hoặc nhiều cửa sổ được kết hợp và nâng lên thành một với một phím tắt.

Kịch bản thực hiện công việc của nó với ba đối số:

add

để thêm cửa sổ hoạt động vào nhóm

raise

để nâng cao nhóm thiết lập

clear

để xóa nhóm, sẵn sàng xác định một nhóm mới

Kịch bản

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

Cách sử dụng

  1. Kịch bản cần wmctrlxdotool:

    sudo apt-get install wmctrl xdotool
  2. Sao chép tập lệnh ở trên vào một tệp trống, lưu nó dưới dạng groupwindows.py
  3. Kiểm tra- chạy tập lệnh: mở hai cửa sổ đầu cuối, chạy lệnh:

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

    trong cả hai. Che chúng với các cửa sổ khác (hoặc giảm thiểu chúng). Mở cửa sổ terminal thứ ba, chạy lệnh:

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

    Hai cửa sổ đầu tiên sẽ được nâng lên làm một.

  4. Nếu tất cả đều hoạt động tốt, hãy tạo ba phím tắt tùy chỉnh: 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 các lệnh bên dưới vào ba phím tắt riêng biệt:

    trên hệ thống của tôi, tôi đã sử dụng:

    Alt+ A, chạy lệnh:

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

    ... Để thêm một cửa sổ cho nhóm.

    Alt+ R, chạy lệnh:

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

    ... để nâng cao nhóm.

    Alt+ C, chạy lệnh:

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

    ... để xóa nhóm

Giải trình

Kịch bản hoạt động khá đơn giản:

  • Khi chạy với đối số add, tập lệnh lưu trữ / thêm id cửa sổ của cửa sổ đang hoạt động vào một tệp ẩn~/.windowlist
  • Khi chạy với đối số raise, tập lệnh sẽ đọc tệp, tăng các cửa sổ trong danh sách bằng lệnh:

    wmctrl -ia <window_id>
  • Khi chạy với đối số clear, tập lệnh sẽ xóa tệp ẩn ~/.windowlist.

Ghi chú

  • Kịch bản cũng sẽ hoạt động trên các cửa sổ được thu nhỏ, nó sẽ bỏ tối thiểu các cửa sổ có thể thu nhỏ
  • Nếu bộ cửa sổ nằm trên một khung nhìn khác, tập lệnh sẽ chuyển sang chế độ xem tương ứng
  • Bộ này là flexibel, bạn luôn có thể thêm các cửa sổ khác vào bộ hiện tại.

Linh hoạt hơn?

Như đã đề cập, đoạn script trên cho phép thêm các cửa sổ bất cứ lúc nào vào các cửa sổ được nhóm. Phiên bản dưới đây cũng cho phép xóa bất kỳ cửa sổ nào (bất cứ lúc nào) khỏi danh sách được nhóm:

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

Đối số bổ sung để chạy tập lệnh là delete, vì vậy:

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

xóa cửa sổ hoạt động khỏi các cửa sổ được nhóm. Để chạy lệnh này, trên hệ thống của tôi, tôi đặt Alt+ Dlàm phím tắt.

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.