View difference between Paste ID: RKwrtE8Y and QkbE3eJF
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/python2
2
# -*- coding: utf-8 -*-
3
4
import gtk
5
import glib
6
import os
7
import sys
8
import ConfigParser
9
import ctypes
10
try:
11
    import pynotify
12
    if not pynotify.init("LockKeys"):
13
        print("Il y a eu une erreur pendant l'initialisation du système de notification. Les notifications ne fonctionnerons pas.")
14
        pynotify = None
15
except:
16
    print("Il semble que python-notify ne soit pas installé. Les notifications ne fonctionnerons pas.")
17
    pynotify = None
18
NotifyAvailable = pynotify
19
20
class XKeyboardState(ctypes.Structure):
21
    _fields_ = [("key_click_percent", ctypes.c_int),
22
                ("bell_percent", ctypes.c_int),
23
                ("bell_pitch", ctypes.c_uint),
24
                ("bell_duration", ctypes.c_uint),
25
                ("led_mask", ctypes.c_ulong),
26
                ("global_auto_repeat", ctypes.c_int),
27
                ("auto_repeats", ctypes.c_char * 32)]
28
29
def initXGetKeyboardControl():
30
    global dpy, keyboardState, XGetKeyboardControl
31
    
32
    libX11 = ctypes.CDLL("libX11.so.6")
33
    XOpenDisplay = libX11.XOpenDisplay
34
    XOpenDisplay.restype = ctypes.c_void_p
35
    XOpenDisplay.argtypes = [ctypes.c_char_p]
36
    XGetKeyboardControl = libX11.XGetKeyboardControl
37
    XGetKeyboardControl.restype = ctypes.c_int
38
    XGetKeyboardControl.argtypes = [ctypes.c_void_p, ctypes.POINTER(XKeyboardState)]
39
    
40
    dpy = XOpenDisplay(None)
41
    keyboardState = XKeyboardState()
42
43
def runXGetKeyboardControl():
44
    global dpy, keyboardState, XGetKeyboardControl
45
    XGetKeyboardControl(dpy, ctypes.byref(keyboardState))
46
    return keyboardState.led_mask
47
48
#écrit dans le fichier de config    
49
def WriteConfig (Section, Key, Value):
50
    Config.set(Section,Key,Value)
51
    with open(ConfigFile, 'w') as myfile:
52
        Config.write(myfile)
53
54
#Notification (état du clavier) si pynotify != None
55
def notify(message,duration):
56
    if pynotify:
57
        n = pynotify.Notification('LockKeys', message)
58
        n.set_timeout(duration)
59
        n.set_icon_from_pixbuf(gtk.Label().render_icon(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_LARGE_TOOLBAR))
60
        n.show()
61
62
63
class Systray():
64
    def __init__(self):
65
        self.tray_object= gtk.StatusIcon()
66
        self.tray_object.connect("popup_menu", self.rightclick_menu)
67
        self.show_trayicon(1) ## fixed to one for now
68
        self._oldMask = -1
69
70
    def show_trayicon(self,value):
71
       self.tray_object.set_visible(True)
72
       return
73
74
    def property_modified(self):
75
        # utilse xset pour connaître l'état des touches capslock et numlock
76
        # 0 -> aucun, 1 -> capslock, 2-> numlock, 3 -> les 2
77
        mask=int(runXGetKeyboardControl()) & 3
78
        if mask != self._oldMask:
79
            self._oldMask = mask
80
            if sound_status == True:
81
                os.system(Sound)
82
            notify(msg[mask],2000)
83
            
84-
        # Todo : essayer d'abord usr/share/lockkeys/ voire ~/.local/lockkeys
84+
            # Todo : essayer d'abord usr/share/lockkeys/ voire ~/.local/lockkeys
85-
        icon_path = './' + str(mask) + '.png'
85+
            icon_path = './' + str(mask) + '.png'
86-
        self.tray_object.set_from_file(icon_path)
86+
            self.tray_object.set_from_file(icon_path)
87
88
    # défini le menu clic droit sur l'icône
89
    def rightclick_menu(self, button, widget, event):
90
        menu = gtk.Menu()
91
        about_menu = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
92
        about_menu.connect('activate', self.about)
93
        exit_menu = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
94
        exit_menu.connect('activate', self.close)
95
        menu.append(about_menu)
96
        menu.append(exit_menu)
97
        sep = gtk.SeparatorMenuItem()
98
        menu.append(sep)
99
        sound_menu = gtk.CheckMenuItem("Activer le son")
100
        sound_menu.set_active(sound_status)
101
        sound_menu.connect("activate", self.sound_toggle)
102
        menu.append(sound_menu)
103
        notify_menu = gtk.CheckMenuItem("Activer les notifications")
104
        notify_menu.set_active(notify_status)
105
        notify_menu.connect("activate", self.notify_toggle)
106
        menu.append(notify_menu)
107
        menu.show_all()
108
        menu.popup(None, None, None, 2, event)
109
        
110
    # activation / désactivation du son et enregistrement dans le fichier config
111
    def sound_toggle(self, widget):
112
        global sound_status
113
        if widget.active: 
114
            sound_status=True
115
        else:
116
            sound_status=False
117
        WriteConfig ('helpers','sound',sound_status) 
118
119
    # activation / désactivation des notifications et enregistrement dans le fichier config
120
    def notify_toggle(self, widget):
121
        global notify_status
122
        global pynotify
123
        if widget.active: 
124
            notify_status=True
125
            pynotify=NotifyAvailable
126
        else:
127
            notify_status=False
128
            pynotify=None
129
        WriteConfig ('helpers','notification',notify_status) 
130
131
    def close(self,button):
132
        sys.exit(0)
133
134
    def about(self, button):
135
        about_dg = gtk.AboutDialog()
136
        about_dg.set_name('Lockkeys')
137
        about_dg.set_version('0.2')
138
        about_dg.set_copyright('(C) 2014 Vincent Gay <vgay@vintherine.org>')
139
        about_dg.set_comments(("Simple icône dans la zone de notification pour indiquer l'état de CapsLock et NumLock"))
140
        about_dg.set_license('Ce script est distribuable sous licence gpl version 3 ou supérieure\nhttp://www.gnu.org/licenses/gpl-3.0.fr.html')
141
        about_dg.set_website('http://blog.vintherine.org')
142
        about_dg.run()
143
        about_dg.destroy()
144
145
class Manager:
146
    def __init__(self):
147
        self.listener = Systray()
148
        
149
    def __property_modified_handler(self):
150
        self.listener.property_modified()
151
 
152
    def update(self):
153
        self.__property_modified_handler()
154
        return True
155
156
def main():
157
    initXGetKeyboardControl()
158
    m = Manager()
159
    glib.timeout_add(300, m.update)
160
    gtk.main()
161
162
ConfigFile=os.path.expanduser('~/.config/lockkeys.cfg')
163
# aplay appartient au paquet alsa, est-ce la peine de vérifier ? 
164
Sound = 'aplay ./ding.wav > /dev/null 2>1&'
165
sound_status=True
166
pynotify = None
167
Config = ConfigParser.ConfigParser()
168
msg=[]
169
msg.append('Capslock = off, Numlock = off')
170
msg.append('Capslock = on, Numlock = off')
171
msg.append('Capslock = off, Numlock = on')
172
msg.append('Capslock = on, Numlock = on')
173
174
#créer le fichier de config s'il n'existe pas
175
if os.path.isfile(ConfigFile) == False:
176
    ini = open(ConfigFile,'w')
177
    Config.add_section('helpers')
178
    Config.set('helpers','sound',True)
179
    Config.set('helpers','notification',False)
180
    Config.write(ini)
181
    ini.close()
182
183
# lire le fichier de configuration    
184
Config.read(ConfigFile)
185
try:
186
    sound_status = Config.getboolean("helpers", "sound")
187
except:
188
    WriteConfig ('helpers','sound',True)
189
try:
190
    notify_status = Config.getboolean("helpers", "notification")
191
except:
192
    WriteConfig ('helpers','notification',False)
193
    notify_status=False
194
if notify_status:
195
    pynotify=NotifyAvailable
196
    
197
main()