pwu / rpms / ibus

Forked from rpms/ibus 5 years ago
Clone
Blob Blame History Raw
diff --git a/autogen.sh b/autogen.sh
index d9a7a56..c34acab 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -4,7 +4,7 @@ set -x
 
 autopoint  --force
 libtoolize --automake --copy --force
-gtkdocize  #--flavour=no-tmpl
+gtkdocize  --copy #--flavour=no-tmpl
 aclocal -I m4 --force
 autoheader --force
 automake --add-missing --copy --force
diff --git a/bus/engineproxy.c b/bus/engineproxy.c
index 6fc111f..647845b 100644
--- a/bus/engineproxy.c
+++ b/bus/engineproxy.c
@@ -636,7 +636,7 @@ bus_engine_proxy_set_capabilities (BusEngineProxy *engine,
     g_assert (BUS_IS_ENGINE_PROXY (engine));
 
     ibus_proxy_call ((IBusProxy *) engine,
-                     "SetCapabilites",
+                     "SetCapabilities",
                      G_TYPE_UINT, &caps,
                      G_TYPE_INVALID);
 
diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
index e92b373..7f51130 100644
--- a/bus/ibusimpl.c
+++ b/bus/ibusimpl.c
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <signal.h>
 #include <stdlib.h>
 #include "ibusimpl.h"
 #include "dbusimpl.h"
@@ -388,6 +389,41 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
 static void
 bus_ibus_impl_destroy (BusIBusImpl *ibus)
 {
+    pid_t pid;
+    glong timeout;
+    gint status;
+    gboolean flag;
+
+    bus_registry_stop_all_components (ibus->registry);
+
+    pid = 0;
+    timeout = 0;
+    flag = FALSE;
+    while (1) {
+        while ((pid = waitpid (0, &status, WNOHANG)) > 0);
+
+        if (pid == -1) { /* all children finished */
+            break;
+        }
+        if (pid == 0) { /* no child status changed */
+            usleep (1000);
+            timeout += 1000;
+            if (timeout >= G_USEC_PER_SEC) {
+                if (flag == FALSE) {
+                    gpointer old;
+                    old = signal (SIGTERM, SIG_IGN);
+                    kill (-getpid (), SIGTERM);
+                    signal (SIGTERM, old);
+                    flag = TRUE;
+                }
+                else {
+                    g_warning ("Not every child processes exited!");
+                    break;
+                }
+            }
+        }
+    };
+
     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
     g_list_free (ibus->engine_list);
     ibus->engine_list = NULL;
@@ -407,7 +443,7 @@ bus_ibus_impl_destroy (BusIBusImpl *ibus)
     }
 
     bus_server_quit (BUS_DEFAULT_SERVER);
-
+    ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
     IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (ibus));
 }
 
@@ -662,6 +698,8 @@ _ibus_create_input_context (BusIBusImpl     *ibus,
     context = bus_input_context_new (connection, client);
     ibus->contexts = g_list_append (ibus->contexts, context);
 
+    _context_request_engine_cb (context, NULL, ibus);
+
     static const struct {
         gchar *name;
         GCallback callback;
@@ -832,7 +870,6 @@ _ibus_list_active_engines (BusIBusImpl   *ibus,
     return reply;
 }
 
-extern gchar **g_argv;
 
 static IBusMessage *
 _ibus_exit (BusIBusImpl     *ibus,
@@ -842,7 +879,7 @@ _ibus_exit (BusIBusImpl     *ibus,
     IBusMessage *reply;
     IBusError *error;
     gboolean restart;
-    
+
     if (!ibus_message_get_args (message,
                                 &error,
                                 G_TYPE_BOOLEAN, &restart,
@@ -859,32 +896,28 @@ _ibus_exit (BusIBusImpl     *ibus,
     ibus_connection_flush ((IBusConnection *) connection);
     ibus_message_unref (reply);
 
-    
+    ibus_object_destroy ((IBusObject *) ibus);
+
     if (!restart) {
         exit (0);
     }
     else {
-        glong timeout;
-        gint fd;
-        gint status;
-        
-        bus_registry_stop_all_components (ibus->registry);
-        ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
-        for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd++) {
-            close (fd);
+        extern gchar **g_argv;
+        gchar *exe;
+
+        exe = g_strdup_printf ("/proc/%d/exe", getpid ());
+        if (!g_file_test (exe, G_FILE_TEST_EXISTS)) {
+            g_free (exe);
+            exe = g_argv[0];
         }
-        for (timeout = 0; waitpid (0, &status, WNOHANG) != -1;) {
-            usleep (1000);
-            timeout += 1000;
-            if (timeout >= G_USEC_PER_SEC * 2) {
-                g_warning ("Not every child processes exited!");
-            }
-        };
-        execv (g_argv[0], g_argv);
+        execv (exe, g_argv);
         g_warning ("execv %s failed!", g_argv[0]);
         exit (-1);
     }
-    
+
+    /* should not reach here */
+    g_assert_not_reached ();
+
     return NULL;
 }
 
diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index be45bbe..979c710 100644
--- a/bus/inputcontext.c
+++ b/bus/inputcontext.c
@@ -100,6 +100,8 @@ static gboolean bus_input_context_send_signal   (BusInputContext        *context
                                                  const gchar            *signal_name,
                                                  GType                   first_arg_type,
                                                  ...);
+
+static void     bus_input_context_unset_engine  (BusInputContext        *context);
 static void     _engine_destroy_cb              (BusEngineProxy         *factory,
                                                  BusInputContext        *context);
 
@@ -486,11 +488,7 @@ bus_input_context_destroy (BusInputContext *context)
     }
 
     if (priv->engine) {
-        g_signal_handlers_disconnect_by_func (priv->engine,
-                                              G_CALLBACK (_engine_destroy_cb),
-                                              context);
-        g_object_unref (priv->engine);
-        priv->engine = NULL;
+        bus_input_context_unset_engine (context);
     }
 
     if (priv->connection) {
@@ -562,7 +560,7 @@ _ic_process_key_event_reply_cb (gpointer data,
 
     retval = (gboolean) GPOINTER_TO_INT (data);
     call_data = (CallData *) user_data;
-    
+
     BusInputContextPrivate *priv;
     priv = BUS_INPUT_CONTEXT_GET_PRIVATE (call_data->context);
 
@@ -596,8 +594,6 @@ _ic_process_key_event (BusInputContext *context,
     BusInputContextPrivate *priv;
     priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
 
-
-    error = ibus_error_new ();
     retval = ibus_message_get_args (message,
                 &error,
                 G_TYPE_UINT, &keyval,
@@ -612,8 +608,6 @@ _ic_process_key_event (BusInputContext *context,
         return reply;
     }
 
-    ibus_error_free (error);
-
     retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, modifiers);
 
     if (retval) {
@@ -623,12 +617,16 @@ _ic_process_key_event (BusInputContext *context,
                                   G_TYPE_INVALID);
     }
     else if (priv->enabled && priv->engine) {
-        CallData *call_data = g_slice_new (CallData);
-        call_data->context = context;
-        call_data->message = message;
+        CallData *call_data;
+
+        call_data = g_slice_new (CallData);
+
         g_object_ref (context);
         ibus_message_ref (message);
 
+        call_data->context = context;
+        call_data->message = message;
+
         bus_engine_proxy_process_key_event (priv->engine,
                                             keyval,
                                             modifiers,
@@ -1012,7 +1010,7 @@ bus_input_context_focus_in (BusInputContext *context)
 
     priv->has_focus = TRUE;
 
-    if (priv->engine) {
+    if (priv->engine && priv->enabled) {
         bus_engine_proxy_focus_in (priv->engine);
     }
 
@@ -1034,7 +1032,7 @@ bus_input_context_focus_out (BusInputContext *context)
 
     priv->has_focus = FALSE;
 
-    if (priv->engine) {
+    if (priv->engine && priv->enabled) {
         bus_engine_proxy_focus_out (priv->engine);
     }
 
@@ -1122,7 +1120,8 @@ _engine_destroy_cb (BusEngineProxy  *engine,
 
     g_assert (priv->engine == engine);
 
-    bus_input_context_set_engine (context, NULL);
+    bus_input_context_unset_engine (context);
+    bus_input_context_disable (context);
 }
 
 static void
@@ -1391,7 +1390,6 @@ bus_input_context_disable (BusInputContext *context)
     BusInputContextPrivate *priv;
     priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
 
-    priv->enabled = FALSE;
 
     if (priv->engine) {
         if (priv->has_focus) {
@@ -1406,8 +1404,52 @@ bus_input_context_disable (BusInputContext *context)
     g_signal_emit (context,
                    context_signals[DISABLED],
                    0);
+
+    priv->enabled = FALSE;
 }
 
+const static struct {
+    const gchar *name;
+    GCallback    callback;
+} signals [] = {
+    { "commit-text",            G_CALLBACK (_engine_commit_text_cb) },
+    { "forward-key-event",      G_CALLBACK (_engine_forward_key_event_cb) },
+    { "update-preedit-text",    G_CALLBACK (_engine_update_preedit_text_cb) },
+    { "show-preedit-text",      G_CALLBACK (_engine_show_preedit_text_cb) },
+    { "hide-preedit-text",      G_CALLBACK (_engine_hide_preedit_text_cb) },
+    { "update-auxiliary-text",  G_CALLBACK (_engine_update_auxiliary_text_cb) },
+    { "show-auxiliary-text",    G_CALLBACK (_engine_show_auxiliary_text_cb) },
+    { "hide-auxiliary-text",    G_CALLBACK (_engine_hide_auxiliary_text_cb) },
+    { "update-lookup-table",    G_CALLBACK (_engine_update_lookup_table_cb) },
+    { "show-lookup-table",      G_CALLBACK (_engine_show_lookup_table_cb) },
+    { "hide-lookup-table",      G_CALLBACK (_engine_hide_lookup_table_cb) },
+    { "page-up-lookup-table",   G_CALLBACK (_engine_page_up_lookup_table_cb) },
+    { "page-down-lookup-table", G_CALLBACK (_engine_page_down_lookup_table_cb) },
+    { "cursor-up-lookup-table", G_CALLBACK (_engine_cursor_up_lookup_table_cb) },
+    { "cursor-down-lookup-table", G_CALLBACK (_engine_cursor_down_lookup_table_cb) },
+    { "register-properties",    G_CALLBACK (_engine_register_properties_cb) },
+    { "update-property",        G_CALLBACK (_engine_update_property_cb) },
+    { "destroy",                G_CALLBACK (_engine_destroy_cb) },
+    { NULL, 0 }
+};
+
+static void
+bus_input_context_unset_engine (BusInputContext *context)
+{
+    g_assert (BUS_IS_INPUT_CONTEXT (context));
+
+    BusInputContextPrivate *priv;
+    priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
+
+    if (priv->engine) {
+        gint i;
+        for (i = 0; signals[i].name != NULL; i++) {
+            g_signal_handlers_disconnect_by_func (priv->engine, signals[i].callback, context);
+        }
+        g_object_unref (priv->engine);
+        priv->engine = NULL;
+    }
+}
 
 void
 bus_input_context_set_engine (BusInputContext *context,
@@ -1420,56 +1462,25 @@ bus_input_context_set_engine (BusInputContext *context,
     priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
 
     if (priv->engine != NULL) {
-        g_signal_handlers_disconnect_by_func (priv->engine, _engine_destroy_cb, context);
-        ibus_object_destroy ((IBusObject *) priv->engine);
-        g_object_unref (priv->engine);
-        priv->engine = NULL;
+        bus_input_context_unset_engine (context);
     }
 
     if (engine == NULL) {
         bus_input_context_disable (context);
-        g_signal_emit (context,
-                       context_signals[ENGINE_CHANGED],
-                       0);
-        return;
     }
-
-    priv->engine = engine;
-    g_object_ref (priv->engine);
-
-    gint i;
-    const static struct {
-        const gchar *name;
-        GCallback    callback;
-    } signals [] = {
-        { "commit-text",            G_CALLBACK (_engine_commit_text_cb) },
-        { "forward-key-event",      G_CALLBACK (_engine_forward_key_event_cb) },
-        { "update-preedit-text",    G_CALLBACK (_engine_update_preedit_text_cb) },
-        { "show-preedit-text",      G_CALLBACK (_engine_show_preedit_text_cb) },
-        { "hide-preedit-text",      G_CALLBACK (_engine_hide_preedit_text_cb) },
-        { "update-auxiliary-text",  G_CALLBACK (_engine_update_auxiliary_text_cb) },
-        { "show-auxiliary-text",    G_CALLBACK (_engine_show_auxiliary_text_cb) },
-        { "hide-auxiliary-text",    G_CALLBACK (_engine_hide_auxiliary_text_cb) },
-        { "update-lookup-table",    G_CALLBACK (_engine_update_lookup_table_cb) },
-        { "show-lookup-table",      G_CALLBACK (_engine_show_lookup_table_cb) },
-        { "hide-lookup-table",      G_CALLBACK (_engine_hide_lookup_table_cb) },
-        { "page-up-lookup-table",   G_CALLBACK (_engine_page_up_lookup_table_cb) },
-        { "page-down-lookup-table", G_CALLBACK (_engine_page_down_lookup_table_cb) },
-        { "cursor-up-lookup-table", G_CALLBACK (_engine_cursor_up_lookup_table_cb) },
-        { "cursor-down-lookup-table", G_CALLBACK (_engine_cursor_down_lookup_table_cb) },
-        { "register-properties",    G_CALLBACK (_engine_register_properties_cb) },
-        { "update-property",        G_CALLBACK (_engine_update_property_cb) },
-        { "destroy",                G_CALLBACK (_engine_destroy_cb) },
-        { NULL, 0 }
-    };
-
-    for (i = 0; signals[i].name != NULL; i++) {
-        g_signal_connect (priv->engine,
-                          signals[i].name,
-                          signals[i].callback,
-                          context);
+    else {
+        gint i;
+        priv->engine = engine;
+        g_object_ref (priv->engine);
+
+        for (i = 0; signals[i].name != NULL; i++) {
+            g_signal_connect (priv->engine,
+                              signals[i].name,
+                              signals[i].callback,
+                              context);
+        }
+        bus_engine_proxy_set_cursor_location (priv->engine, priv->x, priv->y, priv->w, priv->h);
     }
-
     g_signal_emit (context,
                    context_signals[ENGINE_CHANGED],
                    0);
diff --git a/bus/main.c b/bus/main.c
index eec1df0..8757af5 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -29,6 +29,7 @@ gchar **g_argv = NULL;
 static gboolean daemonize = FALSE;
 static gboolean single = FALSE;
 static gboolean xim = FALSE;
+static gboolean replace = FALSE;
 static gchar *panel = "default";
 static gchar *config = "default";
 static gchar *desktop = "gnome";
@@ -45,7 +46,8 @@ static const GOptionEntry entries[] =
     { "panel", 'p', 0, G_OPTION_ARG_STRING, &panel, "specify the cmdline of panel program.", "cmdline" },
     { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "specify the cmdline of config program.", "cmdline" },
     { "address", 'a', 0, G_OPTION_ARG_STRING, &address, "specify the address of ibus daemon.", "address" },
-    { "re-scan", 'r', 0, G_OPTION_ARG_NONE, &g_rescan, "force to re-scan components, and re-create registry cache.", NULL },
+    { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "if there is an old ibus-daemon is running, it will be replaced.", NULL },
+    { "re-scan", 't', 0, G_OPTION_ARG_NONE, &g_rescan, "force to re-scan components, and re-create registry cache.", NULL },
     { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose.", NULL },
     { NULL },
 };
@@ -88,6 +90,7 @@ main (gint argc, gchar **argv)
 {
     GOptionContext *context;
     BusServer *server;
+    IBusBus *bus;
 
     GError *error = NULL;
 
@@ -103,9 +106,6 @@ main (gint argc, gchar **argv)
         exit (-1);
     }
 
-    /* create a new process group */
-    setpgrp ();
-
     if (daemonize) {
         if (daemon (1, 0) != 0) {
             g_printerr ("Can not daemonize ibus.\n");
@@ -113,8 +113,28 @@ main (gint argc, gchar **argv)
         }
     }
 
+    /* create a new process group */
+    setpgrp ();
+
     g_type_init ();
 
+    /* check if ibus-daemon is running in this session */
+    bus = ibus_bus_new ();
+
+    if (ibus_bus_is_connected (bus)) {
+        if (!replace) {
+            g_printerr ("current session already has an ibus-daemon.\n");
+            exit (-1);
+        }
+        ibus_bus_exit (bus, FALSE);
+        while (ibus_bus_is_connected (bus)) {
+            g_main_context_iteration (NULL, TRUE);
+        }
+    }
+    g_object_unref (bus);
+    bus = NULL;
+
+    /* create ibus server */
     server = bus_server_get_default ();
     bus_server_listen (server);
 
diff --git a/client/gtk2/ibusim.c b/client/gtk2/ibusim.c
index 56f593a..75b02a5 100644
--- a/client/gtk2/ibusim.c
+++ b/client/gtk2/ibusim.c
@@ -33,13 +33,11 @@ static const GtkIMContextInfo ibus_im_info = {
     "ja:ko:zh"
 };
 
-static const GtkIMContextInfo * info_list[] = {
+static const GtkIMContextInfo *info_list[] = {
     &ibus_im_info
 };
 
-
-G_MODULE_EXPORT const gchar* g_module_check_init (GModule *module);
-const gchar*
+G_MODULE_EXPORT const gchar*
 g_module_check_init (GModule *module)
 {
     return glib_check_version (GLIB_MAJOR_VERSION,
@@ -47,7 +45,7 @@ g_module_check_init (GModule *module)
                                GLIB_MICRO_VERSION);
 }
 
-void
+G_MODULE_EXPORT void
 im_module_init (GTypeModule *type_module)
 {
     /* make module resident */
@@ -56,25 +54,25 @@ im_module_init (GTypeModule *type_module)
     ibus_im_context_register_type (type_module);
 }
 
-void
+G_MODULE_EXPORT void
 im_module_exit (void)
 {
 }
 
-GtkIMContext *
+G_MODULE_EXPORT GtkIMContext *
 im_module_create (const gchar *context_id)
 {
     if (g_strcmp0 (context_id, "ibus") == 0) {
         IBusIMContext *context;
         context = ibus_im_context_new ();
-        return GTK_IM_CONTEXT(context);
+        return (GtkIMContext *) context;
     }
     return NULL;
 }
 
-void
+G_MODULE_EXPORT void
 im_module_list (const GtkIMContextInfo ***contexts,
-                int                      *n_contexts)
+                gint                     *n_contexts)
 {
     *contexts = info_list;
     *n_contexts = G_N_ELEMENTS (info_list);
diff --git a/client/x11/main.c b/client/x11/main.c
index 5ef9f30..6437d50 100644
--- a/client/x11/main.c
+++ b/client/x11/main.c
@@ -327,7 +327,7 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data)
     x11ic->icid = call_data->icid;
     x11ic->connect_id = call_data->connect_id;
     x11ic->conn = (X11ICONN *)g_hash_table_lookup (_connections,
-                                                   GINT_TO_POINTER (call_data->connect_id));
+                                                   GINT_TO_POINTER ((gint) call_data->connect_id));
     if (x11ic->conn == NULL) {
         g_slice_free (X11IC, x11ic);
         g_return_val_if_reached (0);
@@ -383,7 +383,7 @@ xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *)g_hash_table_lookup (_x11_ic_table,
-                                          GINT_TO_POINTER (call_data->icid));
+                                          GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     if (x11ic->context) {
@@ -393,7 +393,7 @@ xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data)
     }
 
     g_hash_table_remove (_x11_ic_table,
-                         GINT_TO_POINTER (call_data->icid));
+                         GINT_TO_POINTER ((gint) call_data->icid));
     x11ic->conn->clients = g_list_remove (x11ic->conn->clients, (gconstpointer)x11ic);
 
     g_free (x11ic->preedit_string);
@@ -418,7 +418,7 @@ xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
-                                           GINT_TO_POINTER (call_data->icid));
+                                           GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     ibus_input_context_focus_in (x11ic->context);
@@ -436,7 +436,7 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
-                                           GINT_TO_POINTER (call_data->icid));
+                                           GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     ibus_input_context_focus_out (x11ic->context);
@@ -456,7 +456,7 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
-                                           GINT_TO_POINTER (call_data->icid));
+                                           GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     xevent = (XKeyEvent*) &(call_data->event);
@@ -504,7 +504,7 @@ xim_open (XIMS xims, IMOpenStruct *call_data)
                 call_data->connect_id);
 
     conn = (X11ICONN *) g_hash_table_lookup (_connections,
-                                             GINT_TO_POINTER (call_data->connect_id));
+                                             GINT_TO_POINTER ((gint) call_data->connect_id));
     g_return_val_if_fail (conn == NULL, 0);
 
     conn = g_slice_new0 (X11ICONN);
@@ -552,7 +552,7 @@ xim_close (XIMS ims, IMCloseStruct *call_data)
                 call_data->connect_id);
 
     conn = (X11ICONN *) g_hash_table_lookup (_connections,
-                                             GINT_TO_POINTER (call_data->connect_id));
+                                             GINT_TO_POINTER ((gint) call_data->connect_id));
     g_return_val_if_fail (conn != NULL, 0);
 
     g_list_foreach (conn->clients, _free_ic, NULL);
@@ -560,7 +560,7 @@ xim_close (XIMS ims, IMCloseStruct *call_data)
     g_list_free (conn->clients);
 
     g_hash_table_remove (_connections,
-                         GINT_TO_POINTER (call_data->connect_id));
+                         GINT_TO_POINTER ((gint) call_data->connect_id));
 
     g_slice_free (X11ICONN, conn);
 
@@ -621,7 +621,7 @@ xim_set_ic_values (XIMS xims, IMChangeICStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
-                                           GINT_TO_POINTER (call_data->icid));
+                                           GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     i = _xim_store_ic_values (x11ic, call_data);
@@ -643,7 +643,7 @@ xim_get_ic_values (XIMS xims, IMChangeICStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
-                                           GINT_TO_POINTER (call_data->icid));
+                                           GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     XICAttribute *ic_attr = call_data->ic_attr;
@@ -670,7 +670,7 @@ xim_reset_ic (XIMS xims, IMResetICStruct *call_data)
                 call_data->icid, call_data->connect_id);
 
     x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
-                                           GINT_TO_POINTER (call_data->icid));
+                                           GINT_TO_POINTER ((gint) call_data->icid));
     g_return_val_if_fail (x11ic != NULL, 0);
 
     ibus_input_context_reset (x11ic->context);
@@ -981,7 +981,7 @@ _xim_init_IMdkit ()
 static void
 _atexit_cb ()
 {
-    if (_bus) {
+    if (_bus && ibus_bus_is_connected (_bus)) {
         ibus_bus_exit(_bus, False);
     }
 }
diff --git a/configure.ac b/configure.ac
index 7481739..4437fd2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -177,7 +177,7 @@ AC_ARG_ENABLE(qt4-immodule,
 if test x"$IBUS_HAS_QT4" != x"yes"; then
     enable_qt4=no
 fi
-enable_qt=no
+enable_qt4=no
 AM_CONDITIONAL(IBUS_BUILD_QT4, [test x"$enable_qt4" = x"yes" ])
 
 PKG_CHECK_MODULES(GCONF,
diff --git a/ibus.spec.in b/ibus.spec.in
index 65dfced..908ddbd 100644
--- a/ibus.spec.in
+++ b/ibus.spec.in
@@ -20,7 +20,7 @@ BuildRequires:  libtool
 BuildRequires:  python
 BuildRequires:  gtk2-devel
 BuildRequires:  dbus-devel
-BuildRequires:  qt-devel
+# BuildRequires:  qt-devel
 BuildRequires:  dbus-glib-devel
 BuildRequires:  desktop-file-utils
 
@@ -29,10 +29,10 @@ Requires(post):  %{_sbindir}/alternatives
 Requires(postun):  desktop-file-utils
 Requires(postun):  %{_sbindir}/alternatives
 
+Requires:   %{name}-libs = %{version}-%{release}
 Requires:   glib2 >= %{glib_ver}
 Requires:   pygtk2
 Requires:   dbus-python >= 0.83.0
-Requires:   gnome-python2-gconf
 Requires:   notification-daemon
 Requires:   pyxdg
 Requires:   iso-codes
@@ -44,6 +44,14 @@ IBus means Intelligent Input Bus. It is a new input framework for Linux OS. It p
 full featured and user friendly input method user interface. It also may help
 developers to develop input method easily.
 
+%package libs
+Summary:    IBus libraries
+Group:      System Environment/Libraries
+
+%description libs
+This package contains ibus libraries.
+
+
 %package gtk
 Summary:    IBus im module for gtk2
 Group:      System Environment/Libraries
@@ -52,14 +60,14 @@ Requires:   %{name} = %{version}-%{release}
 %description gtk
 This package contains ibus im module for gtk2
 
-%package qt
-Summary:    IBus im module for qt4
-Group:      System Environment/Libraries
-Requires:   %{name} = %{version}-%{release}
-Requires:   qt >= 4.4.2
-
-%description qt
-This package contains ibus im module for qt4
+# %package qt
+# Summary:    IBus im module for qt4
+# Group:      System Environment/Libraries
+# Requires:   %{name} = %{version}-%{release}
+# Requires:   qt >= 4.4.2
+# 
+# %description qt
+# This package contains ibus im module for qt4
 
 %package devel
 Summary:    Development tools for ibus
@@ -100,7 +108,7 @@ desktop-file-install --delete-original          \
 %clean
 rm -rf $RPM_BUILD_ROOT
 
-%post
+%post libs
 /sbin/ldconfig
 update-desktop-database -q
 %{_sbindir}/alternatives --install %{_sysconfdir}/X11/xinit/xinputrc xinputrc %{_xinputconf} 83 || :
@@ -108,7 +116,7 @@ update-desktop-database -q
 %post gtk
 %{_bindir}/update-gtk-immodules %{_host} || :
 
-%postun
+%postun libs
 /sbin/ldconfig
 update-desktop-database -q
 if [ "$1" = "0" ]; then
@@ -123,13 +131,10 @@ fi
 %files -f %{name}.lang
 %defattr(-,root,root,-)
 %doc AUTHORS COPYING README
-%dir %{python_sitelib}/ibus
-%{python_sitelib}/ibus/*
-%dir %{_datadir}/ibus/
+%{python_sitelib}/ibus
 %{_bindir}/ibus-daemon
 %{_bindir}/ibus-setup
-%{_libdir}/libibus.so*
-%{_datadir}/ibus/*
+%{_datadir}/ibus
 %{_datadir}/applications/*
 %{_datadir}/pixmaps/*
 %{_libexecdir}/ibus-gconf
@@ -137,13 +142,18 @@ fi
 %{_libexecdir}/ibus-x11
 %config %{_xinputconf}
 
+
+%files libs
+%defattr(-,root,root,-)
+%{_libdir}/libibus.so*
+
 %files gtk
 %defattr(-,root,root,-)
 %{_libdir}/gtk-2.0/%{gtk_binary_version}/immodules/im-ibus.so
 
-%files qt
-%defattr(-,root,root,-)
-%{_libdir}/qt4/plugins/inputmethods/libibus.so
+# %files qt
+# %defattr(-,root,root,-)
+# %{_libdir}/qt4/plugins/inputmethods/libibus.so
 
 %files devel
 %defattr(-,root,root,-)
diff --git a/ibus/engine.py b/ibus/engine.py
index d52c97e..f8c0447 100644
--- a/ibus/engine.py
+++ b/ibus/engine.py
@@ -44,6 +44,9 @@ class EngineBase(object.Object):
     def set_cursor_location(self, x, y, w, h):
         pass
 
+    def set_capabilities(self, cap):
+        pass
+
     def reset(self):
         pass
 
@@ -158,6 +161,9 @@ class EngineProxy(interface.IEngine):
     def SetCursorLocation(self, x, y, w, h):
         return self.__engine.set_cursor_location(x, y, w, h)
 
+    def SetCapabilities(self, caps):
+        return self.__engine.set_capabilities(caps)
+
     def Reset(self):
         return self.__engine.reset()
 
diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py
index 32ba998..63d6c0e 100644
--- a/ibus/interface/iengine.py
+++ b/ibus/interface/iengine.py
@@ -49,6 +49,9 @@ class IEngine(dbus.service.Object):
     @method(in_signature="iiii")
     def SetCursorLocation(self, x, y, w, h): pass
 
+    @method(in_signature="u")
+    def SetCapabilities(self, cap): pass
+
     @method()
     def FocusIn(self): pass
 
diff --git a/src/ibusbus.c b/src/ibusbus.c
index 9965761..52631e8 100644
--- a/src/ibusbus.c
+++ b/src/ibusbus.c
@@ -149,6 +149,9 @@ _connection_destroy_cb (IBusConnection  *connection,
     priv = IBUS_BUS_GET_PRIVATE (bus);
 
     g_assert (priv->connection == connection);
+    g_signal_handlers_disconnect_by_func (priv->connection,
+                                          G_CALLBACK (_connection_destroy_cb),
+                                          bus);
     g_object_unref (priv->connection);
     priv->connection = NULL;
 
@@ -639,12 +642,15 @@ ibus_bus_exit (IBusBus *bus,
 {
     g_assert (IBUS_IS_BUS (bus));
 
+    IBusBusPrivate *priv;
+    priv = IBUS_BUS_GET_PRIVATE (bus);
+
     gboolean result;
     result = ibus_bus_call (bus,
                             IBUS_SERVICE_IBUS,
                             IBUS_PATH_IBUS,
                             IBUS_INTERFACE_IBUS,
-                            "Kill",
+                            "Exit",
                             G_TYPE_BOOLEAN, &restart,
                             G_TYPE_INVALID,
                             G_TYPE_INVALID);
diff --git a/src/ibusengine.c b/src/ibusengine.c
index 0c36dd4..27fc71e 100644
--- a/src/ibusengine.c
+++ b/src/ibusengine.c
@@ -101,7 +101,7 @@ static void     ibus_engine_cursor_down     (IBusEngine         *engine);
 static void     ibus_engine_property_activate
                                             (IBusEngine         *engine,
                                              const gchar        *prop_name,
-                                             gint                prop_state);
+                                             guint               prop_state);
 static void     ibus_engine_property_show   (IBusEngine         *engine,
                                              const gchar        *prop_name);
 static void     ibus_engine_property_hide   (IBusEngine         *engine,
@@ -227,7 +227,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, focus_in),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[FOCUS_OUT] =
         g_signal_new (I_("focus-out"),
@@ -236,7 +237,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, focus_out),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[RESET] =
         g_signal_new (I_("reset"),
@@ -245,7 +247,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, reset),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[ENABLE] =
         g_signal_new (I_("enable"),
@@ -254,7 +257,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, enable),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[DISABLE] =
         g_signal_new (I_("disable"),
@@ -263,7 +267,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, disable),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[SET_CURSOR_LOCATION] =
         g_signal_new (I_("set-cursor-location"),
@@ -272,8 +277,12 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, set_cursor_location),
             NULL, NULL,
             ibus_marshal_VOID__INT_INT_INT_INT,
-            G_TYPE_NONE, 4,
-            G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
+            G_TYPE_NONE,
+            4,
+            G_TYPE_INT,
+            G_TYPE_INT,
+            G_TYPE_INT,
+            G_TYPE_INT);
 
     engine_signals[SET_CAPABILITIES] =
         g_signal_new (I_("set-capabilities"),
@@ -282,7 +291,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, set_capabilities),
             NULL, NULL,
             ibus_marshal_VOID__UINT,
-            G_TYPE_NONE, 1,
+            G_TYPE_NONE,
+            1,
             G_TYPE_UINT);
 
     engine_signals[PAGE_UP] =
@@ -292,7 +302,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, page_up),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[PAGE_DOWN] =
         g_signal_new (I_("page-down"),
@@ -301,7 +312,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, page_down),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[CURSOR_UP] =
         g_signal_new (I_("cursor-up"),
@@ -310,7 +322,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, cursor_up),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[CURSOR_DOWN] =
         g_signal_new (I_("cursor-down"),
@@ -319,7 +332,8 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, cursor_down),
             NULL, NULL,
             ibus_marshal_VOID__VOID,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            0);
 
     engine_signals[PROPERTY_ACTIVATE] =
         g_signal_new (I_("property-activate"),
@@ -328,7 +342,10 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, property_activate),
             NULL, NULL,
             ibus_marshal_VOID__STRING_INT,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            2,
+            G_TYPE_STRING,
+            G_TYPE_INT);
 
     engine_signals[PROPERTY_SHOW] =
         g_signal_new (I_("property-show"),
@@ -337,7 +354,9 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, property_show),
             NULL, NULL,
             ibus_marshal_VOID__STRING,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            1,
+            G_TYPE_STRING);
 
     engine_signals[PROPERTY_HIDE] =
         g_signal_new (I_("property-hide"),
@@ -346,7 +365,9 @@ ibus_engine_class_init (IBusEngineClass *klass)
             G_STRUCT_OFFSET (IBusEngineClass, property_hide),
             NULL, NULL,
             ibus_marshal_VOID__STRING,
-            G_TYPE_NONE, 0);
+            G_TYPE_NONE,
+            1,
+            G_TYPE_STRING);
 
 }
 
@@ -465,6 +486,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
         ibus_message_iter_init (message, &iter);
         if (ibus_message_iter_has_next (&iter)) {
             error_message = ibus_message_new_error_printf (message,
+                                DBUS_ERROR_INVALID_ARGS,
                                 "%s.%s: Method does not have arguments",
                                 IBUS_INTERFACE_ENGINE, no_arg_methods[i].member);
             ibus_connection_send (connection, error_message);
@@ -512,6 +534,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
 
     _keypress_fail:
         error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
                         "%s.%s: Can not match signature (ubu) of method",
                         IBUS_INTERFACE_ENGINE, "ProcessKeyEvent");
         ibus_connection_send (connection, error_message);
@@ -527,7 +550,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
         retval = ibus_message_get_args (message,
                                         &error,
                                         G_TYPE_STRING, &name,
-                                        G_TYPE_INT, &state,
+                                        G_TYPE_UINT, &state,
                                         G_TYPE_INVALID);
 
         if (!retval)
@@ -546,6 +569,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
 
     _property_activate_fail:
         error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
                         "%s.%s: Can not match signature (si) of method",
                         IBUS_INTERFACE_ENGINE,
                         "PropertyActivate");
@@ -579,6 +603,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
 
     _property_show_fail:
         error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
                         "%s.%s: Can not match signature (s) of method",
                         IBUS_INTERFACE_ENGINE,
                         "PropertyShow");
@@ -607,6 +632,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
 
     _property_hide_fail:
         error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
                         "%s.%s: Can not match signature (s) of method",
                         IBUS_INTERFACE_ENGINE, "PropertyHide");
         ibus_connection_send (connection, error_message);
@@ -645,6 +671,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
 
     _set_cursor_location_fail:
         error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
                         "%s.%s: Can not match signature (iiii) of method",
                         IBUS_INTERFACE_ENGINE,
                         "SetCursorLocation");
@@ -676,6 +703,7 @@ ibus_engine_ibus_message (IBusEngine     *engine,
 
     _set_capabilities_fail:
         error_message = ibus_message_new_error_printf (message,
+                        DBUS_ERROR_INVALID_ARGS,
                         "%s.%s: Can not match signature (u) of method",
                         IBUS_INTERFACE_ENGINE, "SetCapabilities");
         ibus_connection_send (connection, error_message);
@@ -775,8 +803,9 @@ ibus_engine_cursor_down (IBusEngine *engine)
 }
 
 static void
-ibus_engine_property_activate (IBusEngine *engine,
-    const gchar *prop_name, gint prop_state)
+ibus_engine_property_activate (IBusEngine  *engine,
+                               const gchar *prop_name,
+                               guint        prop_state)
 {
     // g_debug ("property-activate ('%s', %d)", prop_name, prop_state);
 }
diff --git a/src/ibusengine.h b/src/ibusengine.h
index 0a827af..1a35c06 100644
--- a/src/ibusengine.h
+++ b/src/ibusengine.h
@@ -91,7 +91,7 @@ struct _IBusEngineClass {
     void        (* property_activate)
                                     (IBusEngine     *engine,
                                      const gchar    *prop_name,
-                                     gint            prop_state);
+                                     guint           prop_state);
     void        (* property_show)   (IBusEngine     *engine,
                                      const gchar    *prop_name);
     void        (* property_hide)   (IBusEngine     *engine,
diff --git a/src/ibuslookuptable.c b/src/ibuslookuptable.c
index e2935b8..37342c5 100644
--- a/src/ibuslookuptable.c
+++ b/src/ibuslookuptable.c
@@ -121,7 +121,7 @@ ibus_lookup_table_serialize (IBusLookupTable *table,
 
     retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &table->cursor_visible);
     g_return_val_if_fail (retval, FALSE);
-    
+
     retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &table->round);
     g_return_val_if_fail (retval, FALSE);
 
@@ -168,7 +168,7 @@ ibus_lookup_table_deserialize (IBusLookupTable *table,
 
     retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &table->cursor_visible);
     g_return_val_if_fail (retval, FALSE);
-    
+
     retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &table->round);
     g_return_val_if_fail (retval, FALSE);
 
@@ -223,6 +223,8 @@ ibus_lookup_table_new (guint page_size,
                        gboolean cursor_visible,
                        gboolean round)
 {
+    g_assert (page_size > 0);
+
     IBusLookupTable *table;
 
     table= g_object_new (IBUS_TYPE_LOOKUP_TABLE, NULL);
@@ -278,15 +280,150 @@ ibus_lookup_table_set_cursor_pos (IBusLookupTable *table,
                                   guint            cursor_pos)
 {
     g_assert (IBUS_IS_LOOKUP_TABLE (table));
+    g_assert (cursor_pos < table->candidates->len);
 
     table->cursor_pos = cursor_pos;
 }
+
+guint
+ibus_lookup_table_get_cursor_pos (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    return table->cursor_pos;
+}
+
+guint
+ibus_lookup_table_get_cursor_in_page (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    return table->cursor_pos % table->page_size;
+}
+
+void
+ibus_lookup_table_set_cursor_visible (IBusLookupTable *table,
+                                      gboolean         visible)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    table->cursor_visible = visible;
+}
+
+gboolean
+ibus_lookup_table_is_cursor_visible (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    return table->cursor_visible;
+}
+
 void
 ibus_lookup_table_set_page_size  (IBusLookupTable *table,
                                   guint            page_size)
 {
     g_assert (IBUS_IS_LOOKUP_TABLE (table));
+    g_assert (page_size > 0);
 
     table->page_size = page_size;
 }
 
+guint
+ibus_lookup_table_get_page_size (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    return table->page_size;
+}
+
+gboolean
+ibus_lookup_table_page_up (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    if (table->cursor_pos < table->page_size) {
+        gint i;
+        gint page_nr;
+
+        if (!table->round) {
+            return FALSE;
+        }
+
+        /* cursor index in page */
+        i = table->cursor_pos % table->page_size;
+        page_nr = (table->candidates->len + table->page_size - 1) / table->page_size;
+
+        table->cursor_pos = page_nr * table->page_size + i;
+        if (table->cursor_pos >= table->candidates->len) {
+            table->cursor_pos = table->candidates->len - 1;
+        }
+        return TRUE;
+    }
+
+    table->cursor_pos -= table->page_size;
+    return TRUE;
+}
+
+gboolean
+ibus_lookup_table_page_down (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    gint i;
+    gint page;
+    gint page_nr;
+
+    /* cursor index in page */
+    i = table->cursor_pos % table->page_size;
+    page = table->cursor_pos  / table->page_size;
+    page_nr = (table->candidates->len + table->page_size - 1) / table->page_size;
+
+    if (page == page_nr - 1) {
+        if (!table->round)
+            return FALSE;
+
+        table->cursor_pos = i;
+        return TRUE;
+    }
+
+    table->cursor_pos += table->page_size;
+    if (table->cursor_pos > table->candidates->len - 1) {
+        table->cursor_pos = table->candidates->len - 1;
+    }
+    return TRUE;
+}
+
+gboolean
+ibus_lookup_table_cursor_up (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    if (table->cursor_pos == 0) {
+        if (!table->round)
+            return FALSE;
+
+        table->cursor_pos = table->candidates->len - 1;
+        return TRUE;
+    }
+
+    table->cursor_pos --;
+
+    return TRUE;
+}
+
+gboolean
+ibus_lookup_table_cursor_down (IBusLookupTable *table)
+{
+    g_assert (IBUS_IS_LOOKUP_TABLE (table));
+
+    if (table->cursor_pos == table->candidates->len - 1) {
+        if (!table->round)
+            return FALSE;
+
+        table->cursor_pos = 0;
+        return TRUE;
+    }
+
+    table->cursor_pos ++;
+    return TRUE;
+}
diff --git a/src/ibuslookuptable.h b/src/ibuslookuptable.h
index 62ca7d8..ede02b1 100644
--- a/src/ibuslookuptable.h
+++ b/src/ibuslookuptable.h
@@ -76,10 +76,26 @@ IBusText            *ibus_lookup_table_get_candidate
 void                 ibus_lookup_table_set_cursor_pos
                                                 (IBusLookupTable    *table,
                                                  guint               cursor_pos);
+guint                ibus_lookup_table_get_cursor_pos
+                                                (IBusLookupTable    *table);
+void                 ibus_lookup_table_set_cursor_visible
+                                                (IBusLookupTable    *table,
+                                                 gboolean            visible);
+gboolean             ibus_lookup_table_is_cursor_visible
+                                                (IBusLookupTable    *table);
+guint                ibus_lookup_table_get_cursor_in_page
+                                                (IBusLookupTable    *table);
 void                 ibus_lookup_table_set_page_size
                                                 (IBusLookupTable    *table,
                                                  guint               page_size);
+guint                ibus_lookup_table_get_page_size
+                                                (IBusLookupTable    *table);
 void                 ibus_lookup_table_clear    (IBusLookupTable    *table);
+gboolean             ibus_lookup_table_page_up  (IBusLookupTable    *table);
+gboolean             ibus_lookup_table_page_down(IBusLookupTable    *table);
+gboolean             ibus_lookup_table_cursor_up(IBusLookupTable    *table);
+gboolean             ibus_lookup_table_cursor_down
+                                                (IBusLookupTable    *table);
 G_END_DECLS
 #endif
 
diff --git a/ui/gtk/languagebar.py b/ui/gtk/languagebar.py
index 3546ef7..2a10a43 100644
--- a/ui/gtk/languagebar.py
+++ b/ui/gtk/languagebar.py
@@ -65,11 +65,11 @@ class LanguageBar(gtk.Toolbar):
 
         root = gdk.get_default_root_window()
         try:
-            workarea = root.property_get("_NET_WORKAREA")[2]
-            right, bottom = workarea[0] + workarea[2], workarea[1] + workarea[3]
+            self.__work_area = root.property_get("_NET_WORKAREA")[2]
         except:
-            right, bottom = root.get_size()
-        self.__position = right - 20, bottom - 20
+            w, h = root.get_size()
+            self.__work_area = 0, 0, w, h
+        self.__position = self.__work_area[0] + self.__work_area[2] - 20, self.__work_area[1] + self.__work_area[3] - 20
         self.__toplevel.move(*self.__position)
 
     def __create_ui(self):
@@ -106,13 +106,19 @@ class LanguageBar(gtk.Toolbar):
 
     def __toplevel_size_allocate_cb(self, toplevel, allocation):
         x, y = self.__position
-        self.__toplevel.move(x - allocation.width, y - allocation.height)
+        if x - self.__work_area[0] >= self.__work_area[2] - 80:
+            self.__toplevel.move(x - allocation.width, y - allocation.height)
 
     def __remove_properties(self):
         # reset all properties
         map(lambda i: i.destroy(), self.__properties)
         self.__properties = []
 
+    def __set_opacity(self, opacity):
+        if self.__toplevel.window == None:
+            self.__toplevel.realize()
+        self.__toplevel.window.set_opacity(opacity)
+
     def do_show(self):
         gtk.Toolbar.do_show(self)
 
@@ -128,10 +134,14 @@ class LanguageBar(gtk.Toolbar):
 
     def set_enabled(self, enabled):
         self.__enabled = enabled
-        if self.__enabled and self.__has_focus:
-            self.show_all()
-        if not self.__enabled and self.__auto_hide:
-            self.hide_all()
+        if self.__enabled:
+            self.__set_opacity(1.0)
+            if self.__has_focus:
+                self.show_all()
+        else:
+            self.__set_opacity(0.5)
+            if self.__auto_hide:
+                self.hide_all()
 
     def is_enabled(self):
         return self.__enabled
diff --git a/ui/gtk/menu.py b/ui/gtk/menu.py
index 9a3b30a..6f6c7d1 100644
--- a/ui/gtk/menu.py
+++ b/ui/gtk/menu.py
@@ -92,7 +92,7 @@ class ImageMenuItem (gtk.ImageMenuItem, PropItem):
     }
 
     def __init__ (self, prop):
-        gtk.ImageMenuItem.__init__ (self, label = prop.label)
+        gtk.ImageMenuItem.__init__ (self, label = prop.label.text)
         PropItem.__init__ (self, prop)
 
         if self._prop.icon:
@@ -128,7 +128,7 @@ class CheckMenuItem (gtk.CheckMenuItem, PropItem):
     }
 
     def __init__ (self, prop):
-        gtk.CheckMenuItem.__init__ (self, label = prop.label)
+        gtk.CheckMenuItem.__init__ (self, label = prop.label.text)
         PropItem.__init__ (self, prop)
 
         self.set_active (self._prop._state == ibus.PROP_STATE_CHECKED)
diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py
index e7850e6..d968393 100644
--- a/ui/gtk/panel.py
+++ b/ui/gtk/panel.py
@@ -74,9 +74,7 @@ class Panel(ibus.PanelBase):
 
         # add icon search path
         icon_theme = gtk.icon_theme_get_default()
-        dir = path.dirname(__file__)
-        icondir = path.join(dir, "..", "icons")
-        icon_theme.prepend_search_path(icondir)
+        icon_theme.prepend_search_path(self.__icons_dir)
 
         self.__language_bar = LanguageBar()
         self.__language_bar.connect("property-activate",
@@ -193,6 +191,7 @@ class Panel(ibus.PanelBase):
     def focus_out(self, ic):
         self.reset()
         self.__focus_ic = None
+        self.__language_bar.set_enabled(False)
         self.__language_bar.focus_out()
         self.__set_im_icon(self.__ibus_icon)
 
diff --git a/ui/gtk/toolitem.py b/ui/gtk/toolitem.py
index 0e4e4ad..09ad686 100644
--- a/ui/gtk/toolitem.py
+++ b/ui/gtk/toolitem.py
@@ -46,7 +46,7 @@ class ToolButton(gtk.ToolButton, PropItem):
             widget = icon.IconWidget(icon_name, 18)
             gtk.ToolButton.set_icon_widget(self, widget)
             self.set_is_important(False)
-        elif self._prop.label:
+        elif self._prop.label.text:
             gtk.ToolButton.set_icon_widget(self, None)
             self.set_is_important(True)
         else: