summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Seguin <guillaume@segu.in>2007-11-17 23:42:35 +0100
committerGuillaume Seguin <guillaume@segu.in>2007-11-17 23:42:35 +0100
commitc6002f67ddf19f91f56bbadead21d8967b0f6159 (patch)
tree5b8ff1e6b3bb1607cbff6a61fd49c70bb0950464
downloadugok-c6002f67ddf19f91f56bbadead21d8967b0f6159.tar.gz
ugok-c6002f67ddf19f91f56bbadead21d8967b0f6159.tar.bz2
* Initial import
-rwxr-xr-xugok.py184
-rw-r--r--ugok/__init__.py0
-rw-r--r--ugok/default_map.py257
-rw-r--r--ugok/key.py52
-rwxr-xr-xugok/uinput.py110
-rwxr-xr-xugok/uinput_keymap.py266
6 files changed, 869 insertions, 0 deletions
diff --git a/ugok.py b/ugok.py
new file mode 100755
index 0000000..b756be2
--- /dev/null
+++ b/ugok.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+# coding=utf-8
+
+'''
+uGOK
+
+ # Minimal GTK onscreen keyboard #
+
+Copyright (C) 2007 Guillaume Seguin <guillaume@segu.in>
+
+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 2
+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, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+'''
+
+import pygtk
+pygtk.require ('2.0')
+
+import gtk
+import pango
+import sys
+
+from ugok.uinput import uinput
+from ugok.default_map import DEFAULT_KBMAP
+
+class uGOK (gtk.Window):
+ '''Keyboard window'''
+
+ icon_name = gtk.STOCK_SELECT_FONT
+ small_font = None
+
+ keys = []
+ rows = []
+ rows_box = None
+ current_row = None
+
+ pressed = []
+ locks = []
+
+ visible = False
+ tray_icon = None
+
+ uinput = None
+
+ def __init__ (self, kbmap = None):
+ '''Initialize object & create widgets'''
+ gtk.Window.__init__ (self)
+
+ self.set_title ("uGOK")
+ self.set_icon_name (self.icon_name)
+ self.set_keep_above (True)
+ self.set_position (gtk.WIN_POS_CENTER)
+ self.set_property ("accept-focus", False)
+ self.set_property ("skip-pager-hint", True)
+ self.set_property ("skip-taskbar-hint", True)
+
+ self.connect ("delete-event", gtk.main_quit)
+ self.connect ("window-state-event", self.on_state_event)
+
+ self.small_font = pango.FontDescription ("Sans 6")
+
+ self.tray_icon = gtk.status_icon_new_from_icon_name (self.icon_name)
+ self.tray_icon.connect ("activate", self.show_hide)
+
+ self.main_box = gtk.HBox ()
+ self.add (self.main_box)
+
+ if not kbmap:
+ kbmap = DEFAULT_KBMAP
+ self.add_keys (kbmap)
+ self.init_uinput ()
+ self.realize ()
+ self.set_resizable (False)
+
+ def init_uinput (self):
+ '''Initialize the uinput context'''
+ keys = [key.id for key in self.keys]
+ try:
+ self.uinput = uinput (keys)
+ except Exception, e:
+ print '''\033[1;31mFatal error\033[0m: failed to initialize the \
+uinput context:\n''', e
+ sys.exit (1)
+
+ def add_keys (self, kbmap):
+ '''Process keyboard map'''
+ self.rows_box = gtk.VBox ()
+ self.main_box.pack_start (self.rows_box, False, False)
+ map (self.add_row, kbmap)
+
+ def add_row (self, row):
+ '''Process key row'''
+ self.current_row = gtk.HBox ()
+ self.rows.append (self.current_row)
+ self.rows_box.pack_start (self.current_row, False, False)
+ map (self.add_key, row)
+
+ def add_key (self, key):
+ '''Process key'''
+ # Add key to the global list
+ self.keys.append (key)
+ # Create label
+ label = gtk.Label (key.label)
+ key.set_label = label.set_label
+ if key.small:
+ label.modify_font (self.small_font)
+ # Create widget
+ if key.sticky or key.lock:
+ btn = gtk.ToggleButton ()
+ btn.connect ("toggled", self.on_toggle, key)
+ else:
+ btn = gtk.Button ()
+ btn.connect ("pressed", self.on_press, key)
+ btn.connect ("released", self.on_release, key)
+ btn.add (label)
+ if key.width != -1:
+ btn.set_size_request (key.width, -1)
+ self.current_row.pack_start (btn, False, False)
+
+ def on_press (self, button, key):
+ '''Handle keypress event'''
+ self.uinput.press ([key.id])
+
+ def on_release (self, button, key):
+ '''Handle keyrelease event'''
+ self.uinput.release ([key.id])
+
+ def on_toggle (self, button, key):
+ '''Handle toggle event'''
+ if key.lock:
+ self.on_press (button, key)
+ self.on_release (button, key)
+ if key in self.locks:
+ self.locks.remove (key)
+ else:
+ self.locks.append (key)
+ self.apply_stickies ()
+ return
+ if key in self.pressed:
+ self.pressed.remove (key)
+ self.on_release (button, key)
+ else:
+ self.pressed.append (key)
+ self.on_press (button, key)
+ self.apply_stickies ()
+
+ def apply_stickies (self):
+ '''Apply sticky keys to buttons'''
+ mods = [key.id for key in self.pressed]
+ mods += [key.id for key in self.locks]
+ map (lambda k: k.apply_mods (mods), self.keys)
+
+ def show_hide (self, *args):
+ '''Show or hide window'''
+ if self.visible:
+ self.iconify ()
+ else:
+ self.deiconify ()
+
+ def on_state_event (self, window, event):
+ '''Update `visible` state variable if needed'''
+ if event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN \
+ or event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
+ self.visible = False
+ else:
+ self.visible = True
+
+if __name__ == "__main__":
+ app = uGOK ()
+ app.show_all ()
+ try:
+ gtk.main ()
+ except KeyboardInterrupt:
+ pass
diff --git a/ugok/__init__.py b/ugok/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ugok/__init__.py
diff --git a/ugok/default_map.py b/ugok/default_map.py
new file mode 100644
index 0000000..11eb50c
--- /dev/null
+++ b/ugok/default_map.py
@@ -0,0 +1,257 @@
+# coding=utf-8
+
+'''
+uGOK default keymap
+
+Copyright (C) 2007 Guillaume Seguin <guillaume@segu.in>
+
+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 2
+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, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+'''
+
+LSHIFT = "KEY_LEFTSHIFT"
+RSHIFT = "KEY_RIGHTSHIFT"
+CAPLCK = "KEY_CAPSLOCK"
+ALTGR = "KEY_RIGHTALT"
+
+from key import Key
+
+DEFAULT_KBMAP = [
+ [
+ Key ("Esc", "KEY_ESC"),
+ Key ("f1", "KEY_F1", w = 25, small = True),
+ Key ("f2", "KEY_F1", w = 25, small = True),
+ Key ("f3", "KEY_F1", w = 25, small = True),
+ Key ("f4", "KEY_F1", w = 25, small = True),
+ Key ("f5", "KEY_F1", w = 25, small = True),
+ Key ("f6", "KEY_F1", w = 25, small = True),
+ Key ("f7", "KEY_F1", w = 25, small = True),
+ Key ("f8", "KEY_F1", w = 25, small = True),
+ Key ("f9", "KEY_F1", w = 25, small = True),
+ Key ("f10", "KEY_F10", w = 25, small = True),
+ Key ("f11", "KEY_F11", w = 25, small = True),
+ Key ("f12", "KEY_F12", w = 25, small = True),
+ Key ("⇞", "KEY_PAGEUP", w = 25),
+ Key ("⇟", "KEY_PAGEDOWN", w = 25),
+ Key ("⇈", "KEY_HOME", w = 25),
+ Key ("⇊", "KEY_END", w = 25),
+ ],
+ [
+ Key ("²", "KEY_GRAVE", w = 20, modifiers = {LSHIFT : "~",
+ RSHIFT : "~",
+ CAPLCK : "²",
+ ALTGR : "¬"}),
+ Key ("&", "KEY_1", w = 25, modifiers = {LSHIFT : "1",
+ RSHIFT : "1",
+ ALTGR : "¹"}),
+ Key ("é", "KEY_2", w = 25, modifiers = {LSHIFT : "2",
+ RSHIFT : "2",
+ CAPLCK : "É",
+ ALTGR : "~"}),
+ Key ('"', "KEY_3", w = 25, modifiers = {LSHIFT : "3",
+ RSHIFT : "3",
+ ALTGR : "#"}),
+ Key ("'", "KEY_4", w = 25, modifiers = {LSHIFT : "4",
+ RSHIFT : "4",
+ ALTGR : "{"}),
+ Key ("(", "KEY_5", w = 25, modifiers = {LSHIFT : "5",
+ RSHIFT : "5",
+ ALTGR : "["}),
+ Key ("-", "KEY_6", w = 25, modifiers = {LSHIFT : "6",
+ RSHIFT : "6",
+ ALTGR : "|"}),
+ Key ("è", "KEY_7", w = 25, modifiers = {LSHIFT : "7",
+ RSHIFT : "7",
+ CAPLCK : "È",
+ ALTGR : "`"}),
+ Key ("_", "KEY_8", w = 25, modifiers = {LSHIFT : "8",
+ RSHIFT : "8",
+ ALTGR : "\\"}),
+ Key ("ç", "KEY_9", w = 25, modifiers = {LSHIFT : "9",
+ RSHIFT : "9",
+ CAPLCK : "Ç",
+ ALTGR : "^"}),
+ Key ("à", "KEY_0", w = 25, modifiers = {LSHIFT : "0",
+ RSHIFT : "0",
+ CAPLCK : "À",
+ ALTGR : "@"}),
+ Key (")", "KEY_MINUS", w = 25, modifiers = {LSHIFT : "°",
+ RSHIFT : "°",
+ ALTGR : "]"}),
+ Key ("=", "KEY_EQUAL", w = 25, modifiers = {LSHIFT : "+",
+ RSHIFT : "+",
+ ALTGR : "}"}),
+ Key ("⟽ ", "KEY_BACKSPACE"),
+ Key ("ins", "KEY_INSERT", small = True),
+ Key ("dele", "KEY_DELETE", small = True),
+ ],
+ [
+ Key ("⇆ ", "KEY_TAB"),
+ Key ("a", "KEY_A", w = 25, modifiers = {LSHIFT : "A",
+ RSHIFT : "A",
+ CAPLCK : "A",
+ ALTGR : "æ"}),
+ Key ("z", "KEY_Z", w = 25, modifiers = {LSHIFT : "Z",
+ RSHIFT : "Z",
+ CAPLCK : "Z",
+ ALTGR : "«"}),
+ Key ("e", "KEY_E", w = 25, modifiers = {LSHIFT : "E",
+ RSHIFT : "E",
+ CAPLCK : "E",
+ ALTGR : "€"}),
+ Key ("r", "KEY_R", w = 25, modifiers = {LSHIFT : "R",
+ RSHIFT : "R",
+ CAPLCK : "R",
+ ALTGR : "¶"}),
+ Key ("t", "KEY_T", w = 25, modifiers = {LSHIFT : "T",
+ RSHIFT : "T",
+ CAPLCK : "T",
+ ALTGR : "ŧ"}),
+ Key ("y", "KEY_Y", w = 25, modifiers = {LSHIFT : "Y",
+ RSHIFT : "Y",
+ CAPLCK : "Y",
+ ALTGR : "←"}),
+ Key ("u", "KEY_U", w = 25, modifiers = {LSHIFT : "U",
+ RSHIFT : "U",
+ CAPLCK : "U",
+ ALTGR : "↓"}),
+ Key ("i", "KEY_I", w = 25, modifiers = {LSHIFT : "I",
+ RSHIFT : "I",
+ CAPLCK : "I",
+ ALTGR : "→"}),
+ Key ("o", "KEY_O", w = 25, modifiers = {LSHIFT : "O",
+ RSHIFT : "O",
+ CAPLCK : "O",
+ ALTGR : "ø"}),
+ Key ("p", "KEY_P", w = 25, modifiers = {LSHIFT : "P",
+ RSHIFT : "P",
+ CAPLCK : "P",
+ ALTGR : "þ"}),
+ Key ("^", "KEY_LEFTBRACE", w = 25, modifiers = {LSHIFT : "¨",
+ RSHIFT : "¨",
+ ALTGR : "¨"}),
+ Key ("$", "KEY_RIGHTBRACE", w = 25, modifiers = {LSHIFT : "£",
+ RSHIFT : "£",
+ ALTGR : "¤"}),
+ Key ("⏎ ", "KEY_ENTER", w = 50),
+ ],
+ [
+ Key ("Caps", "KEY_CAPSLOCK", lock = True),
+ Key ("q", "KEY_Q", w = 25, modifiers = {LSHIFT : "Q",
+ RSHIFT : "Q",
+ CAPLCK : "Q",
+ ALTGR : "@"}),
+ Key ("s", "KEY_S", w = 25, modifiers = {LSHIFT : "S",
+ RSHIFT : "S",
+ CAPLCK : "S",
+ ALTGR : "ß"}),
+ Key ("d", "KEY_D", w = 25, modifiers = {LSHIFT : "D",
+ RSHIFT : "D",
+ CAPLCK : "D",
+ ALTGR : "ð"}),
+ Key ("f", "KEY_F", w = 25, modifiers = {LSHIFT : "F",
+ RSHIFT : "F",
+ CAPLCK : "F",
+ ALTGR : "đ"}),
+ Key ("g", "KEY_G", w = 25, modifiers = {LSHIFT : "G",
+ RSHIFT : "G",
+ CAPLCK : "G",
+ ALTGR : "ŋ"}),
+ Key ("h", "KEY_H", w = 25, modifiers = {LSHIFT : "H",
+ RSHIFT : "H",
+ CAPLCK : "H",
+ ALTGR : "ħ"}),
+ Key ("j", "KEY_J", w = 25, modifiers = {LSHIFT : "J",
+ RSHIFT : "J",
+ CAPLCK : "J",
+ ALTGR : "j"}),
+ Key ("k", "KEY_K", w = 25, modifiers = {LSHIFT : "K",
+ RSHIFT : "K",
+ CAPLCK : "K",
+ ALTGR : "ĸ"}),
+ Key ("l", "KEY_L", w = 25, modifiers = {LSHIFT : "L",
+ RSHIFT : "L",
+ CAPLCK : "L",
+ ALTGR : "ł"}),
+ Key ("m", "KEY_M", w = 25, modifiers = {LSHIFT : "M",
+ RSHIFT : "M",
+ CAPLCK : "M",
+ ALTGR : "µ"}),
+ Key ("ù", "KEY_APOSTROPHE", w = 25, modifiers = {LSHIFT : "%",
+ RSHIFT : "%",
+ CAPLCK : "Ù",
+ ALTGR : "^"}),
+ Key ("*", "KEY_BACKSLASH", w = 25, modifiers = {LSHIFT : "µ",
+ RSHIFT : "µ",
+ ALTGR : "`"}),
+ Key ("⏎ ", "KEY_ENTER", w = 45),
+ ],
+ [
+ Key ("⇧ ", "KEY_LEFTSHIFT", sticky = True),
+ Key ("<", "KEY_102ND", w = 20, modifiers = {LSHIFT : ">",
+ RSHIFT : ">",
+ ALTGR : "|"}),
+ Key ("w", "KEY_W", w = 25, modifiers = {LSHIFT : "W",
+ RSHIFT : "W",
+ CAPLCK : "W",
+ ALTGR : "ł"}),
+ Key ("x", "KEY_X", w = 25, modifiers = {LSHIFT : "X",
+ RSHIFT : "X",
+ CAPLCK : "X",
+ ALTGR : "»"}),
+ Key ("c", "KEY_C", w = 25, modifiers = {LSHIFT : "C",
+ RSHIFT : "C",
+ CAPLCK : "C",
+ ALTGR : "¢"}),
+ Key ("v", "KEY_V", w = 25, modifiers = {LSHIFT : "V",
+ RSHIFT : "V",
+ CAPLCK : "V",
+ ALTGR : "“"}),
+ Key ("b", "KEY_B", w = 25, modifiers = {LSHIFT : "B",
+ RSHIFT : "B",
+ CAPLCK : "B",
+ ALTGR : "”"}),
+ Key ("n", "KEY_N", w = 25, modifiers = {LSHIFT : "N",
+ RSHIFT : "N",
+ CAPLCK : "N",
+ ALTGR : "n"}),
+ Key (",", "KEY_COMMA", w = 25, modifiers = {LSHIFT : "?",
+ RSHIFT : "?",
+ ALTGR : "'"}),
+ Key (";", "KEY_SEMICOLON", w = 25, modifiers = {LSHIFT : ".",
+ RSHIFT : ".",
+ ALTGR : ""}),
+ Key (":", "KEY_DOT", w = 25, modifiers = {LSHIFT : "/",
+ RSHIFT : "/",
+ ALTGR : "·"}),
+ Key ("!", "KEY_SLASH", w = 25, modifiers = {LSHIFT : "§",
+ RSHIFT : "§",
+ ALTGR : ""}),
+ Key ("⇧ ", "KEY_RIGHTSHIFT", sticky = True),
+ Key ("▲", "KEY_UP"),
+ ],
+ [
+ Key ("Ctrl ", "KEY_LEFTCTRL", sticky = True),
+ Key (" ☼ ", "KEY_LEFTMETA", sticky = True),
+ Key ("Alt ", "KEY_LEFTALT", sticky = True),
+ Key (" " * 27, "KEY_SPACE"),
+ Key ("AltGr", "KEY_RIGHTALT", sticky = True),
+ Key (" ☼ ", "KEY_RIGHTMETA"),
+ Key ("▤", "KEY_MENU", w = 23),
+ Key ("Ctrl ", "KEY_RIGHTCTRL", sticky = True),
+ Key ("◄", "KEY_LEFT"),
+ Key ("▼", "KEY_DOWN"),
+ Key ("►", "KEY_RIGHT"),
+ ],
+ ]
diff --git a/ugok/key.py b/ugok/key.py
new file mode 100644
index 0000000..6d068d3
--- /dev/null
+++ b/ugok/key.py
@@ -0,0 +1,52 @@
+'''
+uGOK Key Object
+
+Copyright (C) 2007 Guillaume Seguin <guillaume@segu.in>
+
+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 2
+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, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+'''
+
+
+class Key:
+ '''Simple object defining a keyboard key'''
+
+ label = None
+ id = None
+ sticky = False
+ lock = False
+ width = -1
+ small = False
+ modifiers = {}
+
+ set_label = None
+
+ w = -1
+
+ def __init__ (self, label, id, *args, **kwargs):
+ '''Initialize object and assign properties'''
+ for arg in kwargs:
+ if hasattr (self, arg):
+ setattr (self, arg, kwargs[arg])
+ self.label = label
+ self.id = id
+ self.width = self.w
+
+ def apply_mods (self, modifiers):
+ '''Apply modifiers'''
+ mods = filter (lambda m: m in modifiers, self.modifiers)
+ if not len (mods):
+ self.set_label (self.label)
+ else:
+ self.set_label (self.modifiers[mods[0]])
diff --git a/ugok/uinput.py b/ugok/uinput.py
new file mode 100755
index 0000000..eb20f91
--- /dev/null
+++ b/ugok/uinput.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+
+'''
+uGOK uinput bridge
+
+Copyright (C) 2007 Guillaume Seguin <guillaume@segu.in>
+
+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 2
+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, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+'''
+
+import os, struct, fcntl, time, math
+from uinput_keymap import keymap
+
+class uinput:
+
+ input_event = "LLHHi"
+ UI_DEV_CREATE = 0x5501
+ UI_DEV_DESTROY = 0x5502
+ UI_SET_EVBIT = 0x40045564
+ UI_SET_KEYBIT = 0x40045565
+
+ EV_SYN = 0x00
+ EV_KEY = 0x01
+
+ BTN_MOUSE = 0x110
+ BUS_USB = 0x03
+ SYN_REPORT = 0
+
+ uinput_dev = None
+
+ revkeymap = {}
+ pressed = []
+
+ def __init__ (self, keys):
+ for key in keymap:
+ self.revkeymap[keymap[key]] = key
+ uinput_user_dev = "80sHHHHi" + 64*4*'I'
+ self.uinput_dev = os.open ("/dev/input/uinput", os.O_RDWR)
+ # Write device info
+ uud_str = [
+ "uGOK", # Device name
+ self.BUS_USB, # Bus type
+ 1, # Vendor
+ 1, # Product
+ 1, # Version
+ 0, # ff_effects_max
+ ]
+ for f in range (64*1): #absmin
+ uud_str.append (0x00)
+ for f in range (64*1): #absmax
+ uud_str.append (0x400) # absmax = 1024
+ for f in range (64*2): #absfuzz, absflat
+ uud_str.append (0x00)
+ uud = struct.pack (uinput_user_dev, *uud_str)
+ os.write (self.uinput_dev, uud)
+ # Set the event bits and register keys
+ fcntl.ioctl (self.uinput_dev, self.UI_SET_EVBIT, self.EV_KEY)
+ fcntl.ioctl (self.uinput_dev, self.UI_SET_EVBIT, self.EV_SYN)
+ fcntl.ioctl (self.uinput_dev, self.UI_SET_KEYBIT, self.BTN_MOUSE)
+ for key in keys:
+ keycode = int (self.get_keycode (key))
+ fcntl.ioctl (self.uinput_dev, self.UI_SET_KEYBIT, keycode)
+ # Create the device
+ fcntl.ioctl (self.uinput_dev, self.UI_DEV_CREATE)
+
+ def __del__ (self):
+ if self.uinput_dev:
+ os.close (self.uinput_dev)
+
+ def get_keycode (self, key):
+ return self.revkeymap[key]
+
+ def send_event (self, evtype, evcode, evval):
+ evstruct = struct.pack (self.input_event, time.time (), 0,
+ evtype, evcode, evval)
+ os.write (self.uinput_dev, evstruct)
+
+ def send_key (self, KEY_CONST):
+ self.send_keydown (KEY_CONST)
+ self.send_keyup (KEY_CONST)
+
+ def send_keydown (self, KEY_CONST):
+ self.send_event (self.EV_KEY, KEY_CONST, 1)
+ self.send_event (self.EV_SYN, self.SYN_REPORT, 0)
+
+ def send_keyup (self, KEY_CONST):
+ self.send_event (self.EV_KEY, KEY_CONST, 0)
+ self.send_event (self.EV_SYN, self.SYN_REPORT, 0)
+
+ def press (self, keys):
+ keys = filter (lambda key: key not in self.pressed, keys)
+ map (lambda key: self.pressed.append (key), keys)
+ map (lambda key: self.send_keydown (self.get_keycode (key)), keys)
+
+ def release (self, keys):
+ keys = filter (lambda key: key in self.pressed, keys)
+ map (lambda key: self.pressed.remove (key), keys)
+ map (lambda key: self.send_keyup (self.get_keycode (key)), keys)
diff --git a/ugok/uinput_keymap.py b/ugok/uinput_keymap.py
new file mode 100755
index 0000000..f1d19f9
--- /dev/null
+++ b/ugok/uinput_keymap.py
@@ -0,0 +1,266 @@
+keymap = {
+ 0: "KEY_RESERVED",
+ 1: "KEY_ESC",
+ 2: "KEY_1",
+ 3: "KEY_2",
+ 4: "KEY_3",
+ 5: "KEY_4",
+ 6: "KEY_5",
+ 7: "KEY_6",
+ 8: "KEY_7",
+ 9: "KEY_8",
+ 10: "KEY_9",
+ 11: "KEY_0",
+ 12: "KEY_MINUS",
+ 13: "KEY_EQUAL",
+ 14: "KEY_BACKSPACE",
+ 15: "KEY_TAB",
+ 16: "KEY_A",
+ 17: "KEY_Z",
+ 18: "KEY_E",
+ 19: "KEY_R",
+ 20: "KEY_T",
+ 21: "KEY_Y",
+ 22: "KEY_U",
+ 23: "KEY_I",
+ 24: "KEY_O",
+ 25: "KEY_P",
+ 26: "KEY_LEFTBRACE",
+ 27: "KEY_RIGHTBRACE",
+ 28: "KEY_ENTER",
+ 29: "KEY_LEFTCTRL",
+ 30: "KEY_Q",
+ 31: "KEY_S",
+ 32: "KEY_D",
+ 33: "KEY_F",
+ 34: "KEY_G",
+ 35: "KEY_H",
+ 36: "KEY_J",
+ 37: "KEY_K",
+ 38: "KEY_L",
+ 39: "KEY_M",
+ 40: "KEY_APOSTROPHE",
+ 41: "KEY_GRAVE",
+ 42: "KEY_LEFTSHIFT",
+ 43: "KEY_BACKSLASH",
+ 44: "KEY_W",
+ 45: "KEY_X",
+ 46: "KEY_C",
+ 47: "KEY_V",
+ 48: "KEY_B",
+ 49: "KEY_N",
+ 50: "KEY_COMMA",
+ 51: "KEY_SEMICOLON",
+ 52: "KEY_DOT",
+ 53: "KEY_SLASH",
+ 54: "KEY_RIGHTSHIFT",
+ 55: "KEY_KPASTERISK",
+ 56: "KEY_LEFTALT",
+ 57: "KEY_SPACE",
+ 58: "KEY_CAPSLOCK",
+ 59: "KEY_F1",
+ 60: "KEY_F2",
+ 61: "KEY_F3",
+ 62: "KEY_F4",
+ 63: "KEY_F5",
+ 64: "KEY_F6",
+ 65: "KEY_F7",
+ 66: "KEY_F8",
+ 67: "KEY_F9",
+ 68: "KEY_F10",
+ 69: "KEY_NUMLOCK",
+ 70: "KEY_SCROLLLOCK",
+ 71: "KEY_KP7",
+ 72: "KEY_KP8",
+ 73: "KEY_KP9",
+ 74: "KEY_KPMINUS",
+ 75: "KEY_KP4",
+ 76: "KEY_KP5",
+ 77: "KEY_KP6",
+ 78: "KEY_KPPLUS",
+ 79: "KEY_KP1",
+ 80: "KEY_KP2",
+ 81: "KEY_KP3",
+ 82: "KEY_KP0",
+ 83: "KEY_KPDOT",
+ 84: "KEY_103RD",
+ 85: "KEY_F13",
+ 86: "KEY_102ND",
+ 87: "KEY_F11",
+ 88: "KEY_F12",
+ 89: "KEY_F14",
+ 90: "KEY_F15",
+ 91: "KEY_F16",
+ 92: "KEY_F17",
+ 93: "KEY_F18",
+ 94: "KEY_F19",
+ 95: "KEY_F20",
+ 96: "KEY_KPENTER",
+ 97: "KEY_RIGHTCTRL",
+ 98: "KEY_KPSLASH",
+ 99: "KEY_SYSRQ",
+ 100: "KEY_RIGHTALT",
+ 101: "KEY_LINEFEED",
+ 102: "KEY_HOME",
+ 103: "KEY_UP",
+ 104: "KEY_PAGEUP",
+ 105: "KEY_LEFT",
+ 106: "KEY_RIGHT",
+ 107: "KEY_END",
+ 108: "KEY_DOWN",
+ 109: "KEY_PAGEDOWN",
+ 110: "KEY_INSERT",
+ 111: "KEY_DELETE",
+ 112: "KEY_MACRO",
+ 113: "KEY_MUTE",
+ 114: "KEY_VOLUMEDOWN",
+ 115: "KEY_VOLUMEUP",
+ 116: "KEY_POWER",
+ 117: "KEY_KPEQUAL",
+ 118: "KEY_KPPLUSMINUS",
+ 119: "KEY_PAUSE",
+ 120: "KEY_F21",
+ 121: "KEY_F22",
+ 122: "KEY_F23",
+ 123: "KEY_F24",
+ 124: "KEY_KPCOMMA",
+ 125: "KEY_LEFTMETA",
+ 126: "KEY_RIGHTMETA",
+ 127: "KEY_COMPOSE",
+ 128: "KEY_STOP",
+ 129: "KEY_AGAIN",
+ 130: "KEY_PROPS",
+ 131: "KEY_UNDO",
+ 132: "KEY_FRONT",
+ 133: "KEY_COPY",
+ 134: "KEY_OPEN",
+ 135: "KEY_PASTE",
+ 136: "KEY_FIND",
+ 137: "KEY_CUT",
+ 138: "KEY_HELP",
+ 139: "KEY_MENU",
+ 140: "KEY_CALC",
+ 141: "KEY_SETUP",
+ 142: "KEY_SLEEP",
+ 143: "KEY_WAKEUP",
+ 144: "KEY_FILE",
+ 145: "KEY_SENDFILE",
+ 146: "KEY_DELETEFILE",
+ 147: "KEY_XFER",
+ 148: "KEY_PROG1",
+ 149: "KEY_PROG2",
+ 150: "KEY_WWW",
+ 151: "KEY_MSDOS",
+ 152: "KEY_COFFEE",
+ 153: "KEY_DIRECTION",
+ 154: "KEY_CYCLEWINDOWS",
+ 155: "KEY_MAIL",
+ 156: "KEY_BOOKMARKS",
+ 157: "KEY_COMPUTER",
+ 158: "KEY_BACK",
+ 159: "KEY_FORWARD",
+ 160: "KEY_CLOSECD",
+ 161: "KEY_EJECTCD",
+ 162: "KEY_EJECTCLOSECD",
+ 163: "KEY_NEXTSONG",
+ 164: "KEY_PLAYPAUSE",
+ 165: "KEY_PREVIOUSSONG",
+ 166: "KEY_STOPCD",
+ 167: "KEY_RECORD",
+ 168: "KEY_REWIND",
+ 169: "KEY_PHONE",
+ 170: "KEY_ISO",
+ 171: "KEY_CONFIG",
+ 172: "KEY_HOMEPAGE",
+ 173: "KEY_REFRESH",
+ 174: "KEY_EXIT",
+ 175: "KEY_MOVE",
+ 176: "KEY_EDIT",
+ 177: "KEY_SCROLLUP",
+ 178: "KEY_SCROLLDOWN",
+ 179: "KEY_KPLEFTPAREN",
+ 180: "KEY_KPRIGHTPAREN",
+ 181: "KEY_INTL1",
+ 182: "KEY_INTL2",
+ 183: "KEY_INTL3",
+ 184: "KEY_INTL4",
+ 185: "KEY_INTL5",
+ 186: "KEY_INTL6",
+ 187: "KEY_INTL7",
+ 188: "KEY_INTL8",
+ 189: "KEY_INTL9",
+ 190: "KEY_LANG1",
+ 191: "KEY_LANG2",
+ 192: "KEY_LANG3",
+ 193: "KEY_LANG4",
+ 194: "KEY_LANG5",
+ 195: "KEY_LANG6",
+ 196: "KEY_LANG7",
+ 197: "KEY_LANG8",
+ 198: "KEY_LANG9",
+ 200: "KEY_PLAYCD",
+ 201: "KEY_PAUSECD",
+ 202: "KEY_PROG3",
+ 203: "KEY_PROG4",
+ 205: "KEY_SUSPEND",
+ 206: "KEY_CLOSE",
+ 220: "KEY_UNKNOWN",
+ 224: "KEY_BRIGHTNESSDOWN",
+ 225: "KEY_BRIGHTNESSUP",
+ 0x100: "BTN_0",
+ 0x101: "BTN_1",
+ 0x102: "BTN_2",
+ 0x103: "BTN_3",
+ 0x104: "BTN_4",
+ 0x105: "BTN_5",
+ 0x106: "BTN_6",
+ 0x107: "BTN_7",
+ 0x108: "BTN_8",
+ 0x109: "BTN_9",
+ 0x110: "BTN_LEFT",
+ 0x111: "BTN_RIGHT",
+ 0x112: "BTN_MIDDLE",
+ 0x113: "BTN_SIDE",
+ 0x114: "BTN_EXTRA",
+ 0x115: "BTN_FORWARD",
+ 0x116: "BTN_BACK",
+ 0x120: "BTN_TRIGGER",
+ 0x121: "BTN_THUMB",
+ 0x122: "BTN_THUMB2",
+ 0x123: "BTN_TOP",
+ 0x124: "BTN_TOP2",
+ 0x125: "BTN_PINKIE",
+ 0x126: "BTN_BASE",
+ 0x127: "BTN_BASE2",
+ 0x128: "BTN_BASE3",
+ 0x129: "BTN_BASE4",
+ 0x12a: "BTN_BASE5",
+ 0x12b: "BTN_BASE6",
+ 0x12f: "BTN_DEAD",
+ 0x130: "BTN_A",
+ 0x131: "BTN_B",
+ 0x132: "BTN_C",
+ 0x133: "BTN_X",
+ 0x134: "BTN_Y",
+ 0x135: "BTN_Z",
+ 0x136: "BTN_TL",
+ 0x137: "BTN_TR",
+ 0x138: "BTN_TL2",
+ 0x139: "BTN_TR2",
+ 0x13a: "BTN_SELECT",
+ 0x13b: "BTN_START",
+ 0x13c: "BTN_MODE",
+ 0x13d: "BTN_THUMBL",
+ 0x13e: "BTN_THUMBR",
+ 0x140: "BTN_TOOL_PEN",
+ 0x141: "BTN_TOOL_RUBBER",
+ 0x142: "BTN_TOOL_BRUSH",
+ 0x143: "BTN_TOOL_PENCIL",
+ 0x144: "BTN_TOOL_AIRBRUSH",
+ 0x145: "BTN_TOOL_FINGER",
+ 0x146: "BTN_TOOL_MOUSE",
+ 0x147: "BTN_TOOL_LENS",
+ 0x14a: "BTN_TOUCH",
+ 0x14b: "BTN_STYLUS",
+ 0x14c: "BTN_STYLUS2",
+ }