Come posso raggruppare le finestre da sollevare come una?


10

Ho due finestre, A e B. È possibile in qualche modo collegare due finestre insieme, in modo tale che anche il passaggio a A alzi B o il passaggio a B alzi anche A?

Capisco che l'utilizzo di più aree di lavoro sia un'opzione alternativa, ma mi chiedevo se anche questo fosse possibile?


L'ordine z non è molto importante ma, se possibile, sarebbe fantastico
Simon Tong

Penso che più posti di lavoro siano di gran lunga la soluzione più semplice. Conosci le combinazioni di tasti per passare da una all'altra?
thomasrutter,

1
Sei un accettore rapido :) Tuttavia, ti sarei grato se mi avessi dato un commento sulla mia risposta.
Jacob Vlijm,

5
Possibile duplicato del "raggruppamento"

Risposte:


9

introduzione

Lo script seguente consente di selezionare due finestre e, mentre entrambe le finestre sono aperte, solleverà entrambe le finestre quando l'utente mette a fuoco una delle due. Ad esempio, se si collegano le vedove A e B, la strega con A o B farà alzare entrambi sopra le altre vedove.

Per interrompere lo script è possibile utilizzare killall link_windows.pynel terminale oppure chiudere e riaprire una delle finestre. È inoltre possibile annullare l'esecuzione premendo il pulsante Chiudi Xin una delle finestre di dialogo popup di selezione della finestra.

Potenziali modifiche:

  • più istanze dello script possono essere utilizzate per raggruppare coppie di due finestre. Ad esempio, se abbiamo finestre A, B, C e D, possiamo collegare A e B insieme e collegare C e D insieme.
  • più finestre possono essere raggruppate in un'unica finestra. Ad esempio, se collego la finestra da B a A, da C ad A e da D ad A, ciò significa che se passo sempre ad A, posso sollevare tutte e 4 le finestre contemporaneamente.

uso

Esegui lo script come:

python link_windows.py

Lo script è compatibile con Python 3, quindi può anche essere eseguito come

python3 link_windows.py

Esistono due opzioni della riga di comando:

  • --quietoppure -q, consente di silenziare le finestre della GUI. Con questa opzione puoi semplicemente fare clic con il mouse su due finestre e lo script inizierà a collegarle.
  • --helpoppure -hstampa le informazioni sull'utilizzo e sulla descrizione.

L' -hopzione produce le seguenti informazioni:

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

Ulteriori informazioni tecniche possono essere visualizzate tramite pydoc ./link_windows.py, dove ./indica che è necessario trovarsi nella stessa directory dello script.

Semplice processo di utilizzo per due finestre:

  1. Apparirà un popup che ti chiederà di selezionare una finestra n. 1, premere OKo premere Enter. Il puntatore del mouse si trasformerà in una croce. Fai clic su una delle finestre che desideri collegare.

  2. Apparirà un secondo popup che ti chiederà di selezionare la finestra # 2, premi OKo premi Enter. Ancora una volta, il puntatore del mouse si trasformerà in una croce. Fare clic sull'altra finestra che si desidera collegare. Dopo tale esecuzione avrà inizio.

  3. Ogni volta che focalizzi una delle finestre, lo script solleverà l'altra finestra, ma riporta lo stato attivo su quella originariamente selezionata (nota - con un quarto di secondo di ritardo per le migliori prestazioni), creando così la sensazione che le finestre siano collegate tra loro.

Se si seleziona la stessa finestra entrambe le volte, lo script verrà chiuso. Se in qualsiasi momento fai clic sul pulsante Chiudi della finestra di dialogo popup, lo script verrà chiuso.

Fonte dello script

Disponibile anche come 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()

Appunti:


Saluti, sono davvero colpito. Il time.sleepbit tra il passaggio, io sono in grado di mettere che a zero? c'è un motivo per il ritardo?
Simon Tong,

1
@simontong puoi provare a commentare quella riga come # time.sleep(0.25)e non verrà eseguita. Il motivo è quello di garantire che ogni finestra venga correttamente sollevata. Nella mia esperienza in passato, avevo bisogno di ritardi per il funzionamento su Windows. Penserei che il ritardo di un secondo non sia molto. In realtà, lasciatemi aggiungere solo un'altra riga allo script, che potrebbe accelerarlo. OK ?
Sergiy Kolodyazhnyy il

@simontong OK, ho aggiornato lo script. Provalo ora. Dovrebbe avere una commutazione più veloce
Sergiy Kolodyazhnyy il

@simontong Aggiornerò lo script con alcune aggiunte minori per aggiungere alcune funzionalità extra. Ti farò sapere una volta che è pronto, per favore fatemi sapere cosa ne pensate
Sergiy Kolodyazhnyy

@simontong ha aggiunto opzioni extra allo script, si prega di rivedere
Sergiy Kolodyazhnyy

6

Aumenta un numero arbitrario di finestre come una

La soluzione seguente ti consentirà di scegliere qualsiasi combinazione di due, tre o più finestre da combinare e sollevare come una con una scorciatoia da tastiera.

Lo script fa il suo lavoro con tre argomenti:

add

per aggiungere la finestra attiva al gruppo

raise

per aumentare il gruppo impostato

clear

per cancellare il gruppo, pronto a definire un nuovo gruppo

Il copione

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

Come usare

  1. La sceneggiatura ha bisogno wmctrle xdotool:

    sudo apt-get install wmctrl xdotool
  2. Copia lo script sopra in un file vuoto, salvalo come groupwindows.py
  3. Prova- esegui lo script: apri due finestre di terminale, esegui il comando:

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

    in entrambi. Coprili con altre finestre (o minimizzali). Apri una terza finestra del terminale, esegui il comando:

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

    Le prime due finestre verranno sollevate come una sola.

  4. Se tutto funziona correttamente, crea tre tasti di scelta rapida personalizzati: Scegli: Impostazioni di sistema> "Tastiera"> "Tasti di scelta rapida"> "Tasti di scelta rapida personalizzati". Fai clic su "+" e aggiungi i comandi seguenti a tre scorciatoie separate:

    sul mio sistema, ho usato:

    Alt+ A, eseguendo il comando:

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

    ... per aggiungere una finestra al gruppo.

    Alt+ R, eseguendo il comando:

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

    ... per aumentare il gruppo.

    Alt+ C, eseguendo il comando:

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

    ... per cancellare il gruppo

Spiegazione

Lo script funziona semplicemente:

  • Quando eseguito con l'argomento add, lo script memorizza / aggiunge l'id della finestra della finestra attiva in un file nascosto~/.windowlist
  • Quando eseguito con l'argomento raise, lo script legge il file, solleva le finestre nell'elenco con il comando:

    wmctrl -ia <window_id>
  • Quando eseguito con l'argomento clear, lo script rimuove il file nascosto ~/.windowlist.

Appunti

  • Lo script funziona anche su finestre ridotte a icona, minimizza eventualmente finestre ridotte a icona
  • Se il set di finestre si trova su un'altra finestra, lo script passerà alla finestra corrispondente
  • Il set è flexibel, puoi sempre aggiungere altre finestre al set corrente.

Più flessibilità?

Come accennato, lo script sopra consente di aggiungere finestre in qualsiasi momento alle finestre raggruppate. La versione seguente consente anche di rimuovere qualsiasi finestra (in qualsiasi momento) dall'elenco raggruppato:

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

L'argomento aggiuntivo per eseguire lo script è delete, quindi:

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

elimina la finestra attiva dalle finestre raggruppate. Per eseguire questo comando, sul mio sistema, ho impostato Alt+ Dcome collegamento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.