Created
October 11, 2015 20:50
-
-
Save somian/f85bb1af2420627db848 to your computer and use it in GitHub Desktop.
xkb configuration is too complicated - xmodmap script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment