]> git.neil.brown.name Git - freerunner.git/commitdiff
tapinput - various updates
authorNeilBrown <neilb@suse.de>
Sun, 6 Feb 2011 09:16:49 +0000 (20:16 +1100)
committerNeilBrown <neilb@suse.de>
Sun, 6 Feb 2011 09:16:49 +0000 (20:16 +1100)
Signed-off-by: NeilBrown <neilb@suse.de>
input/tapinput.py

index 2e5f39fb21a0277ba32d933d285c941ced616d59..7c8e9cbb2275368e504c40ca8f9d3fff3d33d9ef 100644 (file)
 # The window can be dragged  by touch-and-drag anywhere.
 # If the window is dragged more than 1/2 off the screen, it disappears.
 
-import gtk, pango, gobject
+import gtk, pango, gobject, os, struct, time
 from fakeinput import fakeinput
 
 keymap = {}
 
 keymap['lower'] = [
-    ['0','1','Tab','2','3',' ','?','@','#'],
+    ['0','1','Tab','2','3','Delete','?','@','#'],
     ['b','c','d','f','g','h',' ','Down',' '],
     ['<','4','5','>','6','7','Return','{','}'],
     ['j','k','~','l','m','Right','n','p','`'],
     ['a','e','i','o',' ','u','r','s','t'],
     ['\\',';',':','Left','\'','"','|','(',')'],
-    ['[',']',' ','8','9','=','+','-','_'],
+    ['[',']','Escape','8','9','=','+','-','_'],
     [' ','Up',' ','q','v','w','x','y','z'],
     ['!','$','%','^','*','/','&',',','.'],
     None,
@@ -45,7 +45,7 @@ keymap['UPPER'] = [
     ['J','K','~','L','M','Right','N','P','`'],
     ['A','E','I','O',' ','U','R','S','T'],
     ['\\',';',':','Left','\'','"','|','(',')'],
-    ['[',']',' ','8','9','=','+','-','_'],
+    ['[',']','Escape','8','9','=','+','-','_'],
     [' ','Up',' ','Q','V','W','X','Y','Z'],
     ['!','$','%','^','*','/','&',',','.'],
     None,
@@ -62,18 +62,22 @@ keymap['number'] = [
     [' ',' ',' ',' ',' ',' ',' ','8',' '],
     [' ',' ',' ',' ',' ',' ',' ',' ','9'],
     None,
-    [' ',' ',' ',' ',' ',' ','*',' ','#', ' ', '0', ' ']
+    ['+',' ','-','.',' ','/','*',' ','#', ' ', '0', ' ']
     ]
-04034
 
 class TapInput(gtk.Window):
     def __init__(self):
         gtk.Window.__init__(self, type=gtk.WINDOW_POPUP)
-        self.set_default_size(320, 420)
+        #self.keysize = 80 Small for opaque
+        #self.keysize = 130 a bit large for transparent
+        self.keysize = 90
+        self.width = int(3*self.keysize)
+        self.height = int(4.2*self.keysize)
+        self.set_default_size(self.width, self.height)
         root = gtk.gdk.get_default_root_window()
         (x,y,width,height,depth) = root.get_geometry()
-        x = int((width-320)/2)
-        y = int((height-420)/2)
+        x = int((width-self.width)/2)
+        y = int((height-self.width)/2)
         self.move(x,y)
 
         self.fi = fakeinput()
@@ -114,7 +118,7 @@ class TapInput(gtk.Window):
         v.add(h)
 
         fd = pango.FontDescription('sans 10')
-        fd.set_absolute_size(30 * pango.SCALE)
+        fd.set_absolute_size(30 * pango.SCALE * self.keysize / 80)
         b = self.add_button('abc', self.nextmode, None, h, fd)
         self.modebutton = b
 
@@ -132,6 +136,9 @@ class TapInput(gtk.Window):
         self.update_buttons()
         self.connect("configure-event", self.update_buttons)
         self.hide()
+        self.visible = False
+        self.set_opacity(0.4)
+
 
     def add_button(self, label, click, arg, box, font = None):
         if not label:
@@ -144,6 +151,7 @@ class TapInput(gtk.Window):
         else:
             b = gtk.Button(label)
         b.show()
+        b.set_property('can-focus', False)
         if font:
             b.child.modify_font(font)
         b.connect('button_press_event', self.press, arg)
@@ -165,19 +173,22 @@ class TapInput(gtk.Window):
         size -= 12
         if size <= 10 or size == self.size:
             return
-        print "update buttons", size
+        #print "update buttons", size
         self.size = size
 
         # For each button in 3x3 we need 10 images,
         # one for initial state, and one for each of the new states
         # So there are two fonts we want.
         # First we make the initial images
-        fd = pango.FontDescription('sans 10')
-        fd.set_absolute_size(size / 4.5 * pango.SCALE)
-        self.modify_font(fd)
+        fdsingle = pango.FontDescription('sans 10')
+        fdsingle.set_absolute_size(size / 3.5 * pango.SCALE)
+        fdword = pango.FontDescription('sans 10')
+        fdword.set_absolute_size(size / 4.5 * pango.SCALE)
 
         bg = self.get_style().bg_gc[gtk.STATE_NORMAL]
-        fg = self.get_style().fg_gc[gtk.STATE_NORMAL]
+        #fg = self.get_style().fg_gc[gtk.STATE_NORMAL]
+        fg = self.window.new_gc()
+        fg.set_foreground(self.get_colormap().alloc_color(gtk.gdk.color_parse('blue')))
         red = self.window.new_gc()
         red.set_foreground(self.get_colormap().alloc_color(gtk.gdk.color_parse('red')))
         base_images = {}
@@ -208,6 +219,10 @@ class TapInput(gtk.Window):
                             if ypos != ypos%6:
                                 ypos = ypos%6
                                 colour = red
+                            if len(sym) == 1:
+                                self.modify_font(fdsingle)
+                            else:
+                                self.modify_font(fdword)
                             layout = self.create_pango_layout(sym[0:3])
                             (ink, (ex,ey,ew,eh)) = layout.get_pixel_extents()
                             pm.draw_layout(colour,
@@ -218,6 +233,7 @@ class TapInput(gtk.Window):
                     im.set_from_pixmap(pm, None)
                     base_images[mode][row*3+col] = im
         self.base_images = base_images
+        fd = pango.FontDescription('sans 10')
         fd.set_absolute_size(size / 1.5 * pango.SCALE)
         self.modify_font(fd)
         sup_images = {}
@@ -243,7 +259,7 @@ class TapInput(gtk.Window):
                             else:
                                 pm = gtk.gdk.Pixmap(self.window, size, size)
                                 pm.draw_rectangle(bg, True, 0, 0, size, size)
-                                layout = self.create_pango_layout(sym)
+                                layout = self.create_pango_layout(sym[0:3])
                                 (ink, (ex,ey,ew,eh)) = layout.get_pixel_extents()
                                 pm.draw_layout(fg,
                                                int((size - ew)/2), int((size - eh)/2),
@@ -290,11 +306,20 @@ class TapInput(gtk.Window):
         self.startx, self.starty  = self.get_position()
         if arg != None and self.taps == 1 and self.button_timeout == None and self.prefix == None:
             self.prefix1 = arg
-            self.button_timeout = gobject.timeout_add(500, self.do_buttons)
+            if not self.button_timeout:
+                self.button_timeout = gobject.timeout_add(300, self.do_buttons)
+        if arg == None:
+            # press-and-hold makes us disappear
+            if not self.button_timeout:
+                self.button_timeout = gobject.timeout_add(300, self.disappear)
 
     def release(self, widget, ev, click, arg):
         self.dragx = None
         self.dragy = None
+        if arg == None:
+            if self.button_timeout:
+                gobject.source_remove(self.button_timeout)
+                self.button_timeout = None
         if self.moved:
             self.moved = False
             self.noprefix()
@@ -307,6 +332,7 @@ class TapInput(gtk.Window):
             if xmid < 0 or xmid > rwidth or \
                ymid < 0 or ymid > rheight:
                 self.hide()
+                self.visible = False
         elif arg != None and self.taps == 1 and self.button_timeout:
             # quick tap in single tap mode, just enter the symbol
             gobject.source_remove(self.button_timeout)
@@ -316,6 +342,7 @@ class TapInput(gtk.Window):
             self.fi.send_char(sym)
         else:
             click(arg)
+
     def motion(self, widget, ev):
         if self.dragx == None:
             return
@@ -333,6 +360,11 @@ class TapInput(gtk.Window):
             gtk.gdk.flush()
             ev.window.get_pointer()
 
+    def disappear(self):
+        self.hide()
+        self.visible = False
+        self.dragx = None
+        self.dragy = None
 
     def do_buttons(self):
         self.set_button_images()
@@ -343,6 +375,8 @@ class TapInput(gtk.Window):
     def nextmode(self, a):
         if self.prefix:
             return self.noprefix()
+        if self.prefix1:
+            self.noprefix()
         if self.mode == 'lower':
             self.mode = 'UPPER'
             self.single = True
@@ -357,7 +391,7 @@ class TapInput(gtk.Window):
         else:
             self.mode = 'lower'
             self.taps = 2
-            self.modebutton.child.set_text('mode')
+            self.modebutton.child.set_text('abc')
         self.set_button_images()
 
     def delete(self, a):
@@ -386,21 +420,138 @@ class TapInput(gtk.Window):
     def activate(self, *a):
         root = gtk.gdk.get_default_root_window()
         (x,y,width,height,depth) = root.get_geometry()
-        x = int((width-320)/2)
-        y = int((height-420)/2)
-        self.move(x,y)
+        if self.window:
+            (wx,wy,ww,wh,wd) = self.window.get_geometry()
+        else:
+            wx,wy,ww,wh,wd = -1,-1,0,0,0
+        if wx < x or wy < y or wx+ww > width or wy+wh > height:
+            # partly off screen, so recentre
+            x = int((width-self.width)/2)
+            y = int((height-self.height)/2)
+            self.move(x,y)
+        else:
+            x,y = wx,wy
         self.fi.new_window()
+        self.hide()
         self.show()
+        self.visible = True
         self.move(x,y)
 
 
+
+class EvDev:
+    def __init__(self, path, on_event):
+        self.f = os.open(path, os.O_RDWR|os.O_NONBLOCK);
+        self.ev = gobject.io_add_watch(self.f, gobject.IO_IN, self.read)
+        self.on_event = on_event
+        self.grabbed = False
+        self.down_count = 0
+    def read(self, x, y):
+        try:
+            str = os.read(self.f, 16)
+        except:
+            return True
+
+        if len(str) != 16:
+            return True
+        (sec,usec,typ,code,value) = struct.unpack_from("IIHHI", str)
+        if typ == 0x01:
+            # KEY event
+            if value == 0:
+                self.down_count -= 1
+            else:
+                self.down_count += 1
+            if self.down_count < 0:
+                self.down_count = 0
+        self.on_event(self.down_count, typ, code, value)
+        return True
+    def grab(self):
+        if self.grabbed:
+            return
+        #print "grab"
+        fcntl.ioctl(self.f, EVIOC_GRAB, 1)
+        self.grabbed = True
+    def ungrab(self):
+        if not self.grabbed:
+            return
+        #print "release"
+        fcntl.ioctl(self.f, EVIOC_GRAB, 0)
+        self.grabbed = False
+
+
+
 class KeyboardIcon(gtk.StatusIcon):
-    def __init__(self, x):
+    def __init__(self, win = None):
         gtk.StatusIcon.__init__(self)
         self.set_from_file('/usr/local/pixmaps/tapinput.png')
-        self.connect('activate', x.activate)
+        if win:
+            self.connect('activate', win.activate)
+    def set_win(self, win):
+        if win:
+            self.connect('activate', win.activate)
+
+power_timer = None
+def power_pressed(cnt, type, code, value):
+    if type != 1:
+        # not a key press
+        return
+    if code != 116:
+        # not the power key
+        return
+    global power_timer
+    if value != 1:
+        # not a down press
+        if power_timer != None:
+            gobject.source_remove(power_timer)
+            power_timer = None
+        return
+    power_timer = gobject.timeout_add(300, power_held)
+
+def power_held():
+    global power_timer
+    power_timer = None
+    open("/sys/class/leds/neo1973:vibrator/trigger","w").write("default-on\n")
+    if win.visible:
+        win.hide()
+        win.visible = False
+    else:
+        win.activate()
+    open("/sys/class/leds/neo1973:vibrator/trigger","w").write("none\n")
+    return False
+
+last_tap = 0
+def tap_pressed(cnt, type, code, value):
+    global last_tap
+    if type != 1:
+        # not a key press
+        return
+    if code != 309:
+        # not BtnZ
+        return
+    if value != 1:
+        # only want dow, not up
+        return
+    now = time.time()
+    print now, last_tap
+    if now - last_tap < 0.2:
+        # two taps
+        if win.visible:
+            win.hide()
+            win.visible = False
+        else:
+            win.activate()
+        last_tap = 0
+    else:
+        last_tap = now
 
+ico = KeyboardIcon()
 win = TapInput()
-ico = KeyboardIcon(win)
+ico.set_win(win)
+#try:
+pbtn = EvDev("/dev/input/event0", power_pressed)
+tbtn = EvDev("/dev/input/event3", tap_pressed)
+#except:
+#    pass
+
 gtk.main()