Pertanyaan Bagaimana saya bisa mengelompokkan windows untuk dibesarkan sebagai satu?


Saya memiliki dua jendela, A dan B. Apakah mungkin menghubungkan dua jendela secara bersamaan, sehingga beralih ke A juga menimbulkan B, atau beralih ke B juga menimbulkan A?

Saya mengerti menggunakan beberapa ruang kerja adalah pilihan alternatif tetapi bertanya-tanya apakah ini juga mungkin?


9
2017-08-01 06:26


asal


z-order tidak super penting tetapi jika mungkin itu akan menjadi besar - simontong
Saya pikir beberapa tempat kerja adalah solusi yang paling sederhana. Anda tahu kombinasi tombol untuk beralih di antara mereka? - thomasrutter
Anda adalah akseptor cepat :) Namun demikian, akan sangat menghargai jika Anda memberi komentar tentang jawaban saya. - Jacob Vlijm
Kemungkinan duplikat dari Jendela 'pengelompokan'?


Jawaban:


pengantar

Skrip berikut memungkinkan memilih dua jendela, dan sementara kedua jendela terbuka, itu akan menaikkan kedua jendela ketika pengguna memfokuskan salah satunya. Misalnya, jika seseorang mengaitkan janda A dan B, menyihir A atau B akan membuat keduanya naik di atas janda lain.

Untuk menghentikan skrip yang bisa Anda gunakan killall link_windows.py di terminal, atau tutup dan buka kembali salah satu jendela. Anda juga dapat membatalkan eksekusi dengan menekan tombol tutup X pada salah satu dialog popup pilihan-jendela.

Tweak potensial: 

  • beberapa contoh skrip dapat digunakan untuk mengelompokkan pasang dua jendela. Sebagai contoh, jika kita memiliki jendela A, B, C, dan D kita dapat menghubungkan A dan B bersama-sama, dan menghubungkan C dan D bersama-sama.
  • beberapa jendela dapat dikelompokkan dalam satu jendela tunggal. Misalnya, jika saya menautkan jendela B ke A, C ke A, dan D ke A, itu berarti jika saya selalu beralih ke A, saya bisa menaikkan semua 4 jendela secara bersamaan.

Pemakaian

Jalankan skrip sebagai:

python link_windows.py

Script ini kompatibel dengan Python 3, sehingga bisa juga dijalankan sebagai

python3 link_windows.py

Ada dua opsi baris perintah:

  • --quiet atau -q , memungkinkan membungkam jendela GUI. Dengan opsi ini Anda cukup mengeklik mouse pada dua jendela, dan skrip akan mulai menautkannya.
  • --help atau -h, mencetak informasi penggunaan dan deskripsi.

Itu -h opsi menghasilkan informasi berikut:

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

Informasi teknis tambahan dapat dilihat melalui pydoc ./link_windows.py , dimana ./ menandakan bahwa Anda harus berada di direktori yang sama dengan skrip.

Proses penggunaan sederhana untuk dua jendela:

  1. Munculan akan muncul meminta Anda memilih jendela # 1, tekan baik atau memukul Memasukkan. Penunjuk mouse akan berubah menjadi tanda silang. Klik pada salah satu jendela yang ingin Anda tautkan.

  2. Popup kedua akan muncul meminta Anda memilih jendela # 2, tekan baik atau memukul Memasukkan. Sekali lagi, penunjuk mouse akan berubah menjadi tanda silang. Klik pada jendela lain yang ingin Anda tautkan. Setelah itu eksekusi akan dimulai.

  3. Setiap kali Anda fokus baik jendela, skrip akan menaikkan jendela lain, tetapi kembali fokus ke yang semula dipilih (catatan - dengan seperempat penundaan kedua untuk kinerja terbaik), sehingga menciptakan nuansa bahwa jendela saling terhubung.

Jika Anda memilih jendela yang sama dua kali, skrip akan berhenti. Jika suatu saat Anda mengklik tombol tutup dialog popup, skrip akan berhenti.

Sumber skrip

Juga tersedia sebagai 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()

Catatan:


9
2017-08-02 00:20



Ceria, saya sangat terkesan. Itu time.sleep bit antara switching, apakah saya bisa memasukkannya ke nol? apakah ada alasan keterlambatan? - simontong
@simontong Anda dapat mencoba mengomentari baris seperti # time.sleep(0.25) dan itu tidak akan dieksekusi. Alasannya adalah untuk memastikan bahwa setiap jendela dibangkitkan dengan baik. Dalam pengalaman saya di masa lalu, saya perlu penundaan untuk beroperasi di windows. Saya akan berpikir keterlambatan seperempat detik tidak sebanyak itu. Sebenarnya, izinkan saya menambahkan satu baris lagi ke skrip, yang bisa mempercepatnya. BAIK ? - Sergiy Kolodyazhnyy
@simontong OK, saya telah memperbarui skripnya. Coba sekarang. Seharusnya beralih lebih cepat - Sergiy Kolodyazhnyy
@simontong Saya akan memperbarui skrip dengan beberapa tambahan kecil untuk menambahkan beberapa fitur tambahan. Saya akan memberi tahu Anda jika sudah siap, beri tahu saya apa yang Anda pikirkan - Sergiy Kolodyazhnyy
@simontong menambahkan opsi ekstra ke skrip, harap tinjau - Sergiy Kolodyazhnyy


Naikkan sejumlah jendela sembarang sebagai satu

Solusi di bawah ini akan membiarkan Anda memilih apa saja kombinasi dua, tiga atau lebih jendela untuk digabungkan dan dibesarkan sebagai satu dengan pintasan keyboard.

Skrip melakukan tugasnya dengan tiga argumen:

add

untuk menambahkan jendela aktif ke grup

raise

untuk menaikkan kelompok set

clear

untuk menghapus grup, siap untuk menentukan grup baru

Naskah

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

Bagaimana cara menggunakan

  1. Kebutuhan skrip wmctrl dan xdotool:

    sudo apt-get install wmctrl xdotool
    
  2. Salin skrip di atas ke dalam file kosong, simpan sebagai groupwindows.py
  3. Uji-jalankan skrip: buka dua jendela terminal, jalankan perintah:

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

    di keduanya. Tutupi mereka dengan jendela lain (atau minimalkan). Buka jendela terminal ketiga, jalankan perintah:

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

    Dua jendela pertama akan dinaikkan menjadi satu.

  4. Jika semuanya berfungsi dengan baik, buat tiga tombol pintasan khusus: Pilih: Pengaturan Sistem> "Keyboard"> "Pintasan"> "Pintasan Kustom". Klik "+" dan tambahkan perintah di bawah ini ke tiga pintas terpisah:

    pada sistem saya, saya menggunakan:

    Alt+SEBUAH, menjalankan perintah:

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

    ... untuk menambahkan jendela ke grup.

    Alt+R, menjalankan perintah:

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

    ... untuk membesarkan kelompok.

    Alt+C, menjalankan perintah:

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

    ... untuk membersihkan grup

Penjelasan

Script bekerja dengan cukup sederhana:

  • Saat dijalankan dengan argumen add, skrip menyimpan / menambahkan jendela-jendela aktif ke file tersembunyi ~/.windowlist
  • Saat dijalankan dengan argumen raise, skrip membaca file, memunculkan jendela dalam daftar dengan perintah:

    wmctrl -ia <window_id>
    
  • Saat dijalankan dengan argumen clear, skrip menghapus file yang tersembunyi ~/.windowlist.

Catatan

  • Skrip ini juga akan bekerja pada jendela diminimalkan, itu akan meminimalkan meminimalkan kemungkinan jendela
  • Jika kumpulan jendela ada di viewport lain, skrip akan beralih ke viewport yang sesuai
  • Perangkat ini fleksibel, Anda selalu dapat menambahkan jendela lain ke set saat ini.

Lebih banyak fleksibilitas?

Seperti disebutkan, skrip di atas memungkinkan menambahkan windows kapan saja ke jendela yang dikelompokkan. Versi di bawah ini juga memungkinkan menghapus salah satu jendela (kapan saja) dari daftar yang dikelompokkan:

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

Argumen tambahan untuk menjalankan skrip adalah delete, jadi:

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

menghapus jendela aktif dari jendela yang dikelompokkan. Untuk menjalankan perintah ini, di sistem saya, saya setel Alt+D sebagai jalan pintas.


6
2017-08-02 06:55