CapsLock auf der Linux Konsole und der grafischen Oberfläche deaktivieren

Geschrieben von Eric Scheibler am 24.04.2015

Dieser Artikel erläutert das Vorgehen beim Deaktivieren der CapsLock Taste unter Linux. Es werden Lösungen für die virtuelle Konsole (tty1-6) sowie für den grafischen Desktop vorgestellt. Getestet unter Debian Jessie und Mate-Desktop.

Konsole (tty1-6)

Zunächst muss eine Keymap Datei mit folgendem Inhalt erstellt werden:

sudo /etc/disable_capslock.keymap

Inhalt:

keymaps 0-127
# kill capslock
keycode 58 = nul

Anschließend wird die Keymap geladen:

sudo /usr/bin/loadkeys /etc/disable_capslock.keymap

Nach dem Laden der Keytable ist die CapsLock Taste ohne Funktion. Sie wird aber trotzdem von Brltty erkannt und kann daher problemlos als Modustaste weiterverwendet werden.

Damit die Keymap auch beim Systemstart geladen wird, fügt man den Loadkey Befehl an die /etc/rc.local Datei an.

Anmerkung: mit sudo dumpkeys kann man sich die aktuell geladene Keymap ausgeben lassen und sudo showkey hilft beim ermitteln des Key Codes für eine bestimmte Taste.

Grafische Oberfläche

Wer nicht auf den Screen Reader Orca angewiesen ist, kann die CapsLock Taste sehr einfach deaktivieren: Auf dem Mate-Desktop im System-Menü unter Einstellungen -> Tastatur den Tab "Belegungen" auswählen und dort die Optionen der Tastatur öffnen. In dem sich öffnenden Fenster sucht man den Eintrag für die CapsLock Taste und wählt "Feststelltaste ist deaktiviert".

Wer hingegen Orca mit dem Laptop-Tastaturschema und CapsLock als Modustaste verwendet, muss ein paar Dinge beachten. Wenn man die CapsLock Taste wie gerade beschrieben deaktiviert, kann man zwar nicht mehr versehentlich Großbuchstaben schreiben aber auch Orca nicht mehr bedienen. Denn der Screen Reader bekommt nun ebenfalls nicht mehr mit, wenn CapsLock gedrückt wurde. Lässt man die Einstellungen für CapsLock jedoch unverändert, so wird zumindest bei mir bei jeder Orca Tastenkombination auch der Status der CapsLock Taste geändert. Das bedeutet, dass ich nach jeder Orca Tastenkombination noch einmal CapsLock drücken muss, da ich sonst versehentlich Großbuchstaben tippe und das ist auf Dauer extrem nervig.

Um das Problem zu beheben, weist man Orca zunächst die Einfügen Taste (insert) als Modustaste zu. Dazu öffnet man die Orca Einstellungen mit CapsLock+Leertaste und wechselt zum Tab Tastenkombinationen. Anschließend Insert als Modustaste festlegen und Fenster mit OK schließen.

Im zweiten Schritt deaktiviert man CapsLock, wie im ersten Absatz beschrieben (System-Tab -> Einstellungen -> Tastatur ...).

Im letzten Schritt erstellt man sich eine eigene Keytable und weist der CapsLock Taste die Insert Taste zu:

xmodmap -pke > ~/.xmodmap
vim ~/.xmodmap

Inhalt:

[...]
keycode  66 = Insert NoSymbol Insert
[...]

Off Topic: Bei den neuen Thinkpad Modellen befindet sich an der Stelle der Kontextmenütaste jetzt die PrintScreen Taste. Wer mit dieser Taste weiterhin gern das Kontextmenü öffnen möchte, der ändert noch die folgende Zeile der Keytable:

[...]
keycode 107 = Menu NoSymbol Menu
[...]

Anschließend wird die Keytable geladen:

xmodmap ~/.xmodmap

Nun kann man die CapsLock Taste wieder als Orca Modustaste verwenden, weil sie sich wie die Einfügen Taste verhält. Allerdings wird die geänderte Keytable bei jedem Ausloggen, Standby und Herunterfahren überschrieben. Mit dem folgenden Python Skript erspart man sich das manuelle nachladen:

Download: reload-xmodmap

#!/usr/bin/env python
# Adapted from Andrey Tataranovich script www.tataranovich.com/public/scripts/xkbmapd.py
# to load the user .Xmodmap file on 1) start, 2) resume and 3) layout switch
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import sys
import fcntl
import dbus
import gobject
import time
from dbus.mainloop.glib import DBusGMainLoop

# Fork to background
if os.fork():
    sys.exit(0)

xmodmap = os.path.expanduser('~/.xmodmap')
if not os.path.isfile(xmodmap):
    print('File not found: ' + xmodmap)
    sys.exit(1)

# Try to detect if another instance already running
lock = open(os.path.realpath(xmodmap), 'r')
try:
    fcntl.flock(lock, fcntl.LOCK_EX|fcntl.LOCK_NB)
except:
    print('Unable to lock file: ' + xmodmap + '. Maybe another instance already running')
    sys.exit(1)

# DBus init
dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)
system_bus = dbus.SystemBus()
session_bus = dbus.SessionBus()

# The command xmodmap ~/xmodmap
def do():
    command = 'xmodmap ' + xmodmap
    if os.path.isfile(xmodmap):
        time.sleep(5)
        os.system(command)

# Get the object path for the current active session
def get_current_session_path():
    seat = system_bus.get_object('org.freedesktop.login1', '/org/freedesktop/login1/seat/' + os.environ['XDG_SEAT'])
    active_session = seat.Get('org.freedesktop.login1.Seat', 'ActiveSession', dbus_interface='org.freedesktop.DBus.Properties')
    session_obj_path = active_session[1]
    return session_obj_path

# Store my session path so we can compare later
my_session = get_current_session_path()

# The event handlers
def handle_resume(arg):
    if arg == False: # PrepareForSleep returns false if resuming
        do()

def handle_session(*args):
    if my_session == get_current_session_path():
        do()

# Debugme: if you have the applet active, when you resume or change sessions, 
# this layout switch handle is called too... so we are loading the xmodmap 2 times!
# But we need the other handles because the applet can be disabled...
def handle_layout_switch(arg):
    if arg == "com.canonical.indicator.keyboard":
        do()

# Why not do at the start?
do()

# The signals
system_bus.add_signal_receiver(handle_resume, signal_name='PrepareForSleep',
        dbus_interface='org.freedesktop.login1.Manager')
system_bus.add_signal_receiver(handle_session, signal_name='PropertiesChanged',
        dbus_interface='org.freedesktop.DBus.Properties', bus_name='org.freedesktop.login1',
        path='/org/freedesktop/login1/seat/' + os.environ['XDG_SEAT'])
session_bus.add_signal_receiver(handle_layout_switch, signal_name='ReSync',
        dbus_interface='com.canonical.Unity.Panel.Service')

# Loop baby
loop = gobject.MainLoop()
loop.run()

Schließlich muss das Skript noch zu den Autostartprogrammen hinzugefügt werden. Mate-Desktop: System Tab -> Einstellungen -> Startprogramme. Dort einen neuen Eintrag anlegen und den kompletten Pfad zum reload-xmodmap Skript angeben (relative Pfade funktionieren nicht).

Noch eine Anmerkung: Die Keytable wird auch neu geladen, wenn die Orca Einstellungen verändert wurden. Diesen Fall deckt das reload-xmodmap Skript nicht ab. Nach der Änderung der Orca Einstellungen muss man daher daran denken, die Keytable mittels xmodmap manuell neu zu laden.