diff --git a/bindings/python/eekboard/Makefile.am b/bindings/python/eekboard/Makefile.am
index d3d1cb23..5209ea9f 100644
--- a/bindings/python/eekboard/Makefile.am
+++ b/bindings/python/eekboard/Makefile.am
@@ -15,7 +15,10 @@
 # along with this program.  If not, see
 # .
 
-pkgpython_PYTHON = \
-	__init__.py \
-	eekboard.py \
+pkgpython_PYTHON =				\
+	__init__.py				\
+	serializable.py				\
+	symbol.py				\
+	keysym.py				\
+	client.py				\
 	context.py
diff --git a/bindings/python/eekboard/__init__.py b/bindings/python/eekboard/__init__.py
index 3ca8dc17..d723f00e 100644
--- a/bindings/python/eekboard/__init__.py
+++ b/bindings/python/eekboard/__init__.py
@@ -15,53 +15,8 @@
 # along with this program.  If not, see
 # .
 
-from gi.repository import Eek, EekXkl, Gio
-
-from eekboard import Eekboard
-from context import Context
-
-Keyboard = Eek.Keyboard
-Section = Eek.Section
-Key = Eek.Key
-Symbol = Eek.Symbol
-Keysym = Eek.Keysym
-SymbolMatrix = Eek.SymbolMatrix
-
-MODIFIER_BEHAVIOR_NONE, \
-MODIFIER_BEHAVIOR_LOCK, \
-MODIFIER_BEHAVIOR_LATCH = \
-(Eek.ModifierBehavior.NONE,
- Eek.ModifierBehavior.LOCK,
- Eek.ModifierBehavior.LATCH)
-
-SymbolCategory = Eek.SymbolCategory
-
-CSW = 640
-CSH = 480
-
-def XmlKeyboard(path, modifier_behavior=MODIFIER_BEHAVIOR_NONE):
-    _file = Gio.file_new_for_path(path)
-    layout = Eek.XmlLayout.new(_file.read())
-    keyboard = Eek.Keyboard.new(layout, CSW, CSH)
-    keyboard.set_modifier_behavior(modifier_behavior)
-    keyboard.set_alt_gr_mask(Eek.ModifierType.MOD5_MASK)
-    return keyboard
-
-def XklKeyboard(modifier_behavior=MODIFIER_BEHAVIOR_NONE):
-    layout = EekXkl.Layout.new()
-    keyboard = Eek.Keyboard.new(layout, CSW, CSH)
-    keyboard.set_modifier_behavior(modifier_behavior)
-    return keyboard
-
-__all__ = ['Eekboard',
-           'Context',
-           'Keyboard',
-           'Section',
-           'Key',
-           'Symbol',
-           'Keysym',
-           'MODIFIER_BEHAVIOR_NONE',
-           'MODIFIER_BEHAVIOR_LOCK',
-           'MODIFIER_BEHAVIOR_LATCH',
-           'XmlKeyboard',
-           'XklKeyboard']
+from symbol import *
+from keysym import *
+from serializable import *
+from client import *
+from context import *
diff --git a/bindings/python/eekboard/eekboard.py b/bindings/python/eekboard/client.py
similarity index 57%
rename from bindings/python/eekboard/eekboard.py
rename to bindings/python/eekboard/client.py
index 0af27c9d..3b21cb5e 100644
--- a/bindings/python/eekboard/eekboard.py
+++ b/bindings/python/eekboard/client.py
@@ -15,12 +15,14 @@
 # along with this program.  If not, see
 # .
 
-from gi.repository import Gio
-import gi.repository
+import dbus
+import dbus.mainloop.glib
 import gobject
 from context import Context
 
-class Eekboard(gobject.GObject):
+dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)
+
+class Client(gobject.GObject):
     __gtype_name__ = "PYEekboardClient"
     __gsignals__ = {
         'destroyed': (
@@ -30,20 +32,25 @@ class Eekboard(gobject.GObject):
         }
 
     def __init__(self):
-        super(Eekboard, self).__init__()
-        self.__connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
-        self.__client = gi.repository.Eekboard.Client.new(self.__connection, None);
-        self.__client.connect('destroyed', lambda *args: self.emit('destroyed'))
+        super(Client, self).__init__()
+        self.__bus = dbus.SessionBus()
+        _service = self.__bus.get_object("org.fedorahosted.Eekboard",
+                                         "/org/fedorahosted/Eekboard")
+        self.__service = dbus.Interface(_service, dbus_interface="org.fedorahosted.Eekboard")
+        self.__service.connect_to_signal("Destroyed", self.__destroyed_cb)
+
+    def __destroyed_cb(self):
+        self.emit("destroyed")
 
     def create_context(self, client_name):
-        context = self.__client.create_context(client_name, None)
-        return Context(context)
+        object_path = self.__service.CreateContext(client_name)
+        return Context(self.__bus, object_path)
 
     def push_context(self, context):
-        self.__client.push_context(context.get_giobject(), None)
+        self.__service.PushContext(context.object_path)
 
     def pop_context(self):
-        self.__client.pop_context(None)
+        self.__service.PopContext()
 
     def destroy_context(self, context):
-        self.__client.destroy_context(context.get_giobject(), None)
+        self.__service.DestroyContext(context.object_path)
diff --git a/bindings/python/eekboard/context.py b/bindings/python/eekboard/context.py
index b4cb66f9..009e50c8 100644
--- a/bindings/python/eekboard/context.py
+++ b/bindings/python/eekboard/context.py
@@ -15,8 +15,9 @@
 # along with this program.  If not, see
 # .
 
-from gi.repository import Eekboard
+import dbus
 import gobject
+import serializable
 
 class Context(gobject.GObject):
     __gtype_name__ = "PYEekboardContext"
@@ -32,11 +33,7 @@ class Context(gobject.GObject):
         'key-pressed': (
             gobject.SIGNAL_RUN_LAST,
             gobject.TYPE_NONE,
-            (gobject.TYPE_UINT,)),
-        'key-released': (
-            gobject.SIGNAL_RUN_LAST,
-            gobject.TYPE_NONE,
-            (gobject.TYPE_UINT,)),
+            (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_UINT)),
         'destroyed': (
             gobject.SIGNAL_RUN_LAST,
             gobject.TYPE_NONE,
@@ -44,19 +41,59 @@ class Context(gobject.GObject):
         }
 
     __gproperties__ = {
-        'keyboard-visible': (bool, None, None, False, gobject.PARAM_READWRITE),
+        'visible': (gobject.TYPE_BOOLEAN, 'Visible', 'Visible',
+                    False, gobject.PARAM_READWRITE),
+        'keyboard': (gobject.TYPE_UINT, 'Keyboard', 'Keyboard',
+                     0, gobject.G_MAXUINT, 0, gobject.PARAM_READWRITE),
+        'group': (gobject.TYPE_UINT, 'Group', 'Group',
+                  0, gobject.G_MAXUINT, 0, gobject.PARAM_READWRITE),
         }
 
-    def __init__(self, giobject):
+    def __init__(self, bus, object_path):
         super(Context, self).__init__()
-        self.__properties = dict()
-        self.__giobject = giobject
-        self.__giobject.connect('enabled', lambda *args: self.emit('enabled'))
-        self.__giobject.connect('disabled', lambda *args: self.emit('disabled'))
-        self.__giobject.connect('key-pressed', lambda *args: self.emit('key-pressed', args[1]))
-        self.__giobject.connect('key-released', lambda *args: self.emit('key-released', args[1]))
-        self.__giobject.connect('destroyed', lambda *args: self.emit('destroyed'))
-        self.__giobject.connect('notify::keyboard-visible', self.__notify_keyboard_visible_cb)
+        self.__bus = bus
+        self.__object_path = object_path
+        self.__properties = {}
+        _context = self.__bus.get_object("org.fedorahosted.Eekboard",
+                                         object_path)
+        self.__context = dbus.Interface(_context, dbus_interface="org.fedorahosted.Eekboard.Context")
+
+        self.__context.connect_to_signal('Enabled', self.__enabled_cb)
+        self.__context.connect_to_signal('Disabled', self.__disabled_cb)
+        self.__context.connect_to_signal('KeyPressed', self.__key_pressed_cb)
+        self.__context.connect_to_signal('Destroyed', self.__destroyed_cb)
+        self.__context.connect_to_signal('VisibilityChanged', self.__visibility_changed_cb)
+        self.__context.connect_to_signal('KeyboardChanged', self.__keyboard_changed_cb)
+        self.__context.connect_to_signal('GroupChanged', self.__group_changed_cb)
+
+    object_path = property(lambda self: self.__object_path)
+
+    def __enabled_cb(self):
+        self.emit('enabled')
+
+    def __disabled_cb(self):
+        self.emit('disabled')
+
+    def __key_pressed_cb(self, *args):
+        keyname = args[0]
+        symbol = serializable.deserialize_object(args[1])
+        modifiers = args[2]
+        self.emit('key-pressed', keyname, symbol, modifiers)
+
+    def __visibility_changed_cb(self, *args):
+        self.set_property('visible', args[0])
+        self.notify('visible')
+
+    def __keyboard_changed_cb(self, *args):
+        self.set_property('keyboard', args[0])
+        self.notify('keyboard')
+
+    def __group_changed_cb(self, *args):
+        self.set_property('group', args[0])
+        self.notify('group')
+
+    def __destroyed_cb(self):
+        self.emit("destroyed")
 
     def do_set_property(self, pspec, value):
         self.__properties[pspec.name] = value
@@ -64,37 +101,26 @@ class Context(gobject.GObject):
     def do_get_property(self, pspec):
         return self.__properties[pspec.name]
 
-    def __notify_keyboard_visible_cb(self, *args):
-        self.set_property('keyboard-visible',
-                          self.__giobject.get_property(args[1].name))
-        self.notify('keyboard-visible')
-
-    def get_giobject(self):
-        return self.__giobject
-
-    def add_keyboard(self, keyboard):
-        return self.__giobject.add_keyboard(keyboard, None)
+    def add_keyboard(self, keyboard_type):
+        return self.__context.AddKeyboard(keyboard_type)
 
     def remove_keyboard(self, keyboard_id):
-        return self.__giobject.remove_keyboard(keyboard_id, None)
+        return self.__context.RemoveKeyboard(keyboard_id)
         
     def set_keyboard(self, keyboard_id):
-        self.__giobject.set_keyboard(keyboard_id, None)
+        self.__context.SetKeyboard(keyboard_id)
 
     def show_keyboard(self):
-        self.__giobject.show_keyboard(None)
+        self.__context.ShowKeyboard()
 
     def hide_keyboard(self):
-        self.__giobject.hide_keyboard(None)
+        self.__context.HideKeyboard()
 
     def set_group(self, group):
-        self.__giobject.set_group(group, None)
+        self.__context.SetGroup(group)
 
-    def press_key(self, keycode):
-        self.__giobject.press_key(keycode, None)
+    def press_keycode(self, keycode):
+        self.__context.PressKeycode(keycode)
 
-    def release_key(self, keycode):
-        self.__giobject.release_key(keycode, None)
-
-    def is_enabled(self):
-        return self.__giobject.is_enabled()
+    def release_keycode(self, keycode):
+        self.__context.ReleaseKeycode(keycode)
diff --git a/bindings/python/eekboard/keysym.py b/bindings/python/eekboard/keysym.py
new file mode 100644
index 00000000..b787e709
--- /dev/null
+++ b/bindings/python/eekboard/keysym.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2011 Daiki Ueno 
+# Copyright (C) 2011 Red Hat, Inc.
+
+# 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
+# .
+
+import symbol
+
+class Keysym(symbol.Symbol):
+    __gtype_name__ = "PYEekKeysym"
+    __NAME__ = "EekKeysym"
+
+    def __init__(self):
+        super(Keysym, self).__init__()
+
+    xkeysym = property(lambda self: self.xkeysym)
+
+    def serialize(self, struct):
+        super(Keysym, self).serialize(struct)
+        struct.append(dbus.UInt32(self.__xkeysym))
+
+    def deserialize(self, struct):
+        super(Keysym, self).deserialize(struct)
+        self.__xkeysym = struct.pop(0)
diff --git a/bindings/python/eekboard/serializable.py b/bindings/python/eekboard/serializable.py
new file mode 100644
index 00000000..ad82a4a5
--- /dev/null
+++ b/bindings/python/eekboard/serializable.py
@@ -0,0 +1,76 @@
+# vim:set et sts=4 sw=4:
+#
+# ibus - The Input Bus
+#
+# Copyright (c) 2007-2010 Peng Huang 
+# Copyright (c) 2007-2010 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA  02111-1307  USA
+
+__all__ = (
+        "Serializable",
+        "serialize_object",
+        "deserialize_object",
+    )
+
+import dbus
+import gobject
+
+__serializable_name_dict = dict()
+
+def serializable_register(classobj):
+    # if not issubclass(classobj, Serializable):
+    #     raise "%s is not a sub-class of Serializable" % str(classobj)
+    __serializable_name_dict[classobj.__NAME__] = classobj
+
+def serialize_object(o):
+    if isinstance(o, Serializable):
+        l = [o.__NAME__]
+        o.serialize(l)
+        return dbus.Struct(l)
+    else:
+        return o
+
+def deserialize_object(v):
+    if isinstance(v, tuple):
+        struct = list(v)
+        type_name = struct.pop(0)
+        type_class = __serializable_name_dict[type_name]
+        o = type_class()
+        o.deserialize (struct)
+        return o
+    return v
+
+class SerializableMeta(gobject.GObjectMeta):
+    def __init__(cls, name, bases, dict_):
+        super(SerializableMeta, cls).__init__(name, bases, dict_)
+        if "__NAME__" in cls.__dict__:
+            serializable_register(cls)
+
+class Serializable(gobject.GObject):
+    __metaclass__ = SerializableMeta
+    __gtype_name__ = "PYEekSerializable"
+    __NAME__ = "EekSerializable"
+    def __init__(self):
+        super(Serializable, self).__init__()
+
+    def serialize(self, struct):
+        pass
+
+    def deserialize(self, struct):
+        pass
+
+__serializable_name_dict["EekSerializable"] = Serializable
diff --git a/bindings/python/eekboard/symbol.py b/bindings/python/eekboard/symbol.py
new file mode 100644
index 00000000..00d38562
--- /dev/null
+++ b/bindings/python/eekboard/symbol.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2011 Daiki Ueno 
+# Copyright (C) 2011 Red Hat, Inc.
+
+# 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
+# .
+
+import serializable
+
+class Symbol(serializable.Serializable):
+    __gtype_name__ = "PYEekSymbol"
+    __NAME__ = "EekSymbol"
+
+    def __init__(self):
+        super(Symbol, self).__init__()
+
+    name = property(lambda self: self.__name)
+    label = property(lambda self: self.__label)
+    category = property(lambda self: self.__category)
+    modifier_mask = property(lambda self: self.__modifier_mask)
+    icon_name = property(lambda self: self.__icon_name)
+
+    def serialize(self, struct):
+        super(Symbol, self).serialize(struct)
+        struct.append(dbus.String(self.__name))
+        struct.append(dbus.String(self.__label))
+        struct.append(dbus.UInt32(self.__category))
+        struct.append(dbus.UInt32(self.__modifier_mask))
+        struct.append(dbus.String(self.__icon_name))
+
+    def deserialize(self, struct):
+        super(Symbol, self).deserialize(struct)
+        self.__name = struct.pop(0)
+        self.__label = struct.pop(0)
+        self.__category = struct.pop(0)
+        self.__modifier_mask = struct.pop(0)
+        self.__icon_name = struct.pop(0)