J'ai 3 moniteurs sur ma machine de développement, qui exécute Ubuntu + Unity. Je dédie généralement un moniteur à la navigation Web et à la messagerie instantanée, et les deux autres aux terminaux sur lesquels je lance vim ou saisis des commandes. Je cherche une séquence à touche unique pour basculer entre eux à volonté.
Je voudrais savoir comment je peux passer au focus sur les fenêtres (supérieures) de chaque moniteur. Le comportement que je recherche ou qui ressemble à ALT + TAB, à la différence qu'au lieu de faire la rotation entre applications (ce qui rend uniquement l'instance d'application la plus récemment utilisée disponible dans la rotation), je peux faire pivoter le focus entre les moniteurs.
En guise de compromis, je pourrais utiliser le mécanisme ALT + TAB si je pouvais avoir chacune des fenêtres de la liste. J'imagine toujours que cela devient agaçant, cependant.
Dans la configuration ci-dessous, deux scripts sont impliqués: un script d'arrière-plan pour conserver l'historique des fenêtres ciblées (voir l'explication en bas pour savoir pourquoi cela est nécessaire), et un script "action" à placer sous une touche de raccourci pour définir le focus sur l'écran suivant. Si l’écran suivant n’a pas de fenêtre sur laquelle activer le focus, un message s’affiche:
Script 1; le script d'arrière-plan, enregistrez-le (exactement) sous le nom focus_track.py
#!/usr/bin/env python3
import subprocess
import time
import os
rootdata = os.environ["HOME"]+"/.focus_history"
def get_screendata():
return sorted([int(s.split("+")[-2]) for s in subprocess.check_output(["xrandr"]).decode("utf-8").split() if s.count("+") == 2])
def current_windows():
try:
return subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8")
except subprocess.CalledProcessError:
pass
def convert_format(w_id):
return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]
def read_data():
return open(rootdata).read().splitlines()
def get_top(wlist):
top = convert_format([l.split("#")[-1].strip() for l in \
subprocess.check_output(["xprop", "-root"]).decode("utf-8").splitlines() \
if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0])
return [l for l in wlist if top in l][0]
if __== "__main__":
open(rootdata, "wt").write("This is an empty line")
while True:
time.sleep(1)
wdata = current_windows()
if wdata != None:
wlist = wdata.splitlines()
# get frontmost window (as in wmctrl -lG)
top = get_top(wlist)
oldlist = read_data()
if not top == oldlist[0]:
# clean up closed windows
[oldlist.remove(l) for l in oldlist if not l.split()[0] in wdata]
# remove possible other mentions of the active window
[oldlist.remove(l) for l in oldlist if l.startswith(top.split()[0])]
open(rootdata, "wt").write(("\n").join([top]+oldlist))
Script 2; le script d’action, enregistrez-le sous le nom next_focus.py
dans un seul et même répertoire comme script 1 .
#!/usr/bin/env python3
import subprocess
import focus_track
# read existing windows and their order (x-wise) from file
windows = [w.split() for w in focus_track.read_data()]
w_data = [[w[0], int(w[2])] for w in windows]
# get position of currently focussed window
currfocus = focus_track.get_top(focus_track.current_windows().splitlines()).split()[2]
# get screendata
screens = focus_track.get_screendata()
def screen_pos(x):
return [(int(x) > n) for n in screens].count(True)
scr_position = screen_pos(currfocus)
next_screen = 1 if scr_position == len(screens) else scr_position+1
try:
next_focus = [w for w in w_data if screen_pos(w[1]) == next_screen][0]
subprocess.Popen(["wmctrl", "-ia", next_focus[0]])
except IndexError:
subprocess.Popen(["notify-send", "No window to focus on next screen"])
Les scripts ont besoin de wmctrl
pour être installé
Sudo apt-get install wmctrl
focus_track.py
. Le nom est important car les deux scripts partagent des fonctions; le script 1 est importé dans le script 2.next_focus.py
dans un seul et même répertoire que le script 1 .Testez - lancez la configuration: N.B. Lancez le script d'arrière-plan avant d'ouvrir (et donc de focaliser) sur les fenêtres. Les fenêtres ouvertes avant le démarrage du script d'arrière-plan ne sont pas "enregistrées" jusqu'à ce qu'elles soient focalisées
Démarrez le script d’arrière-plan (à partir d’un terminal, par exemple) à l’aide de la commande suivante:
python3 /path/to/focus_track.py
Sur vos différents écrans, ouvrez des fenêtres.
Exécutez le script 2 avec la commande:
python3 /path/to/next_focus.py
La mise au point devrait passer à l'écran suivant. Si l'écran actuel est le dernier de la ligne, le focus passe au premier écran.
Si tout fonctionne correctement, ajoutez le script 1 à Applications de démarrage: Tableau de bord> Applications de démarrage> Ajoutez la commande:
python3 /path/to/focus_track.py
et ajoutez le script 2 à un raccourci clavier: choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande:
python3 /path/to/next_focus.py
à une touche de raccourci de votre goût.
Pour basculer le focus d'un écran à un autre, il est nécessaire de déterminer quelle est la fenêtre la plus frontale par écran . Le problème majeur est cependant que les fenêtres, réparties sur plusieurs écrans, sont en réalité toutes dans une seule et même pile, et donc ordonnées dans une même succession (z-wise). Les outils dont nous disposons (wmctrl
, xdotool
, xprop
etc.) ne peuvent dans le meilleur des cas que déterminer la fenêtre actuellement active . Ils ne nous donnent aucune information sur l'ordre des fenêtres sur les autres écrans, car les fenêtres sont en dessous de la fenêtre active .
Par conséquent, à première vue, il semble pratiquement impossible de passer de l’écran à l’autre.
Pourtant:
Cependant, avec une solution de contournement, il existe un échappement: si nous faisons un script d’arrière-plan, gardons une trace de la fenêtre actuellement focalisée et conservons un enregistrement historique des modifications (tant que la fenêtre existe), nous avons peut conclure quel est l'ordre z des fenêtres actuellement ouvertes. Si nous gardons également trace de leur géométrie et de leur position, nous avons toutes les informations dont nous avons besoin.
Un exemple:
Nous avons actuellement cinq fenêtres: A, B, C, D, E. Si leur mise au point change en fonction de D, E, A, C, B, nous savons que l’ordre z des fenêtres est: B, C , A, E, D (de l'avant à l'arrière)
Avec leurs positions (en x) et les données d'écran (la résolution x des écrans), nous avons toutes les informations dont nous avons besoin. Pour passer à l’écran suivant, il suffit de regarder la première fenêtre, située sur l’écran suivant.