it-swarm-es.tech

¿Puedo enviar automáticamente la ventana de una aplicación en particular a la posición z más baja, cuando pierde el foco?

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?

3
Sean

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 :

enter image description hereenter image description here


Posición Z de una ventana

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 dos pequeños scripts de fondo

La solución a continuación existe de dos pequeños scripts de fondo, para ejecutarse simultáneamente.

  1. Una secuencia de comandos para realizar un seguimiento del historial de enfoque: focus_history.py
  2. Un script para enviar la ventana de la aplicación de destino a la última posición si pierde el foco: set_z.py

Script 1

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))

Guión 2

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

Como instalar

  1. El script usa tanto wmctrl como xdotool

    Sudo apt-get install wmctrl xdotool
    
  2. Copie el script 1 en un archivo vacío, guárdelo (¡exactamente!) Como focus_history.py

  3. 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)

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

  5. Ahora comience a abrir ventanas y vea cómo se comporta. Su aplicación debe moverse al fondo (muy) si pierde el foco.

  6. 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"
    

Notas

  • la configuración supone que tiene una sola ventana abierta de la aplicación de destino. Por su pregunta, entiendo que ese es el caso.

Alternativamente

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

3
Jacob Vlijm