Los grandes IDE de JetBrains (IDEA et al.) asignan prácticamente todos los atajos de teclado imaginables a alguna función. Si bien a veces es un poco abrumador, también permite un uso eficiente.
Mi problema es que Unity también asigna algunos de estos accesos directos y tienen prioridad. Un ejemplo particularmente molesto es CTRL + ALT + L . El problema se ha explorado antes aquí.
Sin embargo, ninguno de los enfoques es satisfactorio.
- Desactivar accesos directos del sistema globalmente impide mi productividad general con el sistema.
- Cambiar a un mapa de teclas diferente en IDEA me confundirá mucho cuando desarrolle en diferentes plataformas (y tenga que elegir diferentes asignaciones).
¿Hay alguna manera de desactivar los accesos directos del sistema solo cuando una determinada aplicación está activa, es decir, ejecutándose y enfocada?
Estaría dispuesto a ejecutar un script cada vez que inicie la aplicación.
Respuesta aceptada:
Cómo deshabilitar automáticamente múltiples accesos directos (específicos) si (y mientras) la ventana de una aplicación específica esté activa
El siguiente script deshabilitará atajos de teclado específicos cuando la ventana de una aplicación arbitraria esté activa.
Aunque mencionaste""Estaría dispuesto a ejecutar un script cada vez que inicie la aplicación". , No hay razón para matar el guión después, es extremadamente bajo en jugo.
El guión
#!/usr/bin/env python3
import subprocess
import time
import os
app = "gedit"
f = os.path.join(os.environ["HOME"], "keylist")
def run(cmd):
subprocess.Popen(cmd)
def get(cmd):
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except:
pass
def getactive():
return get(["xdotool", "getactivewindow"])
def setkeys(val):
# --- add the keys to be disabled below
keys = [
["org.gnome.settings-daemon.plugins.media-keys", "logout"],
["org.gnome.settings-daemon.plugins.media-keys", "screensaver"],
]
# ---
writelist = []
if not val:
try:
values = open(f).read().splitlines()
except FileNotFoundError:
values = []
for i, key in enumerate(keys):
try:
cmd = ["gsettings", "set"]+key+[values[i]]
except IndexError:
cmd = ["gsettings", "reset"]+key
run(cmd)
else:
for key in keys:
cmd = ["gsettings", "set"]+key+["['']"]
read = get(["gsettings", "get"]+key)
writelist.append(read)
run(cmd)
if writelist:
open(f, "wt").write("n".join(writelist))
front1 = None
while True:
time.sleep(1)
pid = get(["pgrep", app])
if pid:
try:
active = get(["xdotool", "getactivewindow"])
relevant = get(["xdotool", "search", "--all", "--pid", pid]).splitlines()
front2 = active in relevant
except AttributeError:
front2 = front1
else:
front2 = False
if front2 != front1:
if front2:
setkeys(True)
else:
setkeys(False)
front1 = front2
Cómo usar
-
El script necesita
xdotool
:sudo apt-get install xdotool
-
Copie el script en un archivo vacío, guárdelo como
disable_shortcuts.py
-
En el encabezado del script, reemplace en la línea:
app = "gedit"
"gedit" por su aplicación, lo que significa:el nombre del proceso que posee la ventana.
-
Pruebe el script con el comando:
python3 /path/to/disable_shortcuts.py
-
Si todo funciona bien, agréguelo a Aplicaciones de inicio:Tablero> Aplicaciones de inicio> Agregar. Agregue el comando:
/bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
Agregar más accesos directos para deshabilitar
Como ejemplo, agregué el atajo que mencionaste:CTRL + ALT + L . Los accesos directos se establecen en el dconf
base de datos, y se puede configurar o deshabilitar usando gsettings
.
En el script, estos gsettings
las entradas se establecen en la función:setkeys()
def setkeys(val):
# --- add the keys to be disabled below
keys = [
["org.gnome.settings-daemon.plugins.media-keys", "screensaver"]
]
# ---
Un ejemplo para agregar (deshabilitar) el acceso directo para cerrar sesión:
- Abra una ventana de terminal, ejecute el comando
dconf watch /
- Abra Configuración del sistema> "Teclado"> "Accesos directos"> "Sistema"
-
Vuelva a configurar el acceso directo a sí mismo. En la terminal, puedes ver la
gsettings
tecla que pertenece al atajo: -
Ahora tenemos que agregar la clave encontrada (en una apariencia ligeramente diferente):
["org.gnome.settings-daemon.plugins.media-keys", "logout"]
…a la lista de “claves” en nuestra función:
def setkeys(val): # --- add the keys to be disabled below keys = [ ["org.gnome.settings-daemon.plugins.media-keys", "screensaver"], ["org.gnome.settings-daemon.plugins.media-keys", "logout"], ]
Ahora ambos CTRL + ALT + L y CTRL + ALT + Eliminar están deshabilitados si su aplicación está al frente.
Relacionado:¿Relación de distribución de teclado y xmodmap?Explicación
Como se mencionó, los atajos, como los que mencionas, se establecen en el dconf
base de datos. En el ejemplo CTRL + ALT + L , la clave para establecer o editar el atajo es:
org.gnome.settings-daemon.plugins.media-keys screensaver
Para deshabilitar la clave, el comando es:
gsettings set org.gnome.settings-daemon.plugins.media-keys screensaver ""
Para restablecer la clave a su valor predeterminado:
gsettings reset org.gnome.settings-daemon.plugins.media-keys screensaver
El script se ve una vez por segundo si:
- su aplicación se ejecuta en absoluto
- si es así, mira si alguna de sus ventanas está activa
-
de nuevo (solo) si es así, deshabilita los accesos directos, enumerados en
# --- add the keys to be disabled below keys = [ ["org.gnome.settings-daemon.plugins.media-keys", "screensaver"], ["org.gnome.settings-daemon.plugins.media-keys", "logout"], ]
…esperando el próximo cambio de estado.
Si la ventana activa ya no es una de sus aplicaciones, las teclas mencionadas en la lista se restablecen a los valores predeterminados.
Nota
Como se mencionó anteriormente, la carga adicional para el procesador del script es nula. Podría muy bien ejecutarlo al inicio, como se explica en "Cómo usarlo".
Afectando a múltiples aplicaciones
Como se discutió en los comentarios, en el caso específico de OP, es útil aplicar accesos directos de desactivación en un grupo de aplicaciones, todas residiendo en un directorio.
Debajo de una versión para aplicar esto en todas las aplicaciones de las cuales la salida de
pgrep -f
incluirá un directorio específico. En mi ejemplo, configuré /opt
directorio, por lo que si la ventana activa es una de las aplicaciones en /opt
, los accesos directos establecidos se desactivarán.
traer una ventana de una de las aplicaciones en /opt al frente desactivará el atajo de cierre de sesión
volver a habilitar el acceso directo si otra ventana recibe el foco
El guión
#!/usr/bin/env python3
import subprocess
import time
import os
appdir = "/opt"
f = os.path.join(os.environ["HOME"], "keylist")
def run(cmd):
subprocess.call(cmd)
def get(cmd):
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except:
pass
def getactive():
return get(["xdotool", "getactivewindow"])
def setkeys(val):
# --- add the keys to be disabled below
keys = [
["org.gnome.settings-daemon.plugins.media-keys", "logout"],
["org.gnome.settings-daemon.plugins.media-keys", "screensaver"],
["org.gnome.desktop.wm.keybindings", "begin-move"],
]
# ---
writelist = []
if not val:
try:
values = open(f).read().splitlines()
except FileNotFoundError:
values = []
# for key in keys:
for i, key in enumerate(keys):
try:
cmd = ["gsettings", "set"]+key+[values[i]]
except IndexError:
cmd = ["gsettings", "reset"]+key
run(cmd)
else:
for key in keys:
cmd = ["gsettings", "set"]+key+["['']"]
read = get(["gsettings", "get"]+key)
writelist.append(read)
run(cmd)
if writelist:
open(f, "wt").write("n".join(writelist))
front1 = None
while True:
time.sleep(1)
# check if any of the apps runs at all
checkpids = get(["pgrep", "-f", appdir])
# if so:
if checkpids:
checkpids = checkpids.splitlines()
active = getactive()
# get pid frontmost (doesn't work on pid 0)
match = [l for l in get(["xprop", "-id", active]).splitlines()
if "_NET_WM_PID(CARDINAL)" in l]
if match:
# check if pid is of any of the relevant apps
pid = match[0].split("=")[1].strip()
front2 = True if pid in checkpids else False
else:
front2 = False
else:
front2 = False
if front2 != front1:
if front2:
setkeys(True)
else:
setkeys(False)
front1 = front2
Cómo usar
-
Como el primer script,
xdotool
necesita ser instalado:sudo apt-get install xdotool
-
Copie el script en un archivo vacío, guárdelo como
disable_shortcuts.py
-
En el encabezado del script, reemplace en la línea:
appdir = "/opt"
“/opt” por el directorio donde se encuentran sus aplicaciones.
-
Pruebe el script con el comando:
python3 /path/to/disable_shortcuts.py
-
Si todo funciona bien, agréguelo a Aplicaciones de inicio:Tablero> Aplicaciones de inicio> Agregar. Agregue el comando:
/bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
Agregar otros accesos directos a la lista funciona exactamente de manera similar a la versión 1 del script.
Relacionado:¿No se puede actualizar Logitech Unify Firmware usando fwupd?¿Funciona en todas las aplicaciones?
En su respuesta, menciona:
xprop no revela los PID para todas las ventanas. Ejemplo fallido:cronómetro.
Windows con pid 0 (como tkinter windows, incluido Idle), no tiene window- id en la salida de xprop -id
. Idle
no tiene ningún atajo en conflicto, aunque en mi experiencia. Si se encuentra con alguna aplicación con pid 0 que requiera deshabilitar accesos directos específicos, menciónelo.
En ese caso, un posible escape sería convertir la salida de
xdotool getactivewindow
a hexadecimal, el formato wmctrl
usa, y luego busca el pid
correspondiente en la salida de
wmctrl -lp
Aunque eso parecía lo más obvio para empezar, no lo usé en el guión para mantener el guión lo más ligero posible.