it-swarm.com.de

Blockieren Sie Unity-Tastaturkürzel, wenn eine bestimmte Anwendung aktiv ist

Die großartigen JetBrains-IDEs (IDEA et al.) Weisen so ziemlich jede denkbare Tastenkombination einer Funktion zu. Es ist manchmal leicht überwältigend, sorgt aber auch für eine effiziente Nutzung.

Mein Problem ist, dass Unity auch einige dieser Verknüpfungen zuweist und sie Vorrang haben. Ein besonders ärgerliches Beispiel ist CTRL + ALT + L. Das Problem wurde bereits untersucht hier .

Keiner der Ansätze ist jedoch zufriedenstellend.

  1. Das globale Deaktivieren von Systemverknüpfungen beeinträchtigt meine Gesamtproduktivität mit dem System.
  2. Das Wechseln zu einer anderen Keymap in IDEA wird mich verdammt verwirren, wenn ich auf verschiedenen Plattformen entwickle (und unterschiedliche Zuordnungen wählen muss).

Gibt es eine Möglichkeit, Systemverknüpfungen nur zu deaktivieren, wenn eine bestimmte Anwendung aktiv ist, d. H. Ausgeführt wird und sich im Fokus befindet?

Ich würde jedes Mal ein Skript ausführen, wenn ich die Anwendung starte.

5
Raphael

So deaktivieren Sie mehrere (bestimmte) Verknüpfungen automatisch, wenn (und solange) das Fenster einer bestimmten Anwendung aktiv ist

Das folgende Skript deaktiviert bestimmte Tastenkombinationen, wenn das Fenster einer beliebigen Anwendung aktiv ist.

Obwohl Sie "" erwähnt haben, wäre ich bereit, jedes Mal ein Skript auszuführen, wenn ich die Anwendung starte. ", Es gibt keinen Grund, das Skript danach zu beenden Es ist extrem saftarm.

Das Drehbuch

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

Wie benutzt man

  1. Das Skript benötigt xdotool:

    Sudo apt-get install xdotool
    
  2. Kopieren Sie das Skript in eine leere Datei und speichern Sie es als disable_shortcuts.py

  3. Ersetzen Sie im Kopf des Skripts in der Zeile:

    app = "gedit"
    

    "gedit" von Ihrer Anwendung, dh der Prozessname, dem das Fenster gehört.

  4. Führen Sie das Skript mit dem folgenden Befehl aus:

    python3 /path/to/disable_shortcuts.py
    
  5. Wenn alles funktioniert, fügen Sie es zu Startup Applications hinzu: Dash> Startup Applications> Add. Fügen Sie den Befehl hinzu:

    /bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
    

Hinzufügen weiterer zu deaktivierender Verknüpfungen

Als Beispiel habe ich die von Ihnen erwähnte Verknüpfung hinzugefügt: CTRL + ALT + L. Verknüpfungen werden in der Datenbank dconf festgelegt und können mit gsettings festgelegt oder deaktiviert werden.

Im Skript werden diese gsettings Einträge in der Funktion gesetzt: setkeys()

def setkeys(val):
    # --- add the keys to be disabled below
    keys = [
        ["org.gnome.settings-daemon.plugins.media-keys", "screensaver"]
        ]
    # ---

Ein Beispiel zum Hinzufügen (Deaktivieren) der Verknüpfung zum Abmelden:

  1. Öffnen Sie ein Terminalfenster und führen Sie den Befehl dconf watch / aus.
  2. Öffnen Sie die Systemeinstellungen> "Tastatur"> "Verknüpfungen"> "System".
  3. Setzen Sie die Verknüpfung auf sich selbst zurück. Im Terminal sehen Sie die Taste gsettings, die zur Verknüpfung gehört:

    enter image description here

  4. Jetzt müssen wir den gefundenen Schlüssel hinzufügen (in einem etwas anderen Erscheinungsbild):

    ["org.gnome.settings-daemon.plugins.media-keys", "logout"]
    

    ... zur "Tasten" Liste in unserer Funktion:

    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"],
            ]
    

Nun beide CTRL + ALT + L und CTRL + ALT + Delete sind deaktiviert, wenn sich Ihre Anwendung vorne befindet.

Erläuterung

Wie bereits erwähnt, werden Verknüpfungen wie die von Ihnen erwähnten in der Datenbank dconf festgelegt. Im Beispiel CTRL + ALT + L, der Schlüssel zum Einstellen oder Bearbeiten des Kurzbefehls ist:

org.gnome.settings-daemon.plugins.media-keys screensaver

Der Befehl zum Deaktivieren der Taste lautet:

gsettings set org.gnome.settings-daemon.plugins.media-keys screensaver ""

So setzen Sie den Schlüssel auf seinen Standardwert zurück:

gsettings reset org.gnome.settings-daemon.plugins.media-keys screensaver

Das Skript sieht einmal pro Sekunde aus, wenn:

  • ihre Anwendung läuft überhaupt
  • in diesem Fall wird geprüft, ob eines der Fenster aktiv ist
  • wieder (nur) in diesem Fall werden die in aufgeführten Verknüpfungen deaktiviert

    # --- add the keys to be disabled below
    keys = [
        ["org.gnome.settings-daemon.plugins.media-keys", "screensaver"],
         ["org.gnome.settings-daemon.plugins.media-keys", "logout"],
       ]
    

    ... auf die nächste Zustandsänderung warten.

Wenn das aktive Fenster nicht mehr zu Ihrer Anwendung gehört, werden die in der Liste aufgeführten Schlüssel auf die Standardeinstellungen zurückgesetzt.

Hinweis

Wie bereits erwähnt, ist die zusätzliche Belastung für den Prozessor des Skripts gleich null. Sie können es sehr gut beim Start ausführen, wie unter "Verwendung" erläutert.


Auswirkungen auf mehrere Anwendungen

Wie in den Kommentaren erläutert, ist es im speziellen Fall von OP nützlich, deaktivierende Verknüpfungen für eine Gruppe von Anwendungen anzuwenden, die sich alle in einem Verzeichnis befinden.

Nachfolgend eine Version, um dies auf alle Anwendungen anzuwenden, von denen die Ausgabe von

pgrep -f 

wird ein bestimmtes Verzeichnis enthalten. In meinem Beispiel habe ich das Verzeichnis /opt festgelegt. Wenn das aktive Fenster eine der Anwendungen in /opt ist, werden die festgelegten Verknüpfungen deaktiviert.


Wenn Sie ein Fenster einer der Anwendungen in/opt nach vorne bringen, wird die Verknüpfung zum Abmelden deaktiviert

enter image description here

erneutes Aktivieren der Verknüpfung, wenn ein anderes Fenster den Fokus erhält

enter image description here


Das Drehbuch

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

Wie benutzt man

  1. Wie das erste Skript muss xdotool installiert werden:

    Sudo apt-get install xdotool
    
  2. Kopieren Sie das Skript in eine leere Datei und speichern Sie es als disable_shortcuts.py

  3. Ersetzen Sie im Kopf des Skripts in der Zeile:

    appdir = "/opt"
    

    "/ opt" für das Verzeichnis, in dem sich Ihre Anwendungen befinden.

  4. Führen Sie das Skript mit dem folgenden Befehl aus:

    python3 /path/to/disable_shortcuts.py
    
  5. Wenn alles funktioniert, fügen Sie es zu Startup Applications hinzu: Dash> Startup Applications> Add. Fügen Sie den Befehl hinzu:

    /bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
    

Das Hinzufügen weiterer Verknüpfungen zur Liste funktioniert genauso wie in Version 1 des Skripts.

Funktioniert es bei allen Anwendungen?

In Ihrer Antwort erwähnen Sie:

xprop zeigt PIDs nicht für alle Fenster an. Fehlerhaftes Beispiel: Stoppuhr.

Windows mit pid (wie tkinter windows, einschließlich Idle) haben keine window-id in der Ausgabe von xprop -id. Idle hat meiner Erfahrung nach keine Kollisionsverknüpfungen. Wenn Sie auf eine Anwendung mit PID 0 stoßen, für die bestimmte Verknüpfungen deaktiviert werden müssten, geben Sie dies bitte an.

In diesem Fall besteht ein möglicher Ausweg darin, die Ausgabe von zu konvertieren

xdotool getactivewindow

zum Hexen wird das Format wmctrl verwendet, und anschließend wird das entsprechende pid in der Ausgabe von nachgeschlagen

wmctrl -lp

Obwohl dies zunächst am naheliegendsten schien, habe ich es im Skript nicht verwendet, um das Skript so leicht wie möglich zu halten.

10
Jacob Vlijm

Basierend auf (eine ältere Version von) Jacob Vlijms Antwort Ich habe diese Version geschrieben, die diese zusätzlichen Probleme löst:

  1. Berücksichtigt Änderungen, die der Benutzer während der Ausführung des Skripts vornimmt.
  2. Setzt keine Werte zurück, die der Benutzer auf die Standardeinstellungen gesetzt hat.
  3. Speichert eine Sicherungskopie der Einstellungen, falls das Skript beendet wird, während Verknüpfungen deaktiviert sind.
  4. Behandelt die Verknüpfungen gsettings und dconf. (Dies war möglicherweise kein Problem.)

Offene Probleme:


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

Anmerkungen:

  • Beachten Sie die verschiedenen Schlüsselformate für gsettings resp. dconf.
  • gsettings Tasten erscheinen in dconf, aber dort vorgenommene Änderungen haben keine Wirkung. Als allgemeine Regel fügen Sie Schlüssel hinzu, die mit Jakobs Methode als gsettings gefunden wurden und die Sie manuell in dconf als solche aufspüren mussten.
  • Führen Sie die Sicherungsdatei als Skript aus, falls die Verknüpfungen durcheinander geraten, z. indem das Skript beendet wird, während Verknüpfungen deaktiviert sind.
7
Raphael