diff options
Diffstat (limited to 'ibus')
-rw-r--r-- | ibus/.gitignore | 1 | ||||
-rw-r--r-- | ibus/Makefile.am | 8 | ||||
-rw-r--r-- | ibus/__init__.py | 6 | ||||
-rw-r--r-- | ibus/_gtk.py (renamed from ibus/gtk.py) | 4 | ||||
-rw-r--r-- | ibus/attribute.py | 99 | ||||
-rw-r--r-- | ibus/bus.py | 358 | ||||
-rw-r--r-- | ibus/common.py | 34 | ||||
-rw-r--r-- | ibus/component.py | 131 | ||||
-rw-r--r-- | ibus/config.py | 96 | ||||
-rw-r--r-- | ibus/engine.py | 63 | ||||
-rw-r--r-- | ibus/enginedesc.py | 106 | ||||
-rw-r--r-- | ibus/factory.py | 102 | ||||
-rw-r--r-- | ibus/inputcontext.py | 301 | ||||
-rw-r--r-- | ibus/interface/Makefile.am | 1 | ||||
-rw-r--r-- | ibus/interface/__init__.py | 1 | ||||
-rw-r--r-- | ibus/interface/iconfig.py | 8 | ||||
-rw-r--r-- | ibus/interface/iengine.py | 33 | ||||
-rw-r--r-- | ibus/interface/ienginefactory.py | 10 | ||||
-rw-r--r-- | ibus/interface/iibus.py | 81 | ||||
-rw-r--r-- | ibus/interface/iinputcontext.py | 133 | ||||
-rw-r--r-- | ibus/interface/inotifications.py | 8 | ||||
-rw-r--r-- | ibus/interface/ipanel.py | 36 | ||||
-rw-r--r-- | ibus/lookuptable.py | 133 | ||||
-rw-r--r-- | ibus/notifications.py | 10 | ||||
-rw-r--r-- | ibus/object.py | 19 | ||||
-rw-r--r-- | ibus/observedpath.py | 64 | ||||
-rw-r--r-- | ibus/panel.py | 124 | ||||
-rw-r--r-- | ibus/property.py | 131 | ||||
-rw-r--r-- | ibus/serializable.py | 81 | ||||
-rw-r--r-- | ibus/text.py | 68 |
30 files changed, 1509 insertions, 741 deletions
diff --git a/ibus/.gitignore b/ibus/.gitignore new file mode 100644 index 0000000..56b6ff1 --- /dev/null +++ b/ibus/.gitignore @@ -0,0 +1 @@ +_config.py diff --git a/ibus/Makefile.am b/ibus/Makefile.am index 43b9121..fba01c6 100644 --- a/ibus/Makefile.am +++ b/ibus/Makefile.am @@ -28,10 +28,11 @@ ibus_PYTHON = \ attribute.py \ common.py \ bus.py \ + inputcontext.py \ engine.py \ exception.py \ factory.py \ - gtk.py \ + _gtk.py \ __init__.py \ keysyms.py \ lang.py \ @@ -41,6 +42,11 @@ ibus_PYTHON = \ panel.py \ notifications.py \ property.py \ + serializable.py \ + text.py \ + component.py \ + enginedesc.py \ + observedpath.py \ utility.py \ config.py \ _config.py \ diff --git a/ibus/__init__.py b/ibus/__init__.py index 401d31b..08432a3 100644 --- a/ibus/__init__.py +++ b/ibus/__init__.py @@ -27,6 +27,7 @@ from interface import * from exception import * from lookuptable import * from bus import * +from inputcontext import * from lang import * from utility import * from engine import * @@ -34,4 +35,9 @@ from factory import * from panel import * from notifications import * from config import * +from serializable import * +from text import * +from observedpath import * +from enginedesc import * +from component import * from _config import * diff --git a/ibus/gtk.py b/ibus/_gtk.py index eb82929..b9874a6 100644 --- a/ibus/gtk.py +++ b/ibus/_gtk.py @@ -47,13 +47,13 @@ class PangoAttrList(pango.AttrList): r = (attr.value & 0x00ff0000) >> 8 g = (attr.value & 0x0000ff00) b = (attr.value & 0x000000ff) << 8 - pango_attr = pango.AttrForeground(r, g, b, + pango_attr = pango.AttrForeground(r, g, b, start_index, end_index) elif attr.type == ibus.ATTR_TYPE_BACKGROUND: r = (attr.value & 0x00ff0000) >> 8 g = (attr.value & 0x0000ff00) b = (attr.value & 0x000000ff) << 8 - pango_attr = pango.AttrBackground(r, g, b, + pango_attr = pango.AttrBackground(r, g, b, start_index, end_index) elif attr.type == ibus.ATTR_TYPE_UNDERLINE: pango_attr = pango.AttrUnderline(int(attr.value), diff --git a/ibus/attribute.py b/ibus/attribute.py index 144133a..ef4b6a4 100644 --- a/ibus/attribute.py +++ b/ibus/attribute.py @@ -32,12 +32,12 @@ __all__ = ( "AttributeForeground", "AttributeBackground", "AttrList", - "attribute_from_dbus_value", - "attr_list_from_dbus_value", "ARGB", "RGB" ) import dbus +from exception import IBusException +from serializable import * ATTR_TYPE_UNDERLINE = 1 ATTR_TYPE_FOREGROUND = 2 @@ -48,8 +48,10 @@ ATTR_UNDERLINE_SINGLE = 1 ATTR_UNDERLINE_DOUBLE = 2 ATTR_UNDERLINE_LOW = 3 -class Attribute: - def __init__ (self, type, value, start_index, end_index): +class Attribute(Serializable): + __NAME__ = "IBusAttribute" + def __init__ (self, type=0, value=0, start_index=0, end_index=0): + super(Attribute, self).__init__() self.__type = type self.__value = value self.__start_index = start_index @@ -72,30 +74,25 @@ class Attribute: start_index = property(get_start_index) end_index = property(get_end_index) - def to_dbus_value (self): - values = [dbus.UInt32 (self.__type), - dbus.UInt32 (self.__value), - dbus.UInt32 (self.__start_index), - dbus.UInt32 (self.__end_index)] - return dbus.Struct (values, signature="uuuu") - - def from_dbus_value (self, value): - if not isinstance (value, dbus.Struct): - raise dbus.Exception ("Attribute must be dbus.Struct uuuu") - - if len (value) != 4 or not all (map (lambda x: isinstance (x, dbus.UInt32), value)): - raise dbus.Exception ("Attribute must be dbus.Struct uuuu") - - self.__type = value[0] - self.__value = value[1] - self.__start_index = value[2] - self.__end_index = value[3] - -def attribute_from_dbus_value (value): - attribute = Attribute (0, 0, 0, 0) - attribute.from_dbus_value (value) - return attribute - + def serialize(self, struct): + super(Attribute, self).serialize(struct) + struct.append (dbus.UInt32(self.__type)) + struct.append (dbus.UInt32(self.__value)) + struct.append (dbus.UInt32(self.__start_index)) + struct.append (dbus.UInt32(self.__end_index)) + + def deserialize(self, struct): + super(Attribute, self).deserialize(struct) + if len(struct) < 4: + raise IBusException ("Can not deserialize IBusAttribute") + + self.__type = struct.pop(0) + self.__value = struct.pop(0) + self.__start_index = struct.pop(0) + self.__end_index = struct.pop(0) + +serializable_register(Attribute) + class AttributeUnderline (Attribute): def __init__(self, value, start_index, end_index): Attribute.__init__ (self, ATTR_TYPE_UNDERLINE, value, start_index, end_index) @@ -114,8 +111,10 @@ def ARGB (a, r, g, b): def RGB (r, g, b): return ARGB (255, r, g, b) -class AttrList: +class AttrList(Serializable): + __NAME__ = "IBusAttrList" def __init__ (self, attrs = []): + super(AttrList, self).__init__() self._attrs = [] for attr in attrs: self.append (attr) @@ -124,29 +123,31 @@ class AttrList: assert isinstance (attr, Attribute) self._attrs.append (attr) - def to_dbus_value (self): - array = dbus.Array (signature = "v") - for attr in self._attrs: - array.append (attr.to_dbus_value ()) - return array - - def from_dbus_value (self, value): - attrs = [] - if not isinstance (value, dbus.Array): - raise IBusException ("AttrList must from dbus.Array (uuuu)") - - for v in value: - attr = attribute_from_dbus_value (v) - attrs.append (attr) + def serialize (self, struct): + super(AttrList, self).serialize (struct) + array = map (lambda a: serialize_object(a), self._attrs) + array = dbus.Array (array, signature = "v") + struct.append(array) + def deserialize (self, struct): + super(AttrList, self).deserialize(struct) + attrs = map(lambda v: deserialize_object(v), struct.pop(0)) self._attrs = attrs def __iter__ (self): return self._attrs.__iter__ () -def attr_list_from_dbus_value (value): - if len(value) == 0: - return None - attrs = AttrList () - attrs.from_dbus_value (value) - return attrs +serializable_register(AttrList) + +def test(): + attr_list = AttrList() + attr_list.append (Attribute()) + attr_list.append (Attribute()) + attr_list.append (Attribute()) + attr_list.append (Attribute()) + attr_list.append (Attribute()) + value = serialize_object(attr_list) + attr_list = deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/bus.py b/ibus/bus.py index eb708a6..6ca5f7d 100644 --- a/ibus/bus.py +++ b/ibus/bus.py @@ -23,95 +23,27 @@ __all__ = ( "Bus", ) -import sys -import gobject import dbus import dbus.lowlevel import dbus.connection import dbus.mainloop.glib -import ibus +import gobject +import common +import object +import serializable +import config dbus.mainloop.glib.DBusGMainLoop(set_as_default = True) -class Bus(ibus.Object): +class Bus(object.Object): __gsignals__ = { - "commit-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING) - ), - "update-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_INT, gobject.TYPE_BOOLEAN) - ), - "show-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "hide-preedit" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "update-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) - ), - "show-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "hide-aux-string" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "update-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) - ), - "show-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "hide-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "page-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "page-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "cursor-up-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "cursor-down-lookup-table" : ( - gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING, ) - ), - "config-value-changed" : ( - gobject.SIGNAL_RUN_FIRST, + "disconnected" : ( + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, - (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + () ), "config-reloaded" : ( - gobject.SIGNAL_RUN_FIRST, + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () ), @@ -119,29 +51,36 @@ class Bus(ibus.Object): def __init__(self): super(Bus, self).__init__() - self.__dbusconn = dbus.connection.Connection(ibus.IBUS_ADDR) - self.__ibus = self.__dbusconn.get_object(ibus.IBUS_NAME, - ibus.IBUS_PATH) + self.__dbusconn = dbus.connection.Connection(common.IBUS_ADDR) self.__dbus = self.__dbusconn.get_object(dbus.BUS_DAEMON_NAME, - dbus.BUS_DAEMON_PATH) - self.__dbusconn.add_message_filter(self.__dbus_message_cb) + dbus.BUS_DAEMON_PATH) self.__unique_name = self.hello() + self.__ibus = self.__dbusconn.get_object(common.IBUS_SERVICE_IBUS, + common.IBUS_PATH_IBUS) - try: - unique_name = self.get_name_owner(ibus.IBUS_CONFIG_NAME) - self.__config = self.__dbusconn.get_object(unique_name, - ibus.IBUS_CONFIG_PATH) - except: - self.__config = None - self.add_match( - "type='signal'," - "interface='" + dbus.BUS_DAEMON_IFACE + "'," - "member='NameOwnerChanged'," - "arg0='" + ibus.IBUS_CONFIG_NAME + "'") + self.__dbusconn.call_on_disconnection(self.__dbusconn_disconnected_cb) + # self.__dbusconn.add_message_filter(self.__filter_cb) + + def __filter_cb(self, conn, message): + if message.get_type() == 4: + print "Signal %s" % message.get_member() + print " sender = %s" % message.get_sender() + print " path = %s" % message.get_path() + return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED + + def __dbusconn_disconnected_cb(self, dbusconn): + assert self.__dbusconn == dbusconn + self.__dbusconn = None + self.emit("disconnected") def get_name(self): return self.__unique_name + def get_is_connected(self): + if self.__dbusconn == None: + return False + return self.__dbusconn.get_is_connected() + # define dbus methods def get_dbus(self): return self.__dbus @@ -150,7 +89,7 @@ class Bus(ibus.Object): return self.__dbus.Hello() def request_name(self, name, flags): - return self.__dbus.RequestName(name, flags) + return self.__dbus.RequestName(name, dbus.UInt32 (flags)) def release_name(self, name): return self.__dbus.ReleaseName(name) @@ -168,209 +107,56 @@ class Bus(ibus.Object): return self.__dbusconn def get_address(self): - return ibus.IBUS_ADDR - - def create_input_context(self, client_name): - return self.__ibus.CreateInputContext(client_name) - - def release_input_context(self, ic): - return self.__ibus.ReleaseInputContext(ic) - - def process_key_event(self, ic, keyval, is_press, state): - return self.__ibus.ProcessKeyEvent(ic, keyval, is_press, state) - - def set_cursor_location(self, ic, x, y, w, h): - return self.__ibus.SetCursorLocation(ic, x, y, w, h) - - def foucs_in(self, ic): - return self.__ibus.FocusIn(ic) - - def foucs_out(self, ic): - return self.__ibus.FocusOut(ic) - - def reset(self, ic): - return self.__ibus.Reset(ic) + return common.IBUS_ADDR - def is_enabled(self, ic): - return self.__ibus.IsEnabled(ic) + # define ibus methods + def register_component(self, component): + component = serializable.serialize_object(component) + return self.__ibus.RegisterComponent(component) - def set_capabilities(self, ic, caps): - return self.__ibus.SetCapabilities(ic, caps) + def list_engines(self): + engines = self.__ibus.ListEngines() + return map(serializable.deserialize_object, engines) - def register_factories(self, object_paths): - object_paths = dbus.Array(object_paths, signature="o") - return self.__ibus.RegisterFactories(object_paths, **ibus.DEFAULT_ASYNC_HANDLERS) + def list_active_engines(self): + engines = self.__ibus.ListActiveEngines() + return map(serializable.deserialize_object, engines) - def unregister_factories(self, object_paths): - return self.__ibus.UnregisterFactories(object_paths) - - def register_config(self, object_path, replace = False): - return self.__ibus.RegisterConfig(object_path, replace) - - def get_factories(self): - return self.__ibus.GetFactories() - - def get_factory_info(self, factory_path): - return self.__ibus.GetFactoryInfo(factory_path) - - def set_factory(self, factory_path): - return self.__ibus.SetFactory(factory_path) - - def get_input_context_states(self, ic): - return self.__ibus.GetInputContextStates(ic) - - def config_add_watch(self, section): - return self.add_match( - "type='signal'," - "interface='" + ibus.IBUS_CONFIG_NAME + "'," - "member='ValueChanged'," - "arg0='" + section + "'" - ) + def create_input_context(self, client_name): + return self.__ibus.CreateInputContext(client_name) - def config_remove_watch(self, section): - return self.remove_match( - "type='signal'," - "interface='" + ibus.IBUS_CONFIG_NAME + "'," - "member='ValueChanged'," - "arg0='" + section + "'" - ) + def kill(self): + return self.__ibus.Kill() - def config_set_value(self, section, name, value): - return self.__config.SetValue(section, name, value) + def get_config(self): + try: + return self.__config + except: + self.__config = config.Config(self) + return self.__config - def config_set_list(self, section, name, value, list_type): - value = dbus.Array(value, signature = list_type) - return self.__config.SetValue(section, name, value) +def test(): + import glib + import factory + import text - def config_get_value(self, section, name, default_value = None): - try: - return self.__config.GetValue(section, name) - except Exception, e: - return default_value + mainloop = glib.MainLoop() - def register_list_engines(self): - return self.__ibus.RegisterListEngines() + def __disconnected_cb(*args): + print "Disconnected", args + mainloop.quit() - def register_reload_engines(self): - return self.__ibus.RegisterReloadEngines() + b = Bus() + b.connect("disconnected", __disconnected_cb) - def register_start_engine(self, lang, name): - return self.__ibus.RegisterStartEngine(lang, name) + print "unique_name =", b.get_name() - def register_restart_engine(self, lang, name): - return self.__ibus.RegisterRestartEngine(lang, name) + for i in b.list_factories(): + print i.name - def register_stop_engine(self, lang, name): - return self.__ibus.RegisterStopEngine(lang, name) + mainloop.run() + print "Exit" - def kill(self): - return self.__ibus.Kill() - def __dbus_message_cb(self, conn, message): - # name owner changed signal - if message.is_signal(dbus.BUS_DAEMON_IFACE, "NameOwnerChanged"): - args = message.get_args_list() - if args[0] == ibus.IBUS_CONFIG_NAME: - if args[2] != "": - self.__config = self.__dbusconn.get_object(args[2], ibus.IBUS_CONFIG_PATH) - else: - self.__config = None - self.emit("config-reloaded") - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - # commit string signal - elif message.is_signal(ibus.IBUS_IFACE, "CommitString"): - args = message.get_args_list() - ic, string = args[0:2] - self.emit("commit-string", ic, string.encode("utf-8")) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # preedit signals - elif message.is_signal(ibus.IBUS_IFACE, "UpdatePreedit"): - args = message.get_args_list() - ic, preedit, attrs, cursor_pos, visible = args[0:5] - attrs = ibus.attr_list_from_dbus_value(attrs) - self.emit("update-preedit", ic, preedit.encode("utf-8"), - attrs, cursor_pos, visible) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "ShowPreedit"): - args = message.get_args_list() - ic = args[0] - self.emit("show-preedit", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "HidePreedit"): - args = message.get_args_list() - ic = args[0] - self.emit("hide-preedit", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # aux string signals - elif message.is_signal(ibus.IBUS_IFACE, "UpdateAuxString"): - args = message.get_args_list() - ic, aux_string, attrs, visible = args[0:4] - attrs = ibus.attr_list_from_dbus_value(attrs) - self.emit("update-aux-string", ic, aux_string.encode("utf-8"), - attrs, visible) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "ShowAuxString"): - args = message.get_args_list() - ic = args[0] - self.emit("show-aux-string", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "HideAuxString"): - args = message.get_args_list() - ic = args[0] - self.emit("hide-aux-string", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # lookup table signals - elif message.is_signal(ibus.IBUS_IFACE, "UpdateLookupTable"): - args = message.get_args_list() - ic, lookup_table, visible = args[0:3] - lookup_table = ibus.lookup_table_from_dbus_value(lookup_table) - self.emit("update-lookup-table", ic, lookup_table, visible) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "ShowLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("show-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "HideLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("hide-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "PageUpLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("page-up-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "PageDownLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("page-down-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "CursorUpLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("cursor-up-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - elif message.is_signal(ibus.IBUS_IFACE, "CursorDownLookupTable"): - args = message.get_args_list() - ic = args[0] - self.emit("cursor-down-lookup-table", ic) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # Config signals - elif message.is_signal(ibus.IBUS_CONFIG_IFACE, "ValueChanged"): - args = message.get_args_list() - section, name, value = args[0:3] - self.emit("config-value-changed", section, name, value) - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - - # DBUS Disconnected signal - elif message.is_signal(dbus.LOCAL_IFACE, "Disconnected"): - self.destroy() - retval = dbus.lowlevel.HANDLER_RESULT_HANDLED - else: - retval = dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED - return retval +if __name__ == "__main__": + test() diff --git a/ibus/common.py b/ibus/common.py index 60323e4..e9868ee 100644 --- a/ibus/common.py +++ b/ibus/common.py @@ -21,14 +21,15 @@ __all__ = ( "IBUS_ADDR", - "IBUS_IFACE", - "IBUS_NAME", - "IBUS_PATH", - "IBUS_CONFIG_IFACE", - "IBUS_ENGINE_FACTORY_IFACE", - "IBUS_ENGINE_IFACE", - "IBUS_PANEL_IFACE", - "IBUS_NOTIFICATIONS_IFACE", + "IBUS_IFACE_IBUS", + "IBUS_SERVICE_IBUS", + "IBUS_PATH_IBUS", + "IBUS_IFACE_CONFIG", + "IBUS_IFACE_PANEL", + "IBUS_IFACE_ENGINE", + "IBUS_IFACE_ENGINE_FACTORY", + "IBUS_IFACE_INPUT_CONTEXT", + "IBUS_IFACE_NOTIFICATIONS", "default_reply_handler", "default_error_handler", "DEFAULT_ASYNC_HANDLERS", @@ -67,15 +68,16 @@ if not __username: IBUS_ADDR = "unix:path=/tmp/ibus-%s/ibus-%s" % (__username, display.replace(":", "-")) # IBUS_ADDR = "tcp:host=localhost,port=7799" -IBUS_IFACE = "org.freedesktop.IBus" -IBUS_PATH = "/org/freedesktop/IBus" -IBUS_NAME = "org.freedesktop.IBus" +IBUS_IFACE_IBUS = "org.freedesktop.IBus" +IBUS_PATH_IBUS = "/org/freedesktop/IBus" +IBUS_SERVICE_IBUS = "org.freedesktop.IBus" -IBUS_CONFIG_IFACE = "org.freedesktop.ibus.Config" -IBUS_ENGINE_FACTORY_IFACE = "org.freedesktop.ibus.EngineFactory" -IBUS_ENGINE_IFACE = "org.freedesktop.ibus.Engine" -IBUS_PANEL_IFACE = "org.freedesktop.ibus.Panel" -IBUS_NOTIFICATIONS_IFACE = "org.freedesktop.ibus.Notifications" +IBUS_IFACE_PANEL = "org.freedesktop.IBus.Panel" +IBUS_IFACE_CONFIG = "org.freedesktop.IBus.Config" +IBUS_IFACE_ENGINE = "org.freedesktop.IBus.Engine" +IBUS_IFACE_ENGINE_FACTORY = "org.freedesktop.IBus.EngineFactory" +IBUS_IFACE_INPUT_CONTEXT = "org.freedesktop.IBus.InputContext" +IBUS_IFACE_NOTIFICATIONS = "org.freedesktop.IBus.Notifications" def default_reply_handler( *args): pass diff --git a/ibus/component.py b/ibus/component.py new file mode 100644 index 0000000..afdc152 --- /dev/null +++ b/ibus/component.py @@ -0,0 +1,131 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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__ = ( + "Component", + ) + +import dbus +from exception import IBusException +from serializable import * +from enginedesc import * +from observedpath import * + +class Component(Serializable): + __NAME__ = "IBusComponent" + def __init__ (self, name="", description="", version="", license="", author="", homepage="", _exec="", textdomain=""): + super(Component, self).__init__() + self.__name = name + self.__description = description + self.__version = version + self.__license = license + self.__author = author + self.__homepage = homepage + self.__exec = _exec + self.__textdomain = textdomain + self.__observed_paths = [] + self.__engines = [] + + def get_name(self): + return self.__name + + def get_description(self): + return self.__description + + def get_version(self): + return self.__version + + def get_license(self): + return self.__license + + def get_author(self): + return self.__author + + def get_homepage(self): + return self.__homepage + + def get_exec(self): + return self.__exec + + def get_textdomain(self): + return self.__textdomain + + def get_observed_paths(self): + return self.__observed_paths[:] + + def get_engines(self): + return self.__engines[:] + + name = property(get_name) + description = property(get_description) + version = property(get_version) + license = property(get_license) + author = property(get_author) + homepage = property(get_homepage) + _exec = property(get_exec) + textdomain = property(get_textdomain) + observed_paths = property(get_observed_paths) + engines = property(get_engines) + + def add_observed_path(self, path): + self.__observed_paths.append(ObservedPath(path)) + + def add_engine(self, name="", longname="", description="", language="", license="", author="", icon="", layout=""): + engine = EngineDesc(name, longname, description, language, license, author, icon, layout) + self.__engines.append(engine) + + def serialize(self, struct): + super(Component, self).serialize(struct) + struct.append (dbus.String(self.__name)) + struct.append (dbus.String(self.__description)) + struct.append (dbus.String(self.__version)) + struct.append (dbus.String(self.__license)) + struct.append (dbus.String(self.__author)) + struct.append (dbus.String(self.__homepage)) + struct.append (dbus.String(self.__exec)) + struct.append (dbus.String(self.__textdomain)) + struct.append (dbus.Array(map(serialize_object,self.__observed_paths), signature="v")) + struct.append (dbus.Array(map(serialize_object,self.__engines), signature="v")) + + def deserialize(self, struct): + super(Component, self).deserialize(struct) + + self.__name = struct.pop(0) + self.__description = struct.pop(0) + self.__version = struct.pop(0) + self.__license = struct.pop(0) + self.__author = struct.pop(0) + self.__homepage = struct.pop(0) + self.__exec = struct.pop(0) + self.__textdomain = struct.pop(0) + + self.__observed_paths = map(deserialize_object, struct.pop(0)) + self.__engines = map(deserialize_object, struct.pop(0)) + +serializable_register(Component) + +def test(): + text = Component("Hello", "", "", "", "", "", "", "") + value = serialize_object(text) + text= deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/config.py b/ibus/config.py index 24b4edc..70bc89a 100644 --- a/ibus/config.py +++ b/ibus/config.py @@ -21,17 +21,20 @@ __all__ = ( "ConfigBase", - "IBUS_CONFIG_NAME", - "IBUS_CONFIG_PATH" + "IBUS_SERVICE_CONFIG", + "IBUS_PATH_CONFIG" ) -IBUS_CONFIG_NAME = "org.freedesktop.ibus.Config" -IBUS_CONFIG_PATH = "/org/freedesktop/ibus/Config" +IBUS_SERVICE_CONFIG = "org.freedesktop.IBus.Config" +IBUS_PATH_CONFIG = "/org/freedesktop/IBus/Config" -import ibus -from ibus import interface +import gobject +import object +import interface +import dbus +from dbus.proxies import ProxyObject -class ConfigBase(ibus.Object): +class ConfigBase(object.Object): def __init__(self, bus): super(ConfigBase, self).__init__() self.__proxy = ConfigProxy(self, bus.get_dbusconn()) @@ -48,7 +51,7 @@ class ConfigBase(ibus.Object): class ConfigProxy(interface.IConfig): def __init__ (self, config, dbusconn): - super(ConfigProxy, self).__init__(dbusconn, IBUS_CONFIG_PATH) + super(ConfigProxy, self).__init__(dbusconn, IBUS_PATH_CONFIG) self.__dbusconn = dbusconn self.__config = config @@ -60,3 +63,80 @@ class ConfigProxy(interface.IConfig): def Destroy(self): self.__config.destroy() + +class Config(object.Object): + __gsignals__ = { + "reloaded" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "value-changed" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + ), + } + + def __init__(self, bus): + super(Config, self).__init__() + self.__bus = bus + self.__bus_name = None + + self.__bus.add_match("type='signal',\ + sender='org.freedesktop.DBus',\ + member='NameOwnerChanged',\ + arg0='org.freedesktop.IBus.Config'") + self.__bus.get_dbusconn().add_signal_receiver(self.__name_owner_changed_cb, signal_name="NameOwnerChanged") + + try: + self.__init_config() + except: + self.__config = None + + def __name_owner_changed_cb(self, name, old_name, new_name): + if name == "org.freedesktop.IBus.Config": + if new_name == "": + self.__config = None + else: + self.__init_config(new_name) + + def __init_config(self, bus_name=None): + if bus_name == None: + bus_name = self.__bus.get_name_owner(IBUS_SERVICE_CONFIG) + + match_rule = "type='signal',\ + sender='%s',\ + member='ValueChanged',\ + path='/org/freedesktop/IBus/Config'" + + if self.__bus_name: + self.__bus.remove_match(match_rule % self.__bus_name) + self.__bus_name = None + + self.__config = self.__bus.get_dbusconn().get_object(bus_name, IBUS_PATH_CONFIG) + self.__config.connect_to_signal("ValueChanged", self.__value_changed_cb) + + self.__bus_name = bus_name + self.__bus.add_match(match_rule % self.__bus_name) + self.emit("reloaded") + + def __value_changed_cb(self, section, name, value): + self.emit("value-changed", section, name, value) + + def get_value(self, section, name, default_value): + try: + return self.__config.GetValue(section, name) + except: + return default_value + + def set_value(self, section, name, value): + try: + return self.__config.SetValue(section, name, value) + except: + return + + def set_list(self, section, name, value, signature): + return self.set_value(section, name, dbus.Array(value, signature=signature)) + +gobject.type_register(Config) diff --git a/ibus/engine.py b/ibus/engine.py index 9a6a332..d52c97e 100644 --- a/ibus/engine.py +++ b/ibus/engine.py @@ -23,15 +23,16 @@ __all__ = ( "EngineBase", ) -import ibus -from ibus import interface +import object +import serializable +import interface -class EngineBase(ibus.Object): +class EngineBase(object.Object): def __init__(self, bus, object_path): super(EngineBase, self).__init__() self.__proxy = EngineProxy (self, bus.get_dbusconn(), object_path) - def process_key_event(self, keyval, is_press, state): + def process_key_event(self, keyval, state): return False def focus_in(self): @@ -73,39 +74,37 @@ class EngineBase(ibus.Object): def property_hide(self, prop_name): pass - def commit_string(self, text): - return self.__proxy.CommitString(text) + def commit_text(self, text): + text = serializable.serialize_object(text) + return self.__proxy.CommitText(text) - def forward_key_event(self, keyval, is_press, state): - return self.__proxy.ForwardKeyEvent(keyval, is_press, state) + def forward_key_event(self, keyval, state): + return self.__proxy.ForwardKeyEvent(keyval, state) - def update_preedit(self, text, attrs, cursor_pos, visible): - if attrs == None: - attrs = ibus.AttrList() - return self.__proxy.UpdatePreedit(text, attrs.to_dbus_value(), cursor_pos, visible) + def update_preedit_text(self, text, cursor_pos, visible): + text = serializable.serialize_object(text) + return self.__proxy.UpdatePreeditText(text, cursor_pos, visible) - def show_preedit(self): - return self.__proxy.ShowPreedit() + def show_preedit_text(self): + return self.__proxy.ShowPreeditText() - def hide_preedit(self): - return self.__proxy.HidePreedit() + def hide_preedit_text(self): + return self.__proxy.HidePreeditText() - def update_aux_string(self, text, attrs, visible): - if attrs == None: - attrs = ibus.AttrList() - return self.__proxy.UpdateAuxString(text, attrs.to_dbus_value(), visible) + def update_auxiliary_text(self, text, visible): + text = serializable.serialize_object(text) + return self.__proxy.UpdateAuxiliaryText(text, visible) - def show_aux_string(self): - return self.__proxy.ShowAuxString() + def show_auxiliary_text(self): + return self.__proxy.ShowAuxiliaryText() - def hide_aux_string(self): - return self.__proxy.HideAuxString() + def hide_auxiliary_text(self): + return self.__proxy.HideAuxiliaryText() def update_lookup_table(self, lookup_table, visible, just_current_page = False): if just_current_page: - dbus_values = lookup_table.current_page_to_dbus_value() - else: - dbus_values = lookup_table.to_dbus_value() + lookup_table = lookup_table.get_current_page_as_lookup_table() + dbus_values = serializable.serialize_object(lookup_table) return self.__proxy.UpdateLookupTable(dbus_values, visible) def show_lookup_table(self): @@ -127,10 +126,12 @@ class EngineBase(ibus.Object): return self.__proxy.CursorDownLookupTable() def register_properties(self, props): - return self.__proxy.RegisterProperties(props.to_dbus_value()) + dbus_values = serializable.serialize_object(props) + return self.__proxy.RegisterProperties(dbus_values) def update_property(self, prop): - return self.__proxy.UpdateProperty(prop.to_dbus_value()) + dbus_values = serializable.serialize_object(prop) + return self.__proxy.UpdateProperty(dbus_values) def get_dbus_object(self): return self.__proxy @@ -145,8 +146,8 @@ class EngineProxy(interface.IEngine): super(EngineProxy, self).__init__(conn, object_path) self.__engine = engine - def ProcessKeyEvent(self, keyval, is_press, state): - return self.__engine.process_key_event(keyval, is_press, state) + def ProcessKeyEvent(self, keyval, state): + return self.__engine.process_key_event(keyval, state) def FocusIn(self): return self.__engine.focus_in() diff --git a/ibus/enginedesc.py b/ibus/enginedesc.py new file mode 100644 index 0000000..430072c --- /dev/null +++ b/ibus/enginedesc.py @@ -0,0 +1,106 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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__ = ( + "EngineDesc", + ) + +import dbus +from exception import IBusException +from serializable import * + +class EngineDesc(Serializable): + __NAME__ = "IBusEngineDesc" + def __init__ (self, name="", longname="", description="", language="", license="", author="", icon="", layout=""): + super(EngineDesc, self).__init__() + self.__name = name + self.__longname = longname + self.__description = description + self.__language = language + self.__license = license + self.__author = author + self.__icon = icon + self.__layout = layout + + def get_name(self): + return self.__name + + def get_longname(self): + return self.__longname + + def get_description(self): + return self.__description + + def get_language(self): + return self.__language + + def get_license(self): + return self.__license + + def get_author(self): + return self.__author + + def get_icon(self): + return self.__icon + + def get_layout(self): + return self.__layout + + name = property(get_name) + longname = property(get_longname) + description = property(get_description) + language = property(get_language) + license = property(get_license) + author = property(get_author) + icon = property(get_icon) + layout = property(get_layout) + + def serialize(self, struct): + super(EngineDesc, self).serialize(struct) + struct.append (dbus.String(self.__name)) + struct.append (dbus.String(self.__longname)) + struct.append (dbus.String(self.__description)) + struct.append (dbus.String(self.__language)) + struct.append (dbus.String(self.__license)) + struct.append (dbus.String(self.__author)) + struct.append (dbus.String(self.__icon)) + struct.append (dbus.String(self.__layout)) + + def deserialize(self, struct): + super(EngineDesc, self).deserialize(struct) + self.__name = struct.pop(0) + self.__longname = struct.pop(0) + self.__description = struct.pop(0) + self.__language = struct.pop(0) + self.__license = struct.pop(0) + self.__author = struct.pop(0) + self.__icon = struct.pop(0) + self.__layout = struct.pop(0) + +serializable_register(EngineDesc) + +def test(): + engine = EngineDesc("Hello", "", "", "", "", "", "", "") + value = serialize_object(engine) + engine = deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/factory.py b/ibus/factory.py index 18deebf..82751ba 100644 --- a/ibus/factory.py +++ b/ibus/factory.py @@ -21,24 +21,19 @@ __all__ = ( "EngineFactoryBase", + "FactoryInfo" ) - -import ibus -from ibus import interface - -class EngineFactoryBase(ibus.Object): - def __init__(self, info, engine_class, engine_path, bus, object_path): +import dbus +import object +import interface +from serializable import * +from exception import * + +class EngineFactoryBase(object.Object): + def __init__(self, bus): super(EngineFactoryBase, self).__init__() - self.__proxy = EngineFactoryProxy (self, bus.get_dbusconn(), object_path) - self.__info = info + self.__proxy = EngineFactoryProxy (self, bus.get_dbusconn(), "/org/freedesktop/IBus/Factory") self.__bus = bus - self.__engine_class = engine_class - self.__engine_path = engine_path - self.__engine_id = 1 - self.__object_path = object_path - - def get_info(self): - return self.__info def initialize(self): pass @@ -46,21 +41,13 @@ class EngineFactoryBase(ibus.Object): def uninitialize(self): pass - def register(self): - self.__bus.register_factories([self.__object_path]) - - def create_engine(self): - engine = self.__engine_class(self.__bus, self.__engine_path + str(self.__engine_id)) - self.__engine_id += 1 - return engine.get_dbus_object() + def create_engine(self, engine_name): + raise IBusException("Can not create engine %s" % engine_name) def do_destroy(self): self.__proxy = None self.__bus = None - self.__info = None - self.__engine_class = None - self.__engine_path = None - super(EngineFactoryBase,self).do_destroy() + super(EngineFactoryBase, self).do_destroy() class EngineFactoryProxy(interface.IEngineFactory): @@ -77,11 +64,70 @@ class EngineFactoryProxy(interface.IEngineFactory): def Uninitialize(self): return self.__factory.uninitialize() - def CreateEngine(self): - return self.__factory.create_engine() + def CreateEngine(self, engine_name): + engine = self.__factory.create_engine(engine_name) + return engine.get_dbus_object() def Destroy(self): self.__factory.destroy() self.__factory = None self.remove_from_connection () +class FactoryInfo(Serializable): + __NAME__ = "IBusFactoryInfo" + def __init__ (self, path=None, name=None, lang=None, icon=None, authors=None, credits=None): + super(FactoryInfo, self).__init__() + self.__path = path + self.__name = name + self.__lang = lang + self.__icon = icon + self.__authors = authors + self.__credits = credits + + def get_path(self): + return self.__path + + def get_name(self): + return self.__name + + def get_lang(self): + return self.__lang + + def get_icon(self): + return self.__icon + def get_authors(self): + return self.__authors + + def get_credits(self): + return self.__credits + + path = property(get_path) + name = property(get_name) + lang = property(get_lang) + icon = property(get_icon) + authors = property(get_authors) + credits = property(get_credits) + + def serialize(self, struct): + super(FactoryInfo, self).serialize(struct) + struct.append (dbus.ObjectPath(self.__path)) + struct.append (dbus.String(self.__name)) + struct.append (dbus.String(self.__lang)) + struct.append (dbus.String(self.__icon)) + struct.append (dbus.String(self.__authors)) + struct.append (dbus.String(self.__credits)) + + def deserialize(self, struct): + super(FactoryInfo, self).deserialize(struct) + if len(struct) < 5: + raise IBusException ("Can not deserialize IBusFactoryInfo") + + self.__path = struct.pop(0) + self.__name = struct.pop(0) + self.__lang = struct.pop(0) + self.__icon = struct.pop(0) + self.__authors = struct.pop(0) + self.__credits = struct.pop(0) + +serializable_register(FactoryInfo) + diff --git a/ibus/inputcontext.py b/ibus/inputcontext.py new file mode 100644 index 0000000..10233da --- /dev/null +++ b/ibus/inputcontext.py @@ -0,0 +1,301 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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__ = ( + "InputContext", + ) + +import sys +import gobject +import dbus +import dbus.lowlevel +import object +import common +import serializable + +class InputContext(object.Object): + __gsignals__ = { + "commit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, ) + ), + "update-preedit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, gobject.TYPE_UINT, gobject.TYPE_BOOLEAN) + ), + "show-preedit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "hide-preedit-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "update-auxiliary-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) + ), + "show-auxiliary-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "hide-auxiliary-text" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "update-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN) + ), + "show-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "hide-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "page-up-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "page-down-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "cursor-up-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "cursor-down-lookup-table" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "enabled" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + "disabled" : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + () + ), + } + + def __init__(self, bus, path): + super(InputContext, self).__init__() + + self.__bus = bus + self.__context = bus.get_dbusconn().get_object(common.IBUS_SERVICE_IBUS, path) + self.__signal_matches = [] + + m = self.__context.connect_to_signal("CommitText", self.__commit_text_cb) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("UpdatePreeditText", self.__update_preedit_text_cb) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("UpdateAuxiliaryText", self.__update_auxiliary_text_cb) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("UpdateLookupTable", self.__update_lookup_table_cb) + self.__signal_matches.append(m) + + m = self.__context.connect_to_signal("Enabled", lambda *args: self.emit("enabled")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("Disabled", lambda *args: self.emit("disabled")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("ShowPreeditText", lambda *args: self.emit("show-preedit-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("HidePreeditText", lambda *args: self.emit("hide-preedit-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("ShowAuxiliaryText", lambda *args: self.emit("show-auxiliary-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("HideAuxiliaryText", lambda *args: self.emit("hide-auxiliary-text")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("ShowLookupTable", lambda *args: self.emit("show-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("HideLookupTable", lambda *argss: self.emit("hide-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("PageUpLookupTable", lambda *args: self.emit("page-up-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("PageDownLookupTable", lambda *args: self.emit("page-down-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("CursorUpLookupTable", lambda *args: self.emit("cursor-up-lookup-table")) + self.__signal_matches.append(m) + m = self.__context.connect_to_signal("CursorDownLookupTable", lambda *args: self.emit("cursor-down-lookup-table")) + self.__signal_matches.append(m) + + def __commit_text_cb(self, *args): + text = serializable.deserialize_object(args[0]) + self.emit("commit-text", text) + + def __update_preedit_text_cb(self, *args): + text = serializable.deserialize_object(args[0]) + cursor_pos = args[1] + visible = args[2] + self.emit("update-preedit-text", text, cursor_pos, visible) + + def __update_auxiliary_text_cb(self, *args): + text = serializable.deserialize_object(args[0]) + visible = args[1] + self.emit("update-auxiliray-text", text, visible) + + def __update_lookup_table_cb(self, *args): + table = serializable.deserialize_object(args[0]) + visible = args[1] + self.emit("update-lookup-table", table, visible) + + def process_key_event(self, keyval, modifiers): + keyval = dbus.UInt32(keyval) + modifiers = dbus.UInt32(modifiers) + return self.__context.ProcessKeyEvent(keyval, modifiers) + + def set_cursor_location(self, x, y, w, h): + x = dbus.Int32(x) + y = dbus.Int32(y) + w = dbus.Int32(w) + h = dbus.Int32(h) + return self.__context.SetCursorLocation(x, y, w, h) + + def focus_in(self): + return self.__context.FocusIn() + + def focus_out(self): + return self.__context.FocusOut() + + def reset(self): + return self.__context.Reset() + + def is_enabled(self): + return self.__context.IsEnabled() + + def set_capabilities(self, caps): + caps = dbus.UInt32(caps) + return self.__context.SetCapabilities(caps) + + def destroy(self): + self.__context.Destroy() + super(InputContext, self).destroy() + + def get_engine(self): + try: + engine = self.__context.GetEngine() + engine = serializable.deserialize_object(engine) + return engine + except: + return None + + def set_engine(self, engine): + return self.__context.SetEngine(engine.name) + + +def test(): + import gtk + import gtk.gdk + from bus import Bus + import modifier + import text + import attribute + import property + import lookuptable + import factory + + class TestWindow(gtk.Window): + def __init__(self): + super(TestWindow,self).__init__() + + self.__bus = Bus() + print self.__bus.get_name() + self.__bus.connect("disconnected", gtk.main_quit) + context_path = self.__bus.create_input_context("Test") + print context_path + self.__context = InputContext(self.__bus, context_path) + self.__context.set_capabilities (9) + + self.__context.connect("commit-text", self.__commit_text_cb) + self.__context.connect("update-preedit-text", self.__update_preedit_text_cb) + self.__context.connect("show-preedit-text", self.__show_preedit_text_cb) + self.__context.connect("update-auxiliary-text", self.__update_auxiliary_text_cb) + self.__context.connect("update-lookup-table", self.__update_lookup_table_cb) + self.__context.connect("enabled", self.__enabled_cb) + self.__context.connect("disabled", self.__disabled_cb) + + self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK | gtk.gdk.FOCUS_CHANGE_MASK) + + self.connect("key-press-event", self.__key_press_event_cb) + self.connect("key-release-event", self.__key_release_event_cb) + self.connect("delete-event", gtk.main_quit) + self.connect("focus-in-event", lambda *args: self.__context.focus_in()) + self.connect("focus-out-event", lambda *args: self.__context.focus_out()) + + self.show_all() + + def __commit_text_cb(self, context, text): + print "commit-text:", text.text + + def __update_preedit_text_cb(self, context, text, cursor_pos, visible): + print "preedit-text:", text.text, cursor_pos, visible + + def __show_preedit_text_cb(self, context): + print "show-preedit-text" + + def __hide_preedit_text_cb(self, context): + print "hide-preedit-text" + + def __update_auxiliary_text_cb(self, context, text, visible): + print "auxiliary-text:", text.text, visible + + def __update_lookup_table_cb(self, context, table, visible): + print "update-lookup-table:", visible + + def __enabled_cb(self, context): + print "enabled" + info = context.get_factory_info() + print "factory = %s" % info.name + + def __disabled_cb(self, context): + print "disabled" + + def __key_press_event_cb(self, widget, event): + self.__context.process_key_event(event.keyval, event.state) + + def __key_release_event_cb(self, widget, event): + self.__context.process_key_event(event.keyval, event.state | modifier.RELEASE_MASK) + + w = TestWindow() + gtk.main() + +if __name__ == "__main__": + test() + diff --git a/ibus/interface/Makefile.am b/ibus/interface/Makefile.am index 0e1f8b9..ffc019c 100644 --- a/ibus/interface/Makefile.am +++ b/ibus/interface/Makefile.am @@ -24,6 +24,7 @@ ibus_interface_PYTHON = \ ienginefactory.py \ iengine.py \ iibus.py \ + iinputcontext.py \ ipanel.py \ inotifications.py \ __init__.py \ diff --git a/ibus/interface/__init__.py b/ibus/interface/__init__.py index 5348395..90af265 100644 --- a/ibus/interface/__init__.py +++ b/ibus/interface/__init__.py @@ -20,6 +20,7 @@ # Boston, MA 02111-1307 USA from iibus import * +from iinputcontext import * from iengine import * from ienginefactory import * from ipanel import * diff --git a/ibus/interface/iconfig.py b/ibus/interface/iconfig.py index 171d17a..23954fa 100644 --- a/ibus/interface/iconfig.py +++ b/ibus/interface/iconfig.py @@ -23,22 +23,22 @@ __all__ = ("IConfig", ) import dbus.service from ibus.common import \ - IBUS_CONFIG_IFACE + IBUS_IFACE_CONFIG class IConfig(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_CONFIG_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_CONFIG, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface=IBUS_CONFIG_IFACE, \ + dbus.service.signal(dbus_interface=IBUS_IFACE_CONFIG, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_CONFIG_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_CONFIG, \ async_callbacks=("reply_cb", "error_cb"), \ **args) diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py index dfe285a..32ba998 100644 --- a/ibus/interface/iengine.py +++ b/ibus/interface/iengine.py @@ -23,27 +23,27 @@ __all__ = ("IEngine", ) import dbus.service from ibus.common import \ - IBUS_ENGINE_IFACE + IBUS_IFACE_ENGINE class IEngine(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface=IBUS_ENGINE_IFACE, \ + dbus.service.signal(dbus_interface=IBUS_IFACE_ENGINE, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE, \ async_callbacks=("reply_cb", "error_cb"), \ **args) - @method(in_signature="ubu", out_signature="b") - def ProcessKeyEvent(self, keyval, is_press, state): + @method(in_signature="uu", out_signature="b") + def ProcessKeyEvent(self, keyval, state): pass @method(in_signature="iiii") @@ -89,29 +89,30 @@ class IEngine(dbus.service.Object): @method() def Destroy(self): pass - @signal(signature="s") - def CommitString(self, text): pass + + @signal(signature="v") + def CommitText(self, text): pass @signal(signature="ubu") def ForwardKeyEvent(self, keyval, is_press, state): pass - @signal(signature="sa(uuuu)ib") - def UpdatePreedit(self, text, attrs, cursor_pos, visible): pass + @signal(signature="vub") + def UpdatePreeditText(self, text, cursor_pos, visible): pass @signal() - def ShowPreedit(self): pass + def ShowPreeditText(self): pass @signal() - def HidePreedit(self): pass + def HidePreeditText(self): pass - @signal(signature="sa(uuuu)b") - def UpdateAuxString(self, text, attrs, visible): pass + @signal(signature="vb") + def UpdateAuxiliaryText(self, text, visible): pass @signal() - def ShowAuxString(self): pass + def ShowAuxiliaryText(self): pass @signal() - def HideAuxString(self): pass + def HideAuxiliaryText(self): pass @signal(signature="vb") def UpdateLookupTable(self, lookup_table, visible): pass diff --git a/ibus/interface/ienginefactory.py b/ibus/interface/ienginefactory.py index 5670e81..5e93fd8 100644 --- a/ibus/interface/ienginefactory.py +++ b/ibus/interface/ienginefactory.py @@ -23,17 +23,17 @@ __all__ = ("IEngineFactory", ) import dbus.service from ibus.common import \ - IBUS_ENGINE_FACTORY_IFACE + IBUS_IFACE_ENGINE_FACTORY class IEngineFactory(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_FACTORY_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE_FACTORY, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_ENGINE_FACTORY_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_ENGINE_FACTORY, \ async_callbacks=("reply_cb", "error_cb"), \ **args) @@ -51,8 +51,8 @@ class IEngineFactory(dbus.service.Object): # Create an input context and return the id of the context. # If failed, it will return "" or None. - @method(out_signature="o") - def CreateEngine(self): pass + @method(in_signature="s", out_signature="o") + def CreateEngine(self, engine_name): pass # Destroy the engine @method() diff --git a/ibus/interface/iibus.py b/ibus/interface/iibus.py index cc5c351..848f798 100644 --- a/ibus/interface/iibus.py +++ b/ibus/interface/iibus.py @@ -23,100 +23,49 @@ __all__ = ("IIBus", ) import dbus.service from ibus.common import \ - IBUS_IFACE + IBUS_IFACE_IBUS class IIBus(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_IBUS, \ connection_keyword="dbusconn", \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_IBUS, \ connection_keyword="dbusconn", \ async_callbacks=("reply_cb", "error_cb"), \ **args) @method(out_signature="s") - def GetIBusAddress(self, dbusconn): pass + def GetAddress(self, dbusconn): pass # methods for ibus clients - @method(in_signature="s", out_signature="s") + @method(in_signature="s", out_signature="o") def CreateInputContext(self, client_name, dbusconn): pass - @method(in_signature="s") - def ReleaseInputContext(self, ic, dbusconn): pass - - @async_method(in_signature="subu", out_signature="b") - def ProcessKeyEvent(self, ic, keyval, is_press, state, dbusconn, reply_cb, error_cb): pass - - @method(in_signature="siiii") - def SetCursorLocation(self, ic, x, y, w, h, dbusconn): pass - - @method(in_signature="s") - def FocusIn(self, ic, dbusconn): pass - - @method(in_signature="s") - def FocusOut(self, ic, dbusconn): pass - - @method(in_signature="s") - def Reset(self, ic, dbusconn): pass - - @method(in_signature="s", out_signature="b") - def IsEnabled(self, ic, dbusconn): pass - - @method(in_signature="si") - def SetCapabilities(self, ic, caps, dbusconn): pass + @method(in_signature="s", out_signature="sb") + def GetInputContextStates(self, ic, dbusconn): pass # methods for ibus engine provide - @method(in_signature="ao") + @method(in_signature="av") def RegisterFactories(self, object_paths, dbusconn): pass - @method(in_signature="ao") + @method(in_signature="av") def UnregisterFactories(self, object_paths, dbusconn): pass # general methods - @method(out_signature="av") - def GetFactories(self, dbusconn): pass + @method(in_signature="av") + def RegisterComponent(self, components, dbusconn): pass - @method(in_signature="o", out_signature="av") - def GetFactoryInfo(self, factory_path, dbusconn): pass - - @method(in_signature="o") - def SetFactory(self, factory_path, dbusconn): pass - - @method(in_signature="s", out_signature="sb") - def GetInputContextStates(self, ic, dbusconn): pass - - @method(out_signature="a(sssssssb)") - def RegisterListEngines(self, dbusconn): pass - - @method() - def RegisterReloadEngines(self, dbusconn): pass - - @method(in_signature="ss") - def RegisterStartEngine(self, lang, name, dbusconn): pass - - @method(in_signature="ss") - def RegisterRestartEngine(self, lang, name, dbusconn): pass + @method(out_signature="av") + def ListEngines(self, dbusconn): pass - @method(in_signature="ss") - def RegisterStopEngine(self, lang, name, dbusconn): pass + @method(out_signature="av") + def ListActiveEngines(self, dbusconn): pass @async_method() def Kill(self, dbusconn, reply_cb, error_cb): pass - #sigals - def CommitString(self, ic, text): pass - - def UpdatePreedit(self, ic, text, attrs, cursor_pos, show): pass - - def Enabled(self, ic): pass - - def Disabled(self, ic): pass - - def ConfigValueChanged(self, key, value): pass - - def ConfigReload(self): pass diff --git a/ibus/interface/iinputcontext.py b/ibus/interface/iinputcontext.py new file mode 100644 index 0000000..e5cf129 --- /dev/null +++ b/ibus/interface/iinputcontext.py @@ -0,0 +1,133 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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__ = ("IInputContext", ) + +import dbus.service +from ibus.common import \ + IBUS_IFACE_INPUT_CONTEXT + +class IInputContext(dbus.service.Object): + # define method decorator. + method = lambda **args: \ + dbus.service.method(dbus_interface=IBUS_IFACE_INPUT_CONTEXT, \ + **args) + + # define async method decorator. + async_method = lambda **args: \ + dbus.service.method(dbus_interface=IBUS_IFACE_INPUT_CONTEXT, \ + async_callbacks=("reply_cb", "error_cb"), \ + **args) + + # define signal decorator. + signal = lambda **args: \ + dbus.service.signal(dbus_interface=IBUS_IFACE_INPUT_CONTEXT, \ + **args) + + @async_method(in_signature="uu", out_signature="b") + def ProcessKeyEvent(self, keyval, state, reply_cb, error_cb): pass + + @method(in_signature="iiii") + def SetCursorLocation(self, x, y, w, h): pass + + @method() + def FocusIn(self): pass + + @method() + def FocusOut(self): pass + + @method() + def Reset(self): pass + + @method(out_signature="b") + def IsEnabled(self): pass + + @method(in_signature="u") + def SetCapabilities(self, caps): pass + + @method(out_signature="v") + def GetEngineDesc(self): pass + + @method(in_signature="s") + def SetEngine(self, engine_name): pass + + @method() + def Destroy(self): pass + + #sigals + @signal(signature="v") + def CommitText(self, text): pass + + @signal() + def Enabled(self): pass + + @signal() + def Disabled(self): pass + + @signal(signature="uu") + def ForwardKeyEvent(self, keyval, state): pass + + @signal(signature="vub") + def UpdatePreeditText(self, text, cursor_pos, visible): pass + + @signal() + def ShowPreeditText(self): pass + + @signal() + def HidePreeditText(self): pass + + @signal(signature="vb") + def UpdateAuxiliaryText(self, text, visible): pass + + @signal() + def ShowAuxiliaryText(self): pass + + @signal() + def HideAuxiliaryText(self): pass + + @signal(signature="vb") + def UpdateLookupTable(self, lookup_table, visible): pass + + @signal() + def ShowLookupTable(self): pass + + @signal() + def HideLookupTable(self): pass + + @signal() + def PageUpLookupTable(self): pass + + @signal() + def PageDownLookupTable(self): pass + + @signal() + def CursorUpLookupTable(self): pass + + @signal() + def CursorDownLookupTable(self): pass + + @signal(signature="v") + def RegisterProperties(self, props): pass + + @signal(signature="v") + def UpdateProperty(self, prop): pass + + diff --git a/ibus/interface/inotifications.py b/ibus/interface/inotifications.py index 7d667f2..74d4dcf 100644 --- a/ibus/interface/inotifications.py +++ b/ibus/interface/inotifications.py @@ -23,22 +23,22 @@ __all__ = ("INotifications", ) import dbus.service from ibus.common import \ - IBUS_NOTIFICATIONS_IFACE + IBUS_IFACE_NOTIFICATIONS class INotifications(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface = IBUS_NOTIFICATIONS_IFACE, \ + dbus.service.method(dbus_interface = IBUS_IFACE_NOTIFICATIONS, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface = IBUS_NOTIFICATIONS_IFACE, \ + dbus.service.signal(dbus_interface = IBUS_IFACE_NOTIFICATIONS, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface = IBUS_NOTIFICATIONS_IFACE, \ + dbus.service.method(dbus_interface = IBUS_IFACE_NOTIFICATIONS, \ async_callbacks = ("reply_cb", "error_cb"), \ **args) diff --git a/ibus/interface/ipanel.py b/ibus/interface/ipanel.py index 83d6585..e5d174c 100644 --- a/ibus/interface/ipanel.py +++ b/ibus/interface/ipanel.py @@ -23,44 +23,44 @@ __all__ = ("IPanel", ) import dbus.service from ibus.common import \ - IBUS_PANEL_IFACE + IBUS_IFACE_PANEL class IPanel(dbus.service.Object): # define method decorator. method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_PANEL_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_PANEL, \ **args) # define signal decorator. signal = lambda **args: \ - dbus.service.signal(dbus_interface=IBUS_PANEL_IFACE, \ + dbus.service.signal(dbus_interface=IBUS_IFACE_PANEL, \ **args) # define async method decorator. async_method = lambda **args: \ - dbus.service.method(dbus_interface=IBUS_PANE_IFACE, \ + dbus.service.method(dbus_interface=IBUS_IFACE_PANEL, \ async_callbacks=("reply_cb", "error_cb"), \ **args) @method(in_signature="iiii") def SetCursorLocation(self, x, y, w, h): pass - @method(in_signature="svub") - def UpdatePreedit(self, text, attrs, cursor_pos, visible): pass + @method(in_signature="vub") + def UpdatePreeditText(self, text, cursor_pos, visible): pass @method() - def ShowPreedit(self): pass + def ShowPreeditText(self): pass @method() - def HidePreedit(self): pass + def HidePreeditText(self): pass - @method(in_signature="svb") - def UpdateAuxString(self, text, attrs, visible): pass + @method(in_signature="vb") + def UpdateAuxiliaryText(self, text, visible): pass @method() - def ShowAuxString(self): pass + def ShowAuxiliaryText(self): pass @method() - def HideAuxString(self): pass + def HideAuxiliaryText(self): pass @method(in_signature="vb") def UpdateLookupTable(self, lookup_table, visible): pass @@ -95,14 +95,14 @@ class IPanel(dbus.service.Object): @method() def HideLanguageBar(self): pass - @method(in_signature="s") + @method(in_signature="o") def FocusIn(self, ic): pass - @method(in_signature="s") + @method(in_signature="o") def FocusOut(self, ic): pass @method() - def StatesChanged(self): pass + def StateChanged(self): pass @method() def Reset(self): pass @@ -126,12 +126,12 @@ class IPanel(dbus.service.Object): @signal() def CursorDown(self): pass - @signal() + @signal(signature="si") def PropertyActivate(self, prop_name, prop_state): pass - @signal() + @signal(signature="s") def PropertyShow(self, prop_name): pass - @signal() + @signal(signature="s") def PropertyHide(self, prop_name): pass diff --git a/ibus/lookuptable.py b/ibus/lookuptable.py index 27819ce..bedd8bf 100644 --- a/ibus/lookuptable.py +++ b/ibus/lookuptable.py @@ -21,54 +21,24 @@ __all__ = ( "LookupTable", - "lookup_table_from_dbus_value" ) import dbus -from attribute import * +from serializable import * from exception import * -class CandidateList(list): - def __init__(self, items = []): - super(CandidateList, self).__init__(items) - - def clean(self): - del self[:] - def __getslice__(self, i, j): - items = super(CandidateList, self).__getslice__(i, j) - return CandidateList(items) - - def to_dbus_value(self): - value = dbus.Array([], signature="v") - for text, attrs in self: - value.append(dbus.Struct((dbus.String(text), attrs.to_dbus_value()))) - return value - - def from_dbus_value(self, value): - candidates = [] - if not isinstance(value, dbus.Array): - raise dbus.Exception("Candidates must from dbus.Array(a(sa(...))") - for candidate in value: - if not isinstance(candidate, dbus.Struct): - raise IBusException("Candidates must from dbus.Array(a(sa(...)))") - if len(candidate) != 2 or \ - not isinstance(candidate[0], dbus.String): - raise IBusException("Candidates must from dbus.Array(a(sa(...)))") - text = candidate[0] - attrs = attr_list_from_dbus_value(candidate[1]) - candidates.append((text, attrs)) - - self.clean() - self[:] = candidates - -class LookupTable(object): - def __init__(self, page_size=5, labels=None): +class LookupTable(Serializable): + __NAME__ = "IBusLookupTable" + def __init__(self, page_size=5, cursor_pos=0, coursor_visible=True, candidates=None): super(LookupTable, self).__init__() self.__cursor_visible = True - self.__cursor_pos = 0 - self.__candidates = CandidateList() + self.__cursor_pos = cursor_pos + if candidates == None: + self.__candidates = list() + else: + self.__candidates = candidates self.set_page_size(page_size) - self.set_labels(labels) + self.set_labels(None) def set_page_size(self, page_size): self.__page_size = page_size @@ -159,18 +129,16 @@ class LookupTable(object): return True def clean(self): - self.__candidates.clean() + self.__candidates = list() self.__cursor_pos = 0 - def append_candidate(self, candidate, attrs = None): - if attrs == None: - attrs = AttrList() - self.__candidates.append((candidate, attrs)) + def append_candidate(self, text): + self.__candidates.append(text) def get_candidate(self, index): return self.__candidates[index] - def get_canidates_in_current_page(self): + def get_candidates_in_current_page(self): page = self.__cursor_pos / self.__page_size start_index = page * self.__page_size end_index = min((page + 1) * self.__page_size, len(self.__candidates)) @@ -185,50 +153,43 @@ class LookupTable(object): def __len__(self): return self.get_number_of_candidates() - def to_dbus_value(self): - value = (dbus.Int32(self.__page_size), - dbus.Int32(self.__cursor_pos), - dbus.Boolean(self.__cursor_visible), - self.__candidates.to_dbus_value()) - return dbus.Struct(value) - - def current_page_to_dbus_value(self): - candidates = self.get_canidates_in_current_page() - value = (dbus.Int32(self.__page_size), - dbus.Int32(self.__cursor_pos % self.__page_size), - dbus.Boolean(self.__cursor_visible), - candidates.to_dbus_value()) - return dbus.Struct(value) - - def from_dbus_value(self, value): - if not isinstance(value, dbus.Struct): - raise dbus.Exception("LookupTable must from dbus.Struct(uuba(...))") - - if len(value) != 4 or \ - not isinstance(value[0], dbus.Int32) or \ - not isinstance(value[1], dbus.Int32) or \ - not isinstance(value[2], dbus.Boolean): - raise dbus.Exception("LookupTable must from dbus.Struct(uuba(...))") - - self.__candidates.from_dbus_value(value[3]) - self.__page_size = value[0] - self.__cursor_pos = value[1] - self.__cursor_visible = value[2] - -def lookup_table_from_dbus_value(value): - lookup_table = LookupTable() - lookup_table.from_dbus_value(value) - return lookup_table - -def unit_test(): + def serialize(self, struct): + super(LookupTable, self).serialize(struct) + struct.append(dbus.UInt32(self.__page_size)) + struct.append(dbus.UInt32(self.__cursor_pos)) + struct.append(dbus.Boolean(self.__cursor_visible)) + candidates = map(lambda c: serialize_object(c), self.__candidates) + struct.append(dbus.Array(candidates, signature="v")) + + def get_current_page_as_lookup_table(self): + candidates = self.get_candidates_in_current_page() + return LookupTable(self.__page_size, + self.__cursor_pos % self.__page_size, + self.__cursor_visible, + candidates) + + def deserialize(self, struct): + super(LookupTable, self).deserialize(struct) + + self.__page_size = struct.pop(0) + self.__cursor_pos = struct.pop(0) + self.__cursor_visible = struct.pop(0) + self.__candidates = map(deserialize_object, struct.pop(0)) + + +serializable_register(LookupTable) + +def test(): t = LookupTable() # attrs = AttrList() # attrs.append(AttributeBackground(RGB(233, 0,1), 0, 3)) # attrs.append(AttributeUnderline(1, 3, 5)) t.append_candidate("Hello") - value = t.to_dbus_value() - print value - t = lookup_table_from_dbus_value(value) + value = serialize_object(t) + t = deserialize_object(value) + t = t.get_current_page_as_lookup_table() + value = serialize_object(t) + t = deserialize_object(value) if __name__ == "__main__": - unit_test() + test() diff --git a/ibus/notifications.py b/ibus/notifications.py index 3ae067a..0509548 100644 --- a/ibus/notifications.py +++ b/ibus/notifications.py @@ -21,12 +21,12 @@ __all__ = ( "NotificationsBase", - "IBUS_NOTIFICATIONS_NAME", - "IBUS_NOTIFICATIONS_PATH" + "IBUS_SERVICE_NOTIFICATIONS", + "IBUS_PATH_NOTIFICATIONS" ) -IBUS_NOTIFICATIONS_NAME = "org.freedesktop.ibus.Notifications" -IBUS_NOTIFICATIONS_PATH = "/org/freedesktop/ibus/Notifications" +IBUS_SERVICE_NOTIFICATIONS = "org.freedesktop.IBus.Notifications" +IBUS_PATH_NOTIFICATIONS = "/org/freedesktop/IBus/Notifications" import ibus from ibus import interface @@ -50,7 +50,7 @@ class NotificationsBase(ibus.Object): class NotificationsProxy(interface.INotifications): def __init__ (self, notify, dbusconn): - super(NotificationsProxy, self).__init__(dbusconn, IBUS_NOTIFICATIONS_PATH) + super(NotificationsProxy, self).__init__(dbusconn, IBUS_PATH_NOTIFICATIONS) self.__dbusconn = dbusconn self.__notify = notify diff --git a/ibus/object.py b/ibus/object.py index ca2b380..b00e47a 100644 --- a/ibus/object.py +++ b/ibus/object.py @@ -28,21 +28,30 @@ import gobject class Object(gobject.GObject): __gsignals__ = { 'destroy' : ( - gobject.SIGNAL_RUN_FIRST, + gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } def __init__(self): super(Object, self).__init__() - self._destroyed = False + self.__destroyed = False + self.__handlers = [] def destroy(self): - if not self._destroyed: + if not self.__destroyed: self.emit("destroy") - self._destroyed = True + self.__destroyed = True def do_destroy(self): - pass + self.__disconnect_all() + + def connect(self, signal_name, handler, *args): + id = super(Object, self).connect(signal_name, handler, *args) + self.__handlers.append(id) + + def __disconnect_all(self): + map(self.disconnect, self.__handlers) + self.__handlers = [] gobject.type_register(Object) diff --git a/ibus/observedpath.py b/ibus/observedpath.py new file mode 100644 index 0000000..94b3e7e --- /dev/null +++ b/ibus/observedpath.py @@ -0,0 +1,64 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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__ = ( + "ObservedPath", + ) + +import dbus +from exception import IBusException +from serializable import * + +class ObservedPath(Serializable): + __NAME__ = "IBusObservedPath" + def __init__ (self, path="", mtime=0): + super(ObservedPath, self).__init__() + self.__path = path + self.__mtime = mtime + + def get_path(self): + return self.__path + + def get_mtime(self): + return self.__mtime + + path = property(get_path) + mtime = property(get_mtime) + + def serialize(self, struct): + super(ObservedPath, self).serialize(struct) + struct.append (dbus.String(self.__path)) + struct.append (dbus.Int64(self.__mtime)) + + def deserialize(self, struct): + super(ObservedPath, self).deserialize(struct) + self.__path = struct.pop(0) + self.__mtime = struct.pop(0) + +serializable_register(ObservedPath) + +def test(): + op = ObservedPath("/tmp", 111) + value = serialize_object(op) + op= deserialize_object(value) + +if __name__ == "__main__": + test() diff --git a/ibus/panel.py b/ibus/panel.py index 74b220d..9a34109 100644 --- a/ibus/panel.py +++ b/ibus/panel.py @@ -25,15 +25,17 @@ __all__ = ( "PanelButton", "PanelToggleButton", "PanelMenu", - "IBUS_PANEL_NAME", - "IBUS_PANEL_PATH" + "IBUS_SERVICE_PANEL", + "IBUS_PATH_PANEL" ) -IBUS_PANEL_NAME = "org.freedesktop.ibus.Panel" -IBUS_PANEL_PATH = "/org/freedesktop/ibus/Panel" +IBUS_SERVICE_PANEL = "org.freedesktop.IBus.Panel" +IBUS_PATH_PANEL = "/org/freedesktop/IBus/Panel" -import ibus -from ibus import interface +from serializable import * +from object import Object +import interface +import dbus class PanelItem: pass @@ -47,30 +49,31 @@ class PanelToggleButton(PanelButton): class PanelMenu(PanelItem): pass -class PanelBase(ibus.Object): +class PanelBase(Object): def __init__(self, bus): super(PanelBase, self).__init__() - self.__proxy = PanelProxy(self, bus.get_dbusconn()) + self.__bus = bus + self.__proxy = PanelProxy(self, bus) def set_cursor_location(self, x, y, w, h): pass - def update_preedit(self, text, attrs, cursor_pos, visible): + def update_preedit_text(self, text, cursor_pos, visible): pass - def show_preedit(self): + def show_preedit_text(self): pass - def hide_preedit(self): + def hide_preedit_text(self): pass - def update_aux_string(self, text, attrs, visible): + def update_auxiliary_text(self, text, visible): pass - def show_aux_string(self): + def show_auxiliary_text(self): pass - def hide_aux_string(self): + def hide_auxiliary_text(self): pass def update_lookup_table(self, lookup_table, visible): @@ -118,7 +121,7 @@ class PanelBase(ibus.Object): def focus_out(self, ic): pass - def states_changed(self): + def state_changed(self): pass def reset(self): @@ -140,47 +143,52 @@ class PanelBase(ibus.Object): self.__proxy.CursorDown() def property_activate(self, prop_name, prop_state): + prop_name = dbus.String(prop_name) + prop_state = dbus.Int32(prop_state) self.__proxy.PropertyActivate(prop_name, prop_state) def property_show(self, prop_name): + prop_name = dbus.String(prop_name) self.__proxy.PropertyShow(prop_name) def property_hide(self, prop_name): + prop_name = dbus.String(prop_name) self.__proxy.PropertyHide(prop_name) class PanelProxy(interface.IPanel): - def __init__ (self, panel, dbusconn): - super(PanelProxy, self).__init__(dbusconn, IBUS_PANEL_PATH) - self.__dbusconn = dbusconn + def __init__ (self, panel, bus): + super(PanelProxy, self).__init__(bus.get_dbusconn(), IBUS_PATH_PANEL) + self.__bus = bus self.__panel = panel + self.__focus_ic = None def SetCursorLocation(self, x, y, w, h): self.__panel.set_cursor_location(x, y, w, h) - def UpdatePreedit(self, text, attrs, cursor_pos, show): - attrs = ibus.attr_list_from_dbus_value(attrs) - self.__panel.update_preedit(text, attrs, cursor_pos, show) + def UpdatePreeditText(self, text, cursor_pos, visible): + text = deserialize_object(text) + self.__panel.update_preedit_text(text, cursor_pos, visible) - def ShowPreedit(self): - self.__panel.show_preedit() + def ShowPreeditText(self): + self.__panel.show_preedit_text() - def HidePreedit(self): - self.__panel.hide_preedit() + def HidePreeditText(self): + self.__panel.hide_preedit_text() - def UpdateAuxString(self, text, attrs, show): - attrs = ibus.attr_list_from_dbus_value(attrs) - self.__panel.update_aux_string(text, attrs, show) + def UpdateAuxiliaryText(self, text, visible): + text = deserialize_object(text) + self.__panel.update_auxiliary_text(text, visible) - def ShowAuxString(self): - self.__panel.show_aux_string() + def ShowAuxiliaryText(self): + self.__panel.show_auxiliary_text() - def HideAuxString(self): - self.__panel.hide_aux_string() + def HideAuxiliaryText(self): + self.__panel.hide_auxiliary_text() - def UpdateLookupTable(self, lookup_table, show): - lookup_table = ibus.lookup_table_from_dbus_value(lookup_table) - self.__panel.update_lookup_table(lookup_table, show) + def UpdateLookupTable(self, lookup_table, visible): + lookup_table = deserialize_object(lookup_table) + self.__panel.update_lookup_table(lookup_table, visible) def ShowLookupTable(self): self.__panel.show_lookup_table() @@ -213,11 +221,11 @@ class PanelProxy(interface.IPanel): self.__panel.hide_language_bar() def RegisterProperties(self, props): - props = ibus.prop_list_from_dbus_value(props) + props = deserialize_object(props) self.__panel.register_properties(props) def UpdateProperty(self, prop): - prop = ibus.property_from_dbus_value(prop) + prop = deserialize_object(prop) self.__panel.update_property(prop) def FocusIn(self, ic): @@ -226,8 +234,8 @@ class PanelProxy(interface.IPanel): def FocusOut(self, ic): self.__panel.focus_out(ic) - def StatesChanged(self): - self.__panel.states_changed() + def StateChanged(self): + self.__panel.state_changed() def Reset(self): self.__panel.reset() @@ -238,3 +246,41 @@ class PanelProxy(interface.IPanel): def Destroy(self): self.__panel.destroy() +def test(): + import gtk + from bus import Bus + from inputcontext import InputContext + import factory + import attribute + import property + import text + import lookuptable + + class TestPanel(PanelBase): + def __init__(self): + self.__bus = Bus() + self.__bus.connect("disconnected", gtk.main_quit) + super(TestPanel, self).__init__(self.__bus) + self.__bus.request_name(IBUS_SERVICE_PANEL, 0) + + def focus_in(self, ic): + print "focus-in:", ic + context = InputContext(self.__bus, ic) + info = context.get_factory_info() + print "factory:", info.name + + def focus_out(self, ic): + print "focus-out:", ic + + def update_auxiliary_text(self, text, visible): + print "update-auxiliary-text:", text.text + + def update_lookup_table(self, table, visible): + print "update-lookup-table", table + + panel = TestPanel() + gtk.main() + + +if __name__ == "__main__": + test() diff --git a/ibus/property.py b/ibus/property.py index 970975e..72f72a2 100644 --- a/ibus/property.py +++ b/ibus/property.py @@ -30,11 +30,11 @@ __all__ = ( "PROP_STATE_INCONSISTENT", "Property", "PropList", - "property_from_dbus_value", - "prop_list_from_dbus_value", ) import dbus +from text import Text +from serializable import * PROP_TYPE_NORMAL = 0 PROP_TYPE_TOGGLE = 1 @@ -52,18 +52,18 @@ def _to_unicode(text): if isinstance(text, str): return unicode(text, "utf8") raise TypeError("text must be instance of unicode or str") +def _to_text(text): + if isinstance(text, Text): + return text + text = _to_unicode(text) + return Text(text) -class Property(object): - def __init__(self, name, - type = PROP_TYPE_NORMAL, - label = u"", - icon = u"", - tooltip = u"", - sensitive = True, - visible = True, - state = PROP_STATE_UNCHECKED): +class Property(Serializable): + __NAME__ = "IBusProperty" + def __init__(self, key="", type=PROP_TYPE_NORMAL, label=u"", icon=u"", tooltip=u"", + sensitive=True, visible=True, state=PROP_STATE_UNCHECKED): super(Property, self).__init__() - self.__name = _to_unicode(name) + self.__key = _to_unicode(key) self.__type = type self.label = label self.icon = icon @@ -79,14 +79,14 @@ class Property(object): def get_sub_props(self): return self.__sub_props - def get_name(self): - return self.__name + def get_key(self): + return self.__key def get_type(self): return self.__type def set_label(self, label): - self.__label = _to_unicode(label) + self.__label = _to_text(label) def get_label(self): return self.__label @@ -98,7 +98,7 @@ class Property(object): return self.__icon def set_tooltip(self, tooltip): - self.__tooltip = _to_unicode(tooltip) + self.__tooltip = _to_text(tooltip) def get_tooltip(self): return self.__tooltip @@ -121,7 +121,7 @@ class Property(object): def get_visible(self): return self.__visible - name = property(get_name) + key = property(get_key) type = property(get_type) label = property(get_label, set_label) icon = property(get_icon, set_icon) @@ -146,38 +146,37 @@ class Property(object): return self.__sub_props.is_same(prop.__sub_props, test_all) - def to_dbus_value(self): - sub_props = self.__sub_props.to_dbus_value() - values = (dbus.String(self.__name), - dbus.UInt32(self.__type), - dbus.String(self.__label), - dbus.String(self.__icon), - dbus.String(self.__tooltip), - dbus.Boolean(self.__sensitive), - dbus.Boolean(self.__visible), - dbus.UInt32(self.__state), - sub_props) - return dbus.Struct(values) - - def from_dbus_value(self, value): - self.__name, \ - self.__type, \ - self.__label, \ - self.__icon, \ - self.__tooltip, \ - self.__sensitive, \ - self.__visible, \ - self.__state, \ - props = value - - self.__sub_props = prop_list_from_dbus_value(props) - -def property_from_dbus_value(value): - p = Property("") - p.from_dbus_value(value) - return p - -class PropList(object): + def serialize(self, struct): + super(Property, self).serialize(struct) + struct.append(dbus.String(self.__key)) + struct.append(dbus.UInt32(self.__type)) + struct.append(serialize_object(self.__label)) + struct.append(dbus.String(self.__icon)) + struct.append(serialize_object(self.__tooltip)) + struct.append(dbus.Boolean(self.__sensitive)) + struct.append(dbus.Boolean(self.__visible)) + struct.append(dbus.UInt32(self.__state)) + sub_props = serialize_object(self.__sub_props) + struct.append(sub_props) + + def deserialize(self, struct): + super(Property, self).deserialize(struct) + self.__key = struct.pop(0) + self.__type = struct.pop(0) + self.__label = deserialize_object(struct.pop(0)) + self.__icon = struct.pop(0) + self.__tooltip = deserialize_object(struct.pop(0)) + self.__sensitive = deserialize_object(struct.pop(0)) + self.__visible = struct.pop(0) + self.__state = struct.pop(0) + props = struct.pop(0) + + self.__sub_props = deserialize_object(props) + +serializable_register(Property) + +class PropList(Serializable): + __NAME__ = "IBusPropList" def __init__(self): super(PropList, self).__init__() self.__props = [] @@ -203,14 +202,14 @@ class PropList(object): return False return False - def to_dbus_value(self): - props = map(lambda p: p.to_dbus_value(), self.__props) - return dbus.Array(props, signature = "v") + def serialize(self, struct): + super(PropList, self).serialize(struct) + props = map(lambda p: serialize_object(p), self.__props) + struct.append (dbus.Array(props, signature = "v")) - def from_dbus_value(self, value): - props = [] - for p in value: - props.append(property_from_dbus_value(p)) + def deserialize(self, struct): + super(PropList, self).deserialize(struct) + props = map(lambda v: deserialize_object(v), struct.pop(0)) self.__props = props def __iter__(self): @@ -219,10 +218,7 @@ class PropList(object): def __getitem__(self, i): return self.__props.__getitem__(i) -def prop_list_from_dbus_value(value): - props = PropList() - props.from_dbus_value(value) - return props +serializable_register(PropList) def test(): props = PropList() @@ -230,18 +226,9 @@ def test(): props.append(Property(u"b")) props.append(Property(u"c")) props.append(Property(u"d")) - value = props.to_dbus_value() - print prop_list_from_dbus_value(value) - - p = Property(u"z") - p.set_sub_props(props) - props = PropList() - props.append(p) - value = props.to_dbus_value() - print prop_list_from_dbus_value(value) - p.label = u"a" - p.label = "a" - p.label = 1 + value = serialize_object(props) + props = deserialize_object(value) + print props if __name__ == "__main__": test() diff --git a/ibus/serializable.py b/ibus/serializable.py new file mode 100644 index 0000000..734940a --- /dev/null +++ b/ibus/serializable.py @@ -0,0 +1,81 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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_register", + "Serializable", + "serialize_object", + "deserialize_object", + ) + +from object import 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 Serializable(Object): + __NAME__ = "IBusSerializable" + def __init__(self): + super(Serializable, self).__init__() + self.__attachments = dict() + + def serialize(self, struct): + d = dbus.Dictionary(signature="sv") + for k, v in self.__attachments.items(): + d[k] = serialize(v) + struct.append(d) + + def deserialize(self, struct): + d = struct.pop(0) + self.__attachments = dict() + for k, v in d.items(): + self.__atachments[k] = deserialize(v) + + def do_destroy(self): + self.__attachments = None + super(Serializable, self).do_destroy() + +__serializable_name_dict["IBusSerializable"] = Serializable +gobject.type_register(Serializable) diff --git a/ibus/text.py b/ibus/text.py new file mode 100644 index 0000000..9b47dbf --- /dev/null +++ b/ibus/text.py @@ -0,0 +1,68 @@ +# vim:set et sts=4 sw=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# 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__ = ( + "Text", + ) + +import dbus +from exception import IBusException +from serializable import * +from attribute import AttrList + +class Text(Serializable): + __NAME__ = "IBusText" + def __init__ (self, text="", attrs=None): + super(Text, self).__init__() + self.__text = text + self.__attrs = attrs + + def get_text(self): + return self.__text + + def get_attributes(self): + return self.__attrs + + text = property(get_text) + attributes = property(get_attributes) + + def serialize(self, struct): + super(Text, self).serialize(struct) + struct.append (dbus.String(self.__text)) + if self.__attrs == None: + self.__attrs = AttrList() + struct.append (serialize_object(self.__attrs)) + + def deserialize(self, struct): + super(Text, self).deserialize(struct) + + self.__text = struct.pop(0) + self.__attrs = deserialize_object(struct.pop(0)) + +serializable_register(Text) + +def test(): + text = Text("Hello") + value = serialize_object(text) + text = deserialize_object(value) + +if __name__ == "__main__": + test() |