Wie kann ich Fenster gruppieren, die als eines angehoben werden sollen?

10

Ich habe zwei Fenster, A und B. Ist es möglich, zwei Fenster irgendwie miteinander zu verbinden, so dass das Umschalten auf A auch B oder das Umschalten auf B auch A auslöst?

Ich verstehe, dass die Verwendung mehrerer Arbeitsbereiche eine alternative Option ist, habe mich aber gefragt, ob dies auch möglich ist?

Simon Tong
quelle
Z-Reihenfolge ist nicht besonders wichtig, aber wenn möglich, wäre das großartig
Simon Tong
Ich denke, mehrere Arbeitsplätze sind bei weitem die einfachste Lösung. Sie kennen die Tastenkombinationen für den Wechsel zwischen ihnen?
Thomasrutter
1
Sie sind ein schneller Akzeptant :) Trotzdem würde ich mich freuen, wenn Sie meine Antwort kommentieren würden.
Jacob Vlijm
5
Mögliches Duplikat der Fenstergruppierung?

Antworten:

9

Einführung

Das folgende Skript ermöglicht die Auswahl von zwei Fenstern. Während beide Fenster geöffnet sind, werden beide Fenster geöffnet, wenn der Benutzer eines der beiden Fenster fokussiert. Wenn man beispielsweise die Witwen A und B verbindet, werden beide durch Hexen mit A oder B über andere Witwen erhoben.

Um das Skript zu stoppen, können Sie es killall link_windows.pyim Terminal verwenden oder eines der Fenster schließen und erneut öffnen. Sie können die Ausführung auch abbrechen, indem Sie in Xeinem der Popup-Dialogfelder zur Fensterauswahl auf die Schaltfläche "Schließen" klicken.

Mögliche Verbesserungen:

  • Mehrere Instanzen des Skripts können verwendet werden, um Paare von zwei Fenstern zu gruppieren. Wenn wir beispielsweise Fenster A, B, C und D haben, können wir A und B miteinander verbinden und C und D miteinander verbinden.
  • Mehrere Fenster können unter einem einzigen Fenster zusammengefasst werden. Wenn ich beispielsweise Fenster B mit A, C mit A und D mit A verbinde, bedeutet dies, dass ich alle 4 Fenster gleichzeitig öffnen kann, wenn ich immer zu A wechsle.

Verwendung

Führen Sie das Skript wie folgt aus:

python link_windows.py

Das Skript ist mit Python 3 kompatibel und kann daher auch als ausgeführt werden

python3 link_windows.py

Es gibt zwei Befehlszeilenoptionen:

  • --quietoder -qermöglicht das Stummschalten der GUI-Fenster. Mit dieser Option können Sie einfach mit der Maus auf zwei beliebige Fenster klicken, und das Skript beginnt, diese zu verknüpfen.
  • --helpoder -hdruckt die Verwendungs- und Beschreibungsinformationen.

Die -hOption erzeugt die folgenden Informationen:

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

Zusätzliche technische Informationen können über angezeigt werden pydoc ./link_windows.py. Dies ./bedeutet, dass Sie sich im selben Verzeichnis wie das Skript befinden müssen.

Einfacher Verwendungsprozess für zwei Fenster:

  1. Ein Popup wird angezeigt, in dem Sie aufgefordert werden, ein Fenster Nr. 1 auszuwählen, zu drücken OKoder zu drücken Enter. Der Mauszeiger wird zu einem Kreuz. Klicken Sie auf eines der Fenster, die Sie verknüpfen möchten.

  2. Ein zweites Popup wird angezeigt, in dem Sie aufgefordert werden, Fenster 2 auszuwählen, zu drücken OKoder zu drücken Enter. Der Mauszeiger wird wieder zu einem Kreuz. Klicken Sie auf das andere Fenster, das Sie verknüpfen möchten. Danach beginnt die Ausführung.

  3. Wenn Sie eines der beiden Fenster fokussieren, hebt das Skript das andere Fenster an, stellt jedoch den Fokus wieder auf das ursprünglich ausgewählte (Hinweis - mit einer Verzögerung von einer Viertelsekunde für beste Leistung), wodurch das Gefühl entsteht, dass Fenster miteinander verbunden sind.

Wenn Sie beide Male dasselbe Fenster auswählen, wird das Skript beendet. Wenn Sie zu irgendeinem Zeitpunkt auf die Schaltfläche zum Schließen des Popup-Dialogfelds klicken, wird das Skript beendet.

Skriptquelle

Auch als GitHub Gist erhältlich

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

Anmerkungen:

Sergiy Kolodyazhnyy
quelle
Prost, ich bin wirklich beeindruckt. time.sleepKann ich das Bit zwischen dem Umschalten auf Null setzen? Gibt es einen Grund für die Verzögerung?
Simon Tong
1
@simontong Sie können versuchen, diese Zeile wie auskommentieren # time.sleep(0.25)und es wird nicht ausgeführt. Der Grund dafür ist, sicherzustellen, dass jedes Fenster richtig angehoben wird. Nach meiner Erfahrung in der Vergangenheit musste ich Verzögerungen für den Betrieb unter Windows haben. Ich würde denken, dass eine Verzögerung von einer Viertelsekunde nicht so viel ist. Lassen Sie mich dem Skript nur noch eine Zeile hinzufügen, die es beschleunigen könnte. OK ?
Sergiy Kolodyazhnyy
@ Simontong OK, ich habe das Skript aktualisiert. Probieren Sie es jetzt. Sollte schneller wechseln
Sergiy Kolodyazhnyy
@simontong Ich werde das Skript mit ein paar kleinen Ergänzungen aktualisieren, um ein paar zusätzliche Funktionen hinzuzufügen. Ich werde Sie wissen lassen, sobald es fertig ist, bitte lassen Sie mich wissen, was Sie denken
Sergiy Kolodyazhnyy
@ Simontong hat zusätzliche Optionen zum Skript hinzugefügt, bitte überprüfen
Sergiy Kolodyazhnyy
6

Erhöhen Sie eine beliebige Anzahl von Fenstern als eins

Mit der folgenden Lösung können Sie eine beliebige Kombination aus zwei, drei oder mehr Fenstern auswählen , die kombiniert und mit einer Tastenkombination als eins angezeigt werden sollen.

Das Skript arbeitet mit drei Argumenten:

add

um das aktive Fenster zur Gruppe hinzuzufügen

raise

um die eingestellte Gruppe zu erhöhen

clear

Um die Gruppe zu löschen, können Sie eine neue Gruppe definieren

Das Skript

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

Wie benutzt man

  1. Das Skript benötigt wmctrlund xdotool:

    sudo apt-get install wmctrl xdotool
  2. Kopieren Sie das obige Skript in eine leere Datei und speichern Sie es unter groupwindows.py
  3. Testen Sie das Skript: Öffnen Sie zwei Terminalfenster und führen Sie den folgenden Befehl aus:

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

    in beiden. Decken Sie sie mit anderen Fenstern ab (oder minimieren Sie sie). Öffnen Sie ein drittes Terminalfenster und führen Sie den folgenden Befehl aus:

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

    Die ersten beiden Fenster werden als eins angehoben.

  4. Wenn alles einwandfrei funktioniert, erstellen Sie drei benutzerdefinierte Tastenkombinationen: Wählen Sie: Systemeinstellungen> "Tastatur"> "Tastenkombinationen"> "Benutzerdefinierte Tastenkombinationen". Klicken Sie auf das "+" und fügen Sie die folgenden Befehle zu drei separaten Verknüpfungen hinzu:

    Auf meinem System habe ich verwendet:

    Alt+ A, den Befehl ausführen:

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

    ... um der Gruppe ein Fenster hinzuzufügen.

    Alt+ R, den Befehl ausführen:

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

    ... um die Gruppe zu erheben.

    Alt+ C, den Befehl ausführen:

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

    ... um die Gruppe zu löschen

Erläuterung

Das Skript funktioniert ganz einfach:

  • Wenn adddas Skript mit dem Argument ausgeführt wird , speichert / fügt es die Fenster-ID des aktiven Fensters in eine versteckte Datei ein~/.windowlist
  • Wenn raisedas Skript mit dem Argument ausgeführt wird , liest es die Datei und öffnet die Fenster in der Liste mit dem folgenden Befehl:

    wmctrl -ia <window_id>
  • Wenn cleardas Skript mit dem Argument ausgeführt wird , entfernt es die versteckte Datei ~/.windowlist.

Anmerkungen

  • Das Skript funktioniert auch bei minimierten Fenstern und hebt möglicherweise minimierte Fenster auf
  • Befindet sich der Fenstersatz in einem anderen Ansichtsfenster, wechselt das Skript zum entsprechenden Ansichtsfenster
  • Das Set ist flexibel. Sie können dem aktuellen Set jederzeit weitere Fenster hinzufügen.

Mehr Flexibilität?

Wie bereits erwähnt, können Sie mit dem obigen Skript jederzeit Fenster zu den gruppierten Fenstern hinzufügen. In der folgenden Version können Sie auch jedes Fenster (jederzeit) aus der gruppierten Liste entfernen :

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

Das zusätzliche Argument zum Ausführen des Skripts lautet delete:

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

löscht das aktive Fenster aus den gruppierten Fenstern. Um diesen Befehl auszuführen, habe ich auf meinem System Alt+ Dals Verknüpfung festgelegt.

Jacob Vlijm
quelle