Hago la mayor parte de mi trabajo en dos aplicaciones: mi navegador web y mi editor. Cambio de un lado a otro con frecuencia con Alt-Tab. También tengo un cliente de mensajería instantánea (Hipchat) abierto en todo momento, pero interactúo con él solo en raras ocasiones en comparación con las otras dos aplicaciones.
Una molestia recurrente es que después de interactuar con la ventana de Hipchat y Alt-Tab de regreso a (por ejemplo) mi editor, mi memoria muscular se sintoniza para esperar que otra Alt-Tab se enfoque en mi navegador, pero termino en Hipchat nuevamente.
¿Hay alguna forma de hacer que Hipchat se envíe al final de la pila o lista de lo último o lo que sea, después de que pierde el foco por cualquier medio?
Lo que pides es en realidad permitir que la ventana de una aplicación específica solo aparezca en la primera o la última posición, z-wise.
Cuando la ventana gedit (en este ejemplo) pierde el foco, se envía a la última posición (z-wise, debajo de la ventana de terminal semitransparente) en lugar de descender solo una posición :
Si bien se puede hacer, todavía tenemos que superar algunas complicaciones graves; Cuando la ventana se envía a la última posición, querrá mantener el orden z de todas las demás ventanas. Sin embargo, actualmente, no hay herramientas que nos puedan dar este orden z de ventanas. Tanto xdotool
como wmctrl
no nos dan información sobre esto.
Sin embargo, lo que podemos hacer es hacer un seguimiento del historial de enfoque de (todas) las ventanas. Dado que una ventana desciende una posición si otra ventana obtiene el foco, podemos concluir el orden z de las ventanas si ejecutamos un script de fondo para ver el historial de foco de las ventanas.
La solución a continuación existe de dos pequeños scripts de fondo, para ejecutarse simultáneamente.
focus_history.py
set_z.py
focus-history.py
#!/usr/bin/env python3
import subprocess
import time
import os
rootdata = os.environ["HOME"]+"/.focus_history"
open(rootdata, "wt").write("This is an empty line")
def current_windows():
try:
return subprocess.check_output(["wmctrl", "-lp"]).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):
try:
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]
except IndexError:
pass
if __== "__main__":
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 any([top == oldlist[0], top == None]):
# 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))
#!/usr/bin/python3
import subprocess
import time
import focus_history
# --- set the process name of your application below
proc = "gedit"
# ---
focus_hist = focus_history.rootdata
def get(val):
try:
return subprocess.check_output(val).decode("utf-8").strip()
except subprocess.CalledProcessError:
pass
def front_w():
get_front = str(hex(int(get(["xdotool", "getactivewindow"]))))
return get_front[:2]+(10-len(get_front))*"0"+get_front[2:]
while True:
time.sleep(1)
pid = get(["pgrep", proc])
front1 = ""
while pid:
time.sleep(1)
frontpid = get(["xdotool", "getactivewindow", "getwindowpid"])
front2 = frontpid == pid
if front2 != front1:
if front2 == False:
zdata = [l for l in open(focus_hist).read().splitlines()]
wins = list(reversed([l.split()[0] for l in zdata if not pid in l]))
for w in wins+[front_w()]:
cmd = ["xdotool", "windowraise", w]
subprocess.call(cmd)
pid = get(["pgrep", proc])
front1 = front2
El script usa tanto wmctrl
como xdotool
Sudo apt-get install wmctrl xdotool
Copie el script 1 en un archivo vacío, guárdelo (¡exactamente!) Como focus_history.py
Copie el script 2 en un archivo vacío, guárdelo como set_z.py
en el mismo directorio como script 1.
En la sección principal del script, en la línea:
proc = "gedit"
reemplace "gedit"
por el nombre del proceso de su aplicación (entre comillas)
Pruebe a ejecutar el script: Antes de abrir cualquier ventana (adicional) , inicie el script 1 con el comando :
python3 /path/to/focus_history.py & python3 /path/to/set_z.py
[El script reconocerá las ventanas que se enfocaron al menos una vez. Ese será el caso si el script se ejecuta al iniciar sesión]
Como se mencionó, los scripts deben estar en el mismo directorio, en el mismo nivel.
Ahora comience a abrir ventanas y vea cómo se comporta. Su aplicación debe moverse al fondo (muy) si pierde el foco.
Si todo funciona bien, agréguelo a Aplicaciones de inicio: Tablero> Aplicaciones de inicio> Agregar. Agrega el comando:
/bin/bash -c "sleep 15 && python3 /path/to/focus_history.py & python3 /path/to/set_z.py"
Alternativamente, puede establecer una tecla de acceso directo para abrir la ventana de una aplicación específica si existe, como se explica aquí .
Sin embargo, eso requeriría tener otro acceso directo para volver a la ventana de la primera aplicación,
A menos que ...,
Configuraría un acceso directo para alternar entre dos aplicaciones. Sin embargo, eso estaría fuera del alcance de esta pregunta ...