Ярлык для переключения сочетаний клавиш [dубликат]

Великие среды IDE JetBrains (IDEA и др.) назначают практически любую возможную комбинацию клавиш для некоторых функций.

Моя проблема в том, что Unity также назначает некоторые из этих ярлыков, и они имеют приоритет. Одним из особенно неприятных примеров является CTRL + ALT + L. Проблема была изучена до этого.

Однако ни один из подходов не является удовлетворительным.

Отключение горячих клавиш системы глобально препятствует моей общей производительность с системой. Переход на другую раскладку в IDEA смутит меня, когда я буду развиваться на разных платформах (и должен выбирать разные сопоставления).

Есть ли способ отключить ярлыки системы только тогда, когда какое-то приложение активно, то есть работает и в фокусе?

Я бы хотел запускать скрипт каждый раз, когда я запускаю приложение.

5
задан 13 April 2017 в 15:25

10 ответов

На основании (более старой версии) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

Честные изменения, которые пользователь делает во время работы скрипта. Не сбрасывает значения, установленные пользователем по умолчанию. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:

Я не могу найти, где установлены некоторые ярлыки, такие как Alt + `и Alt + F1. Они исходят от Unity, соответственно. Compiz; как мы можем программным образом изменить ярлыки, показанные при удержании Super? xprop не показывает PID для всех окон. Неудачный пример: stopwatch. (Jaco Vlijm имеет некоторые идеи.) #!/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

Открытые проблемы:

Я не могу найти, где установлены некоторые ярлыки, такие как Alt + `и Alt + F1. Они исходят от Unity, соответственно. Compiz; как мы можем программным образом изменить ярлыки, показанные, когда вы держите клавиши Super? gsettings, появляются в dconf, но внесенные изменения не влияют. Как правило, добавьте ключи, найденные с использованием метода Джейкоба, как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые. xprop не показывает PID для всех окон. Неудачный пример: stopwatch. (У Жако Влайма есть некоторые идеи.)
7
ответ дан 18 July 2018 в 11:48

На основании (более старой версии) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

Честные изменения, которые пользователь делает во время работы скрипта. Не сбрасывает значения, установленные пользователем по умолчанию. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:

Я не могу найти, где установлены некоторые ярлыки, такие как Alt + `и Alt + F1. Они исходят от Unity, соответственно. Compiz; как мы можем программным образом изменить ярлыки, показанные при удержании Super? xprop не показывает PID для всех окон. Неудачный пример: stopwatch. (Jaco Vlijm имеет некоторые идеи.) #!/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

Открытые проблемы:

Я не могу найти, где установлены некоторые ярлыки, такие как Alt + `и Alt + F1. Они исходят от Unity, соответственно. Compiz; как мы можем программным образом изменить ярлыки, показанные, когда вы держите клавиши Super? gsettings, появляются в dconf, но внесенные изменения не влияют. Как правило, добавьте ключи, найденные с использованием метода Джейкоба, как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые. xprop не показывает PID для всех окон. Неудачный пример: stopwatch. (У Жако Влайма есть некоторые идеи.)
7
ответ дан 24 July 2018 в 19:51
  • 1
    Я собрал несколько ярлыков, полезных для использования IDE JetBrains здесь . – Raphael 22 December 2016 в 17:25
  • 2
    @ Raphael нет, это неверно. Второй и первый разные, поскольку первый из них сделан для того, как вы сначала задали свой вопрос, а второй - для дополнительных требований в комментариях. Ты пробовал? – Jacob Vlijm 22 December 2016 в 17:50
  • 3
    @Raphael также, некоторые из ваших исправлений включают в себя нежелательное использование прямого редактирования dconf. Кроме того, это «исправления» вопросы, которые вы не упомянули в своем вопросе. Прокомментирует позже. Без обид, но imo будет достойным действием, чтобы принять (этот) ответ, если он является основой вашего решения. – Jacob Vlijm 22 December 2016 в 17:54
  • 4
    @Raphael, меняющий вопрос после того, как ответы были опубликованы, на основе исходного вопроса вполне, ну, не сделано. В комментарии я уже упоминал, почему редактирование dconf напрямую не является желаемым. / org / gnome / desktop / wm / keybindings / begin-move находится в gsettings (16.04) – Jacob Vlijm 22 December 2016 в 18:42
  • 5
    Как упоминалось ранее, dconf не следует использовать, если gsettings доступен, что имеет место во всех ярлыках, которые вы упомянули. gsettings защищает согласованность базы данных dconf. Проблема заключалась в использовании & quot; '' & quot; для перечислены значения . исправлено в ответе. – Jacob Vlijm 23 December 2016 в 12:00
  • 6
    Привет @Raphael, проблема с указанными значениями (как указано в 1-м комментарии) исправлена. Кроме того, скрипты теперь также адаптируют ярлыки пользовательских наборов и сбрасываются на них. Резервная копия кажется немного избыточной для меня, так как просто (se) запуск скрипта будет устанавливать все сочетания клавиш для ранее заданных ярлыков. как объяснено, использование dconf нежелательно, а также ненужное с момента исправления. – Jacob Vlijm 23 December 2016 в 23:10
  • 7
    Что касается комментария Джейкоба, да: все ярлыки, которые я пробовал (с моей версией скрипта), работают с gsettings. Я оставляю код так, как сейчас, но пользователи могут предпочесть формат gsettings. – Raphael 2 January 2017 в 12:42

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
10
ответ дан 31 July 2018 в 22:54

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
10
ответ дан 2 August 2018 в 17:45

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
10
ответ дан 3 August 2018 в 20:09

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
10
ответ дан 5 August 2018 в 04:53

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
10
ответ дан 6 August 2018 в 22:01

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
10
ответ дан 9 August 2018 в 02:24

Как автоматически отключить несколько (конкретных) ярлыков, если (и пока) окно конкретного приложения активно

В приведенном ниже сценарии будут отключены определенные ключевые ярлыки при активном окне произвольного приложения.

Хотя вы упоминали «« Я бы хотел запускать скрипт каждый раз, когда я запускаю приложение ». . Позже нет причин убивать скрипт, он крайне низок сок

Сценарий

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

Как использовать

  1. Для сценария необходимо xdotool:
    sudo apt-get install xdotool
    
  2. Скопируйте сценарий в пустой файл, сохраните его как disable_shortcuts.py
  3. В начале скрипта замените в строке:
    app = "gedit"
    
    «gedit» вашим приложением, что означает: имя процесса, которое .
  4. Протестируйте скрипт командой:
    python3 /path/to/disable_shortcuts.py
    
  5. Если все работает нормально, добавьте его в приложения для запуска: Dash> Startup Applications> Add. команда:
    /bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
    

Добавление дополнительных ярлыков для отключения

В качестве примера я добавил sh ortcut вы упомянули: CTRL + ALT + L. Ярлыки установлены в базе данных dconf и могут быть установлены или отключены с помощью gsettings.

В скрипте эти записи gsettings установлены в функция: setkeys()

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

Пример добавления (отключения) ярлыка выхода из системы:

  1. Откройте окно терминала, запустите команду dconf watch /
  2. Открыть системные настройки> «Клавиатура»> «Ярлыки»> «Система»
  3. Повторно установите ярлык для себя. В терминале вы можете увидеть клавишу gsettings, которая принадлежит ярлыку:
  4. Теперь нам нужно добавить найденный ключ (несколько иначе):
    ["org.gnome.settings-daemon.plugins.media-keys", "logout"]
    
    ... в список «keys» в нашей функции:
    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"],
            ]
    

Теперь оба CTRL + ALT + L и CTRL + ALT + Delete отключены, если ваше приложение находится впереди.

Объяснение

Как уже упоминалось, ярлыки, подобные тем, которые вы упоминаете, устанавливаются в базе данных dconf. В примере CTRL + ALT + L ключ для установки или редактирования schortcut:

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

Чтобы отключить , команда:

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

Чтобы сбросить ключ до значения по умолчанию:

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

Сценарий выглядит один раз в секунду, если:

  • ваше приложение запускается на всех
  • , если это так, он выглядит, если какое-либо из его окон активно
  • снова (только), если это так, оно отключает ярлыки, перечисленные в
    # --- add the keys to be disabled below
    keys = [
        ["org.gnome.settings-daemon.plugins.media-keys", "screensaver"],
         ["org.gnome.settings-daemon.plugins.media-keys", "logout"],
       ]
    
    ... ожидании следующего изменения состояния ,

Если активное окно больше не является вашим приложением, ключи, упомянутые в списке, сбрасываются по умолчанию.

Примечание

Как упоминалось ранее, дополнительная нагрузка на процессор скрипта - нигил. Вы можете очень хорошо запустить его при запуске, как описано в «Как использовать».


Влияние на несколько приложений

Как обсуждалось в комментариях, в конкретном случае OP это полезно применять ярлыки отключения в группе приложений, все из которых находятся в одном каталоге.

Ниже приведена версия для применения ко всем приложениям, выход которых из

pgrep -f 

будет содержать конкретный каталог. В моем примере я установил каталог /opt, поэтому, если активное окно является одним из любых приложений в /opt, ярлыки набора будут отключены.

, приведя окно одного из приложений в / opt к фронту, отключит ярлык выхода

re - включение ярлыка, если другое окно получает фокус

Сценарий

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

Как использовать

  1. Как и первый скрипт, необходимо установить xdotool:
    sudo apt-get install xdotool
    
  2. Скопировать сценарий в пустой файл, сохранить его как disable_shortcuts.py
  3. В начале скрипта замените в строке:
    appdir = "/opt"
    
    "/ opt" в каталоге, в котором находятся ваши приложения.
  4. Протестируйте скрипт с помощью command:
    python3 /path/to/disable_shortcuts.py
    
  5. Если все работает нормально, добавьте его в приложения для запуска: Dash> Startup Applications> Add. Добавьте команду:
    /bin/bash -c "sleep 15 && python3 /path/to/disable_shortcuts.py"
    

Добавление других ярлыков в список работает точно так же, как и версия 1 скрипта.

Работает ли он во всех приложениях?

В вашем ответе вы отметите:

xprop не показывает PID для всех окон. Неудачный пример: секундомер.

Windows с pid 0 (например, окна tkinter, включая Idle), не имеют идентификатора окна на выходе xprop -id. Idle не имеет каких-либо сочетаний ярлыков, хотя в моем опыте. Если вы столкнулись с любым приложением с pid 0, для которого требуется отключить определенные ярлыки, пожалуйста, укажите.

В этом случае возможным выходом будет преобразование вывода

xdotool getactivewindow

в формате wmctrl используется формат, а затем поиск соответствующего pid на выходе

wmctrl -lp

. Хотя это казалось наиболее очевидным для начала, я не сделал используйте его в скрипте, чтобы сценарий был как можно более легким.

10
ответ дан 12 August 2018 в 14:06
  • 1
    @ Raphael нет, это неверно. Второй и первый разные, поскольку первый из них сделан для того, как вы сначала задали свой вопрос, а второй - для дополнительных требований в комментариях. Ты пробовал? – Jacob Vlijm 22 December 2016 в 17:50
  • 2
    @Raphael также, некоторые из ваших исправлений включают в себя нежелательное использование прямого редактирования dconf. Кроме того, это «исправления» вопросы, которые вы не упомянули в своем вопросе. Прокомментирует позже. Без обид, но imo будет достойным действием, чтобы принять (этот) ответ, если он является основой вашего решения. – Jacob Vlijm 22 December 2016 в 17:54
  • 3
    @Raphael, меняющий вопрос после того, как ответы были опубликованы, на основе исходного вопроса вполне, ну, не сделано. В комментарии я уже упоминал, почему редактирование dconf напрямую не является желаемым. / org / gnome / desktop / wm / keybindings / begin-move находится в gsettings (16.04) – Jacob Vlijm 22 December 2016 в 18:42
  • 4
    Привет @Raphael, проблема с указанными значениями (как указано в 1-м комментарии) исправлена. Кроме того, скрипты теперь также адаптируют ярлыки пользовательских наборов и сбрасываются на них. Резервная копия кажется немного избыточной для меня, так как просто (se) запуск скрипта будет устанавливать все сочетания клавиш для ранее заданных ярлыков. как объяснено, использование dconf нежелательно, а также ненужное с момента исправления. – Jacob Vlijm 23 December 2016 в 23:10
  • 5
    Я, наконец, добрался до новой версии (версии для нескольких приложений). К сожалению, я получаю ошибки . – Raphael 2 January 2017 в 12:29

На основе (более старая версия) ответа Якоба Влайма я написал эту версию, которая решает эти дополнительные проблемы:

  1. Честности, которые пользователь делает, пока скрипт
  2. Не сбрасывает значения, установленные пользователем по умолчанию.
  3. Сохраняет резервную копию настроек в случае, если скрипт завершает работу, пока ярлыки отключены.
  4. Ручки gsettings и dconf ярлыки. (Это может быть не проблема.)

Открытые проблемы:


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

Примечания:

  • Обратите внимание на различные форматы клавиш для gsettings соотв. dconf.
  • gsettings клавиши do отображаются в dconf, но внесенные изменения не действуют. Как правило, добавьте ключи, найденные с помощью метода Jacob's , как gsettings, и те, которые вам пришлось вручную отслеживать в dconf как таковые.
  • Запустить файл резервной копии как скрипт в случае перебора ярлыков, например по завершению сценария, когда ярлыки отключены.
7
ответ дан 14 August 2018 в 20:38
  • 1
    Я собрал несколько ярлыков, полезных для использования IDE JetBrains здесь . – Raphael 22 December 2016 в 17:25
  • 2
    Как упоминалось ранее, dconf не следует использовать, если gsettings доступен, что имеет место во всех ярлыках, которые вы упомянули. gsettings защищает согласованность базы данных dconf. Проблема заключалась в использовании & quot; '' & quot; для перечисленных значений. исправлено в ответе. – Jacob Vlijm 23 December 2016 в 12:00
  • 3
    Что касается комментария Джейкоба, да: все ярлыки, которые я пробовал (с моей версией скрипта), работают с gsettings. Я оставляю код так, как сейчас, но пользователи могут предпочесть формат gsettings. – Raphael 2 January 2017 в 12:42

Другие вопросы по тегам:

Похожие вопросы: