introduction
Le script suivant permet de sélectionner deux fenêtres, et bien que les deux fenêtres soient ouvertes, il soulèvera les deux fenêtres lorsque l'utilisateur se concentrera sur l'une d'entre elles. Par exemple, si l'on relie les veuves A et B, le fait de passer à A ou B les fera s'élever au-dessus des autres veuves.
Pour arrêter le script, vous pouvez utiliser killall link_windows.py
dans le terminal, ou fermer et rouvrir l'une des fenêtres. Vous pouvez également annuler l'exécution en appuyant sur Xle bouton de fermeture dans l'une des boîtes de dialogue contextuelles de sélection de fenêtre.
Ajustements potentiels:
- plusieurs instances du script peuvent être utilisées pour regrouper des paires de deux fenêtres. Par exemple, si nous avons des fenêtres A, B, C et D, nous pouvons lier A et B ensemble, et lier C et D ensemble.
- plusieurs fenêtres peuvent être regroupées sous une seule fenêtre. Par exemple, si je relie la fenêtre B à A, C à A et D à A, cela signifie que si je passe toujours à A, je peux ouvrir les 4 fenêtres en même temps.
Usage
Exécutez le script en tant que:
python link_windows.py
Le script est compatible avec Python 3, il peut donc également s'exécuter en tant que
python3 link_windows.py
Il existe deux options de ligne de commande:
--quiet
ou -q
, permet de faire taire les fenêtres de l'interface graphique. Avec cette option, vous pouvez simplement cliquer avec la souris sur deux fenêtres et le script commencera à les lier.
--help
ou -h
imprime les informations d'utilisation et de description.
L' -h
option produit les informations suivantes:
$ 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.
Des informations techniques supplémentaires peuvent être consultées via pydoc ./link_windows.py
, où ./
signifie que vous devez être dans le même répertoire que le script.
Processus d'utilisation simple pour deux fenêtres:
Une fenêtre apparaîtra vous demandant de sélectionner une fenêtre # 1, appuyez OKou appuyez sur Enter. Le pointeur de la souris se transforme en croix. Cliquez sur l'une des fenêtres que vous souhaitez lier.
Une deuxième fenêtre apparaîtra vous demandant de sélectionner la fenêtre # 2, appuyez OKou appuyez sur Enter. Encore une fois, le pointeur de la souris se transforme en croix. Cliquez sur l'autre fenêtre que vous souhaitez lier. Après cette exécution commencera.
Chaque fois que vous concentrez l'une des fenêtres, le script fait monter l'autre fenêtre, mais ramène le focus à celle initialement sélectionnée (note - avec un quart de seconde de retard pour de meilleures performances), créant ainsi l'impression que les fenêtres sont liées entre elles.
Si vous sélectionnez la même fenêtre les deux fois, le script se fermera. Si à tout moment vous cliquez sur le bouton Fermer de la boîte de dialogue contextuelle, le script se fermera.
Source de script
Également disponible en 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()
Remarques: