Les grands IDE JetBrains (IDEA et autres) attribuent pratiquement tous les raccourcis clavier imaginables à certaines fonctions. Bien que légèrement accablant par moments, il permet également une utilisation efficace.
Mon problème est que Unity assigne également certains de ces raccourcis, qui sont prioritaires. Un exemple particulièrement agaçant est CTRL + ALT + L. La question a été explorée auparavant ici .
Cependant, aucune des approches n'est satisfaisante.
Existe-t-il un moyen de désactiver les raccourcis système uniquement lorsqu'une application donnée est active, c'est-à-dire en cours d'exécution et active?
Je serais prêt à exécuter un script chaque fois que je lance l'application.
Le script ci-dessous désactivera des raccourcis clavier spécifiques lorsque la fenêtre d'une application arbitraire est active.
Bien que vous ayez mentionné "", je serais prêt à exécuter un script chaque fois que je lance l'application. ", il n'y a aucune raison de supprimer le script par la suite. , il est extrêmement faible en jus.
#!/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
Le script a besoin de xdotool
:
Sudo apt-get install xdotool
Copiez le script dans un fichier vide, enregistrez-le sous le nom disable_shortcuts.py
Dans la tête du script, remplacez dans la ligne:
app = "gedit"
"gedit" par votre application, ce qui signifie: le nom du processus propriétaire de la fenêtre.
Test-exécuter le script par la commande:
python3 /path/to/disable_shortcuts.py
Si tout fonctionne correctement, ajoutez-le à Applications de démarrage: Dash> Applications de démarrage> Ajouter. Ajoutez la commande:
/bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
A titre d'exemple, j'ai ajouté le raccourci que vous avez mentionné: CTRL + ALT + L. Les raccourcis sont définis dans la base de données dconf
et peuvent être définis ou désactivés à l'aide de gsettings
.
Dans le script, ces entrées gsettings
sont définies dans la fonction: setkeys()
def setkeys(val):
# --- add the keys to be disabled below
keys = [
["org.gnome.settings-daemon.plugins.media-keys", "screensaver"]
]
# ---
Un exemple pour ajouter (désactiver) le raccourci de déconnexion:
dconf watch /
Re-définir le raccourci à lui-même. Dans le terminal, vous pouvez voir la touche gsettings
qui appartient au raccourci:
Nous devons maintenant ajouter la clé trouvée (sous une apparence légèrement différente):
["org.gnome.settings-daemon.plugins.media-keys", "logout"]
... à la liste "clés" de notre fonction:
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"],
]
Maintenant les deux CTRL + ALT + L et CTRL + ALT + Delete sont désactivés si votre application est devant.
Comme mentionné, les raccourcis, comme ceux que vous avez mentionnés, sont définis dans la base de données dconf
. Dans l'exemple CTRL + ALT + L, la clé pour définir ou éditer le schortcut est:
org.gnome.settings-daemon.plugins.media-keys screensaver
Pour désactiver la clé, la commande est la suivante:
gsettings set org.gnome.settings-daemon.plugins.media-keys screensaver ""
Pour réinitialiser la clé à sa valeur par défaut:
gsettings reset org.gnome.settings-daemon.plugins.media-keys screensaver
Le script recherche une fois par seconde si:
encore (seulement) si oui, il désactive les raccourcis, listés dans
# --- add the keys to be disabled below
keys = [
["org.gnome.settings-daemon.plugins.media-keys", "screensaver"],
["org.gnome.settings-daemon.plugins.media-keys", "logout"],
]
... en attente du prochain changement d'état.
Si la fenêtre active ne fait plus partie de votre application, les clés mentionnées dans la liste sont réinitialisées.
Comme mentionné précédemment, la charge supplémentaire imposée au processeur du script est le nihil. Vous pouvez très bien l'exécuter au démarrage, comme expliqué dans "Comment utiliser".
Comme indiqué dans les commentaires, dans le cas spécifique d'OP, il est utile d'appliquer des raccourcis désactivants sur un groupe d'applications, qui résident tous dans un seul répertoire.
Ci-dessous une version à appliquer sur toutes les applications dont la sortie de
pgrep -f
comprendra un répertoire spécifique. Dans mon exemple, j'ai défini le répertoire /opt
. Ainsi, si la fenêtre active est l'une des applications de /opt
, les raccourcis définis seront désactivés.
si vous ouvrez une fenêtre de l'une des applications dans/opt avant, le raccourci de déconnexion sera désactivé.
réactiver le raccourci si une autre fenêtre devient active
#!/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
Comme le premier script, xdotool
doit être installé:
Sudo apt-get install xdotool
Copiez le script dans un fichier vide, enregistrez-le sous le nom disable_shortcuts.py
Dans la tête du script, remplacez dans la ligne:
appdir = "/opt"
"/ opt" par le répertoire de vos applications.
Test-exécuter le script par la commande:
python3 /path/to/disable_shortcuts.py
Si tout fonctionne correctement, ajoutez-le à Applications de démarrage: Dash> Applications de démarrage> Ajouter. Ajoutez la commande:
/bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
L'ajout d'autres raccourcis à la liste fonctionne exactement de la même manière que la version 1 du script.
Dans votre réponse, vous mentionnez:
xprop ne révèle pas les PID pour toutes les fenêtres. Exemple manquant: chronomètre.
Les fenêtres avec pid (comme tkinter windows, y compris Idle), n'ont pas d'identifiant de fenêtre dans la sortie de xprop -id
. Idle
ne possède pas de raccourcis contradictoires, mais dans mon expérience. Si vous rencontrez une application avec le pid 0 qui nécessiterait la désactivation de raccourcis spécifiques, veuillez l'indiquer.
Dans ce cas, une issue possible serait de convertir la sortie de
xdotool getactivewindow
au format hexadécimal, le format wmctrl
utilise, puis recherche le pid
correspondant dans la sortie de
wmctrl -lp
Bien que cela paraisse la chose la plus évidente au début, je ne l’ai pas utilisé dans le script pour le garder aussi léger que possible.
Basé sur (une ancienne version de) la réponse de Jacob Vlijm j'ai écrit cette version qui résout ces problèmes supplémentaires:
gsettings
et dconf
.Problèmes ouverts:
xprop
ne révèle pas les PID pour toutes les fenêtres. Exemple défaillant: stopwatch
. ( Jaco Vlijm a quelques idées .)#!/usr/bin/env python3
import subprocess
import time
import os
# Path pattern to block
apppattern = "myprocess"
# Write a backup that can restore the settings at the
# start of the script.
# Leave empty to not write a backup.
backupfile = "~/.keymap_backup"
# Add the keys to be disabled below.
shortcuts = {
"org.gnome.settings-daemon.plugins.media-keys/key" : "gsettings",
"/org/gnome/desktop/wm/keybindings/key" : "dconf",
}
#
# Helper functions
#
# Run a command on the Shell
def run(cmd):
subprocess.Popen(cmd)
# Run a command on the Shell and return the
# stripped result
def get(cmd):
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except:
pass
# Get the PID of the currently active window
def getactive():
xdoid = get(["xdotool", "getactivewindow"])
pidline = [l for l in get(["xprop", "-id", xdoid]).splitlines()\
if "_NET_WM_PID(CARDINAL)" in l]
if pidline:
pid = pidline[0].split("=")[1].strip()
else:
# Something went wrong
print("Warning: Could not obtain PID of current window")
pid = ""
return pid
def readkey(key):
if shortcuts[key] == "gsettings":
return get(["gsettings", "get"] + key.split("/"))
Elif shortcuts[key] == "dconf":
return get(["dconf", "read", key])
def writekey(key, val):
if val == "":
val = "['']"
if shortcuts[key] == "gsettings":
run(["gsettings", "set"] + key.split("/") + [val])
Elif shortcuts[key] == "dconf":
run(["dconf", "write", key, val])
def resetkey(key):
if shortcuts[key] == "gsettings":
run(["gsettings", "reset"] + key.split("/"))
Elif shortcuts[key] == "dconf":
run(["dconf", "reset", key])
# If val == True, disables all shortcuts.
# If val == False, resets all shortcuts.
def setkeys(flag):
for key, val in shortcutmap.items():
if flag == True:
# Read current value again; user may change
# settings, after all!
shortcutmap[key] = readkey(key)
writekey(key, "")
Elif flag == False:
if val:
writekey(key, val)
else:
resetkey(key)
#
# Main script
#
# Store current shortcuts in case they are non-default
# Note: if the default is set, dconf returns an empty string!
# Optionally, create a backup script to restore the value in case
# this script crashes at an inopportune time.
shortcutmap = {}
if backupfile:
f = open(os.path.expanduser(backupfile),'w+')
f.write('#!/bin/sh\n')
for key, val in shortcuts.items():
if shortcuts[key] == "gsettings":
shortcutmap[key] = get(["gsettings", "get"] + key.split("/"))
if backupfile:
if shortcutmap[key]:
f.write("gsettings set " + " ".join(key.split("/")) + " " +
shortcutmap[key] + "\n")
else:
f.write("gsettings reset " + " ".join(key.split("/")) + "\n")
Elif shortcuts[key] == "dconf":
shortcutmap[key] = get(["dconf", "read", key])
if backupfile:
if shortcutmap[key]:
f.write("dconf write " + key + " " + shortcutmap[key] + "\n")
else:
f.write("dconf reset " + key + "\n")
if backupfile: f.close()
# Check every half second if the window changed form or to a
# matching application.
front1 = None
while True:
time.sleep(0.5)
checkpids = get(["pgrep", "-f", apppattern])
if checkpids:
checkpids = checkpids.splitlines()
activepid = getactive()
#print(activepid)
if activepid:
front2 = True if activepid in checkpids else False
else:
front2 = False
else:
front2 = False
if front2 != front1:
#print("Matches: " + str(flag))
if front2:
setkeys(True)
else:
setkeys(False)
front1 = front2
Notes:
gsettings
resp. dconf
.gsettings
font dans dconf
, mais les modifications apportées n'ont aucun effet. En règle générale, ajoutez les clés trouvées en utilisant méthode de Jacob en tant que gsettings
et celles que vous avez dû rechercher manuellement dans dconf
en tant que telles.