diff --git a/qwerty.py b/qwerty.py
index 5590e8a..c4110cd 100755
--- a/qwerty.py
+++ b/qwerty.py
@@ -17,6 +17,10 @@ GLOBAL = 0
SECTION = 1
KEY = 2
+SHIFT = 1
+CONTROL = 2
+ALT = 4
+
PADDING = 4
ICON_TOP_MARGIN = 35
LABEL_LEFT, LABEL_TOP = 15,25
@@ -222,11 +226,12 @@ class SectionButton(SuperButton):
class Section(object):
def __init__(self,title):
self.title = title
- self.keys = {}
+ self.keys = []
class Key(object):
def __init__(self,key):
self.key = key
+ self.mods = []
def parse_config():
global sections
@@ -242,6 +247,17 @@ def parse_config():
if line.startswith(key):
return line[len(key):].strip()
+ def parse_mods(s):
+ r = []
+ ms = s.upper().split()
+ if 'SHIFT' in ms:
+ r.append(SHIFT)
+ if ('CONTROL' in ms) or ('CTRL' in ms):
+ r.append(CONTROL)
+ if 'ALT' in ms:
+ r.append(ALT)
+ return r
+
context = GLOBAL
for line in open(config_file):
line = line.strip()
@@ -269,7 +285,7 @@ def parse_config():
if v:
v = v.upper()
K = Key(v)
- S.keys[v] = K
+ S.keys.append(K)
context = KEY
continue
@@ -280,6 +296,13 @@ def parse_config():
context = KEY
continue
+ v = parse_line('Mods', line)
+ if v:
+ if context == KEY:
+ K.mods = parse_mods(v)
+ else:
+ raise SyntaxError, "Unexpected 'Mods' key in config"
+
v = parse_line('Description',line)
if v:
if context == KEY:
@@ -330,6 +353,16 @@ def save_config():
def writeln():
cf.write('\n')
+ def mods_str(ms):
+ r = ''
+ if SHIFT in ms:
+ r += 'Shift '
+ if CONTROL in ms:
+ r += 'Control '
+ if ALT in ms:
+ r += 'Alt'
+ return r
+
global sections
global defsection
global speckeys
@@ -342,8 +375,11 @@ def save_config():
write('Icon', S.icon)
write('Order', S.order)
writeln()
- for K in S.keys.values():
+
+ for K in S.keys:
write('Key', K.key)
+ if K.mods:
+ write('Mods', mods_str(K.mods))
write('Icon', K.icon)
write('Title', K.title)
if hasattr(K, 'desc'):
@@ -415,7 +451,7 @@ class GUI(object):
btn.connect("button-press-event",self.on_section)
for i,S in sections.iteritems():
- btn = self.sbuttons[(i-1)%10]
+ btn = self.sbuttons[i]
btn.set_label(S.title)
btn.set_icon(S.icon)
@@ -428,7 +464,8 @@ class GUI(object):
self.window.set_title('Qwerty-Launcher')
self.window.add(self.main)
self.window.connect('destroy', self.exit)
- self.window.connect('key-release-event', self.on_key)
+ self.window.connect('key-press-event', self.on_key)
+ self.window.connect('key-release-event', self.key_released)
self.window.fullscreen()
self.window.show()
@@ -518,7 +555,41 @@ class GUI(object):
km = gtk.gdk.keymap_get_default()
kv = km.lookup_key(hw_code,0,0)
return gtk.gdk.keyval_name(kv)
+
+ def translate_mods(self,event):
+ mods = []
+ shift = event.state & gtk.gdk.SHIFT_MASK
+ ctrl = event.state & gtk.gdk.CONTROL_MASK
+ alt = event.state & gtk.gdk.MOD1_MASK
+ if shift:
+ mods.append(SHIFT)
+ if ctrl:
+ mods.append(CONTROL)
+ if alt:
+ mods.append(ALT)
+ return mods
+
+ def key_in(self,kv,names):
+ return kv in map(gtk.gdk.keyval_from_name, names)
+
+ def key_in_mods(self,kv):
+ names = ['Shift_L', 'Shift_R','Control_L', 'Control_R', 'Mod1']
+ return self.key_in(kv,names)
+ def key_released(self,widget,event):
+
+ if self.key_in_mods(event.keyval):
+ mods = self.translate_mods(event)
+
+ if self.key_in(event.keyval,['Shift_L','Shift_R']):
+ mods.remove(SHIFT)
+ if self.key_in(event.keyval, ['Control_L', 'Control_R']):
+ mods.remove(CONTROL)
+ if self.key_in(event.keyval, ['Mod1']):
+ mods.remove(ALT)
+
+ self.show_section((self.S.order+1)%10, mods)
+
def on_key(self,widget,event):
global speckeys
@@ -526,6 +597,19 @@ class GUI(object):
self.exit()
return
+ mods = self.translate_mods(event)
+
+ if self.key_in(event.keyval,['Shift_L','Shift_R']):
+ mods.append(SHIFT)
+ if self.key_in(event.keyval, ['Control_L', 'Control_R']):
+ mods.append(CONTROL)
+ if self.key_in(event.keyval, ['Mod1']):
+ mods.append(ALT)
+
+ if self.key_in_mods(event.keyval):
+ self.show_section((self.S.order+1)%10, mods)
+ return
+
for k in speckeys:
if event.keyval == gtk.gdk.keyval_from_name(k):
self.do_special_button(speckeys[k])
@@ -534,19 +618,20 @@ class GUI(object):
k = self.get_key(event.hardware_keycode)
if k in DIGITS:
- self.show_section(k)
+ self.show_section(k, mods)
elif k == ' ':
self.switch_taskbar()
elif k in ALPHABET.lower():
- self.do_button(k)
+ self.do_button(k, mods)
- def key_exec(self,key):
- cmd = self.S.keys[key].command
+ def key_exec(self,key,mods):
+ ks = dict([((k.key,tuple(k.mods)), k) for k in self.S.keys])
+ cmd = ks[key,tuple(mods)].command
os.system(cmd + " &")
- def do_button(self,key):
+ def do_button(self,key, mods):
try:
- self.on_button(self.buttons[key.upper()])
+ self.on_button(self.buttons[key.upper()],mods=mods)
except KeyError:
return
@@ -575,18 +660,18 @@ class GUI(object):
else:
os.system(key.command + ' &')
- def on_button(self,widget,event=None):
+ def on_button(self,widget,event=None,mods=[]):
if widget.running:
# print "Activating", widget.label
self.activate_window(widget.cls)
else:
- self.key_exec(widget.key)
+ self.key_exec(widget.key,mods)
self.exit()
def on_section(self,widget,event=None):
- self.show_section(widget.key)
+ self.show_section(widget.key, self.translate_mods(event))
- def show_section(self,k):
+ def show_section(self,k,mods):
global sections
global defsection
@@ -595,7 +680,7 @@ class GUI(object):
id = (int(k)-1)%10
# id = int(k)
try:
- self.S = sections[int(k)]
+ self.S = sections[id]
except KeyError:
return
defsection = id
@@ -612,8 +697,11 @@ class GUI(object):
btn = self.buttons[b]
btn.clear()
- for k in self.S.keys:
- K = self.S.keys[k]
+ for K in self.S.keys:
+# K = self.S.keys[k]
+ if K.mods != mods:
+ continue
+ k = K.key
btn = self.buttons[k]
btn.set_label(K.title)
if hasattr(K, 'desc'):
@@ -627,5 +715,5 @@ class GUI(object):
parse_config()
g = GUI()
-g.show_section(defsection+1)
+g.show_section(defsection+1,[])
gtk.main()