This commit is contained in:
Huang Peng 2008-07-16 16:53:51 +08:00
Родитель 193650d386
Коммит a1f880ae4c
5 изменённых файлов: 383 добавлений и 309 удалений

Просмотреть файл

@ -9,7 +9,7 @@
*
* 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
* 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
@ -22,47 +22,51 @@
#include <string.h>
#include <stdio.h>
#include "ibusimclient.h"
#include "ibusimcontext.h"
#define IBUS_LOCALDIR ""
static const GtkIMContextInfo ibus_im_info = {
"ibus",
"The Input Bus",
"ibus",
IBUS_LOCALDIR,
""
"ibus",
"The Input Bus",
"ibus",
IBUS_LOCALDIR,
""
};
static const GtkIMContextInfo * info_list[] = {
&ibus_im_info
&ibus_im_info
};
IBusIMClient *_client = NULL;
void
im_module_init (GTypeModule *type_module)
{
ibus_im_client_register_type(type_module);
ibus_im_context_register_type(type_module);
ibus_im_client_register_type(type_module);
ibus_im_context_register_type(type_module);
_client = ibus_im_client_new ();
}
void
im_module_exit (void)
{
g_object_unref (_client);
}
GtkIMContext *
im_module_create (const gchar *context_id)
{
if (strcmp (context_id, "ibus") == 0)
return ibus_im_context_new ();
return NULL;
if (strcmp (context_id, "ibus") == 0)
return ibus_im_client_create_im_context (_client);
return NULL;
}
void
im_module_list (const GtkIMContextInfo ***contexts,
int *n_contexts)
{
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
*contexts = info_list;
*n_contexts = G_N_ELEMENTS (info_list);
}

Просмотреть файл

@ -52,38 +52,25 @@ struct _IBusIMClientPrivate {
#ifdef HAVE_INOTIFY
/* inotify */
gint inotify_wd;
GIOChannel *inotify_channel;
GIOChannel *inotify_channel;
guint inotify_source;
#endif
DBusConnection *ibus;
gboolean enable;
DBusConnection *ibus;
GtkIMContext *context;
gchar *ic;
/* preedit status */
gchar *preedit_string;
PangoAttrList *preedit_attrs;
gint preedit_cursor;
gboolean preedit_show;
GHashTable *ic_table;
GList *contexts;
};
/* functions prototype */
static void ibus_im_client_class_init (IBusIMClientClass *klass);
static void ibus_im_client_init (IBusIMClient *client);
static void ibus_im_client_finalize (GObject *obj);
static void ibus_im_client_class_init (IBusIMClientClass *klass);
static void ibus_im_client_init (IBusIMClient *client);
static void ibus_im_client_finalize (GObject *obj);
static void ibus_im_client_commit_string(IBusIMClient *client,
const gchar *string);
static void ibus_im_client_update_preedit
(IBusIMClient *client,
const gchar *string,
PangoAttrList *attrs,
gint cursor_pos,
gboolean show);
static const gchar *
_ibus_im_client_create_input_context
(IBusIMClient *client);
static void ibus_im_client_sync_hotkeys (IBusIMClient *client);
static gboolean _ibus_call_with_reply_and_block
(DBusConnection *connection,
const gchar *method,
@ -103,25 +90,28 @@ static gboolean _dbus_call_with_reply_and_block
const gchar *path,
const gchar *iface,
const char *method,
int first_arg_type,
int first_arg_type,
...);
static GtkIMContext *
_ibus_client_ic_to_context (IBusIMClient *client,
const gchar *ic);
/* callback functions */
static DBusHandlerResult
_ibus_im_client_message_filter_cb
(DBusConnection *connection,
DBusMessage *message,
void *user_data);
(DBusConnection *connection,
DBusMessage *message,
void *user_data);
static void _dbus_name_owner_changed_cb (DBusGProxy *proxy,
const gchar *name,
const gchar *old_name,
const gchar *new_name,
IBusIMClient *client);
static void _dbus_name_owner_changed_cb
(DBusGProxy *proxy,
const gchar *name,
const gchar *old_name,
const gchar *new_name,
IBusIMClient *client);
static GType ibus_type_im_client = 0;
static GtkObjectClass *parent_class = NULL;
static IBusIMClient *_client = NULL;
static gboolean has_focus = FALSE;
@ -157,22 +147,16 @@ ibus_im_client_register_type (GTypeModule *type_module)
}
}
IBusIMClient *
ibus_im_client_get_client (void)
ibus_im_client_new (void)
{
if (_client == NULL) {
_client = IBUS_IM_CLIENT(g_object_new (IBUS_TYPE_IM_CLIENT, NULL));
g_object_ref_sink (_client);
}
else {
g_object_ref (_client);
}
IBusIMClient *client;
return _client;
client = IBUS_IM_CLIENT(g_object_new (IBUS_TYPE_IM_CLIENT, NULL));
return client;
}
static void
ibus_im_client_class_init (IBusIMClientClass *klass)
{
@ -221,7 +205,6 @@ _ibus_im_client_reinit_imm (IBusIMClient *client)
return;
}
ibus_im_client_sync_hotkeys (client);
g_debug ("new imm %s", dbus_g_proxy_get_bus_name (priv->imm));
}
#endif
@ -289,6 +272,61 @@ _ibus_im_client_ibus_open (IBusIMClient *client)
return;
}
dbus_connection_setup_with_g_main (priv->ibus, NULL);
GList *p;
for (p = priv->contexts; p != NULL; p = g_list_next (p)) {
IBusIMContext *ctx = IBUS_IM_CONTEXT (p->data);
const gchar *ic = _ibus_im_client_create_input_context (client);
ibus_im_context_set_ic (ctx, ic);
}
}
static void
_ibus_im_client_ibus_close (IBusIMClient *client)
{
IBusIMClientPrivate *priv = client->priv;
GList *p;
for (p = priv->contexts; p != NULL; p = g_list_next (p)) {
IBusIMContext *ctx = IBUS_IM_CONTEXT (p->data);
ibus_im_context_set_ic (ctx, NULL);
}
g_hash_table_remove_all (priv->ic_table);
if (priv->ibus) {
dbus_connection_close (priv->ibus);
dbus_connection_unref (priv->ibus);
priv->ibus = NULL;
}
}
IBusIMContext *
ibus_im_client_create_im_context (IBusIMClient *client)
{
IBusIMContext *context;
IBusIMClientPrivate *priv = client->priv;
context = IBUS_IM_CONTEXT (ibus_im_context_new ());
priv->contexts = g_list_append (priv->contexts, context);
const gchar *ic = _ibus_im_client_create_input_context (client);
ibus_im_context_set_ic (context, ic);
if (ic) {
g_hash_table_insert (priv->ic_table, (gpointer)g_strdup (ic), context);
}
return context;
}
static const gchar *
_ibus_im_client_create_input_context (IBusIMClient *client)
{
IBusIMClientPrivate *priv = client->priv;
if (priv->ibus == NULL)
return NULL;
const gchar *app_name = g_get_application_name ();
gchar *ic = NULL;
_ibus_call_with_reply_and_block (priv->ibus, "CreateInputContext",
@ -296,38 +334,7 @@ _ibus_im_client_ibus_open (IBusIMClient *client)
DBUS_TYPE_INVALID,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID);
priv->ic = g_strdup (ic);
}
static void
_ibus_im_client_ibus_close (IBusIMClient *client)
{
DBusError error;
IBusIMClientPrivate *priv = client->priv;
if (priv->ibus) {
dbus_connection_close (priv->ibus);
dbus_connection_unref (priv->ibus);
priv->ibus = NULL;
}
if (priv->preedit_string) {
g_free (priv->preedit_string);
priv->preedit_string = NULL;
}
if (priv->preedit_attrs) {
pango_attr_list_unref (priv->preedit_attrs);
priv->preedit_attrs = NULL;
}
if (priv->context) {
g_signal_emit_by_name (priv->context, "preedit-changed");
}
priv->enable = FALSE;
return ic;
}
#ifdef HAVE_INOTIFY
@ -385,12 +392,8 @@ ibus_im_client_init (IBusIMClient *obj)
priv = G_TYPE_INSTANCE_GET_PRIVATE (client, IBUS_TYPE_IM_CLIENT, IBusIMClientPrivate);
client->priv = priv;
priv->context = NULL;
priv->preedit_string = NULL;
priv->preedit_attrs = NULL;
priv->preedit_cursor = 0;
priv->enable = FALSE;
priv->ic_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
priv->contexts = NULL;
watch_path = g_strdup_printf ("/tmp/ibus-%s", g_get_user_name ());
@ -513,54 +516,31 @@ ibus_im_client_finalize (GObject *obj)
}
void
ibus_im_client_set_im_context (IBusIMClient *client, GtkIMContext *context)
{
IBusIMClientPrivate *priv = client->priv;
priv->context = context;
}
GtkIMContext *
ibus_im_client_get_im_context (IBusIMClient *client)
{
IBusIMClientPrivate *priv = client->priv;
return priv->context;
}
static void
ibus_im_client_commit_string (IBusIMClient *client, const gchar *string)
ibus_im_client_commit_string (IBusIMClient *client, const gchar *ic, const gchar *string)
{
IBusIMClientPrivate *priv = client->priv;
IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic);
if (priv->context) {
g_signal_emit_by_name (priv->context, "commit", string);
if (context == NULL) {
g_debug ("Can not find context assocate with ic(%s)", ic);
return;
}
g_signal_emit_by_name (G_OBJECT (context), "commit", string);
}
static void
ibus_im_client_update_preedit (IBusIMClient *client, const gchar *string,
ibus_im_client_update_preedit (IBusIMClient *client, const gchar *ic, const gchar *string,
PangoAttrList *attrs, gint cursor_pos, gboolean show)
{
IBusIMClientPrivate *priv = client->priv;
if (priv->preedit_string) {
g_free (priv->preedit_string);
}
priv->preedit_string = g_strdup (string);
IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic);
if (priv->preedit_attrs) {
pango_attr_list_unref (priv->preedit_attrs);
}
priv->preedit_attrs = attrs;
if (attrs) {
pango_attr_list_ref (priv->preedit_attrs);
}
priv->preedit_cursor = cursor_pos;
priv->preedit_show = show;
if (priv->context) {
g_signal_emit_by_name (priv->context, "preedit-changed");
if (context == NULL) {
g_debug ("Can not find context assocate with ic(%s)", ic);
return;
}
ibus_im_context_update_preedit (context, string, attrs, cursor_pos, show);
}
static void
@ -580,11 +560,12 @@ _ibus_signal_commit_string_handler (DBusConnection *connection, DBusMessage *mes
dbus_error_free (&error);
}
else {
if (g_strcmp0 (priv->ic, ic) != 0) {
g_warning ("ic is wrong!");
IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic);
if (context == NULL) {
g_debug ("Can not find context assocate with ic(%s)", ic);
return;
}
ibus_im_client_commit_string (client, string);
ibus_im_context_commit_string (context, string);
}
}
@ -616,11 +597,6 @@ _ibus_signal_update_preedit_handler (DBusConnection *connection, DBusMessage *me
dbus_message_iter_get_basic (&iter, &ic);
dbus_message_iter_next (&iter);
if (g_strcmp0 (priv->ic, ic) != 0) {
g_warning ("ic is wrong!");
return;
}
type = dbus_message_iter_get_arg_type (&iter);
if (type != DBUS_TYPE_STRING) {
g_warning ("The 2nd argument of UpdatePreedit signal must be a String");
@ -717,7 +693,14 @@ _ibus_signal_update_preedit_handler (DBusConnection *connection, DBusMessage *me
dbus_message_iter_get_basic (&iter, &show);
dbus_message_iter_next (&iter);
ibus_im_client_update_preedit (client, string, attrs, cursor, show);
{
IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic);
if (context == NULL) {
g_debug ("Can not find context assocate with ic(%s)", ic);
return;
}
ibus_im_context_update_preedit (context, string, attrs, cursor, show);
}
pango_attr_list_unref (attrs);
}
@ -765,7 +748,25 @@ static void
_ibus_signal_enabled_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client)
{
DEBUG_FUNCTION_IN;
client->priv->enable = TRUE;
/* Handle CommitString signal */
IBusIMClientPrivate *priv = client->priv;
DBusError error = {0};
gchar *ic = NULL;
if (!dbus_message_get_args (message, &error,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID)) {
g_warning ("%s", error.message);
dbus_error_free (&error);
}
else {
IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic);
if (context == NULL) {
g_debug ("Can not find context assocate with ic(%s)", ic);
return;
}
ibus_im_context_enable (context);
}
}
@ -773,8 +774,28 @@ static void
_ibus_signal_disabled_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client)
{
DEBUG_FUNCTION_IN;
client->priv->enable = FALSE;
/* Handle CommitString signal */
IBusIMClientPrivate *priv = client->priv;
DBusError error = {0};
gchar *ic = NULL;
if (!dbus_message_get_args (message, &error,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID)) {
g_warning ("%s", error.message);
dbus_error_free (&error);
}
else {
IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic);
if (context == NULL) {
g_debug ("Can not find context assocate with ic(%s)", ic);
return;
}
ibus_im_context_disable (context);
}
}
static DBusHandlerResult
_ibus_im_client_message_filter_cb (DBusConnection *connection, DBusMessage *message, void *user_data)
{
@ -1048,9 +1069,11 @@ _ibus_filter_keypress_reply_cb (DBusPendingCall *pending, void *user_data)
}
gboolean
ibus_im_client_filter_keypress (IBusIMClient *client, GdkEventKey *event)
ibus_im_client_filter_keypress (IBusIMClient *client, IBusIMContext *context, GdkEventKey *event)
{
IBusIMClientPrivate *priv = client->priv;
gchar *ic = ibus_im_context_get_ic (context);
g_return_val_if_fail (ic != NULL, FALSE);
guint state = event->state & GDK_MODIFIER_MASK;
gboolean is_press = event->type == GDK_KEY_PRESS;
@ -1065,7 +1088,7 @@ ibus_im_client_filter_keypress (IBusIMClient *client, GdkEventKey *event)
_ibus_filter_keypress_reply_cb,
gdk_event_copy ((GdkEvent *)event),
(DBusFreeFunction)gdk_event_free,
DBUS_TYPE_STRING, &priv->ic,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_UINT32, &event->keyval,
DBUS_TYPE_BOOLEAN, &is_press,
DBUS_TYPE_UINT32, &state,
@ -1077,96 +1100,62 @@ ibus_im_client_filter_keypress (IBusIMClient *client, GdkEventKey *event)
void
ibus_im_client_focus_in (IBusIMClient *client)
ibus_im_client_focus_in (IBusIMClient *client, IBusIMContext *context)
{
IBusIMClientPrivate *priv = client->priv;
gchar *ic = ibus_im_context_get_ic (context);
g_return_if_fail (ic != NULL);
/* Call IBus FocusIn method */
_ibus_call_with_reply_and_block (client->priv->ibus,
_ibus_call_with_reply_and_block (priv->ibus,
"FocusIn",
DBUS_TYPE_STRING, &priv->ic,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID,
DBUS_TYPE_INVALID);
}
void
ibus_im_client_focus_out (IBusIMClient *client)
ibus_im_client_focus_out (IBusIMClient *client, IBusIMContext *context)
{
IBusIMClientPrivate *priv = client->priv;
gchar *ic = ibus_im_context_get_ic (context);
g_return_if_fail (ic != NULL);
/* Call IBus FocusOut method */
_ibus_call_with_reply_and_block (client->priv->ibus,
_ibus_call_with_reply_and_block (priv->ibus,
"FocusOut",
DBUS_TYPE_STRING, &priv->ic,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID,
DBUS_TYPE_INVALID);
}
void
ibus_im_client_reset (IBusIMClient *client)
ibus_im_client_reset (IBusIMClient *client, IBusIMContext *context)
{
IBusIMClientPrivate *priv = client->priv;
gchar *ic = ibus_im_context_get_ic (context);
g_return_if_fail (ic != NULL);
/* Call IBus Reset method */
_ibus_call_with_reply_and_block (client->priv->ibus,
_ibus_call_with_reply_and_block (priv->ibus,
"Reset",
DBUS_TYPE_STRING, &priv->ic,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID,
DBUS_TYPE_INVALID);
}
gboolean
ibus_im_client_get_preedit_string (
IBusIMClient *client,
gchar **str,
PangoAttrList **attrs,
gint *cursor_pos
)
{
IBusIMClientPrivate *priv = client->priv;
if (!priv->preedit_show) {
if (str) *str = g_strdup ("");
if (attrs) *attrs = pango_attr_list_new ();
if (cursor_pos) *cursor_pos = 0;
return TRUE;
}
if (str) {
*str = g_strdup (priv->preedit_string ? priv->preedit_string: "");
}
if (attrs) {
if (priv->preedit_attrs) {
*attrs = pango_attr_list_ref (priv->preedit_attrs);
}
else {
*attrs = pango_attr_list_new ();
}
}
if (cursor_pos) {
*cursor_pos = priv->preedit_cursor;
}
return TRUE;
}
void
ibus_im_client_set_client_window (IBusIMClient *client, GdkWindow *window)
{
IBusIMClientPrivate *priv = client->priv;
}
void
ibus_im_client_set_cursor_location (IBusIMClient *client, GdkRectangle *area)
ibus_im_client_set_cursor_location (IBusIMClient *client, IBusIMContext *context, GdkRectangle *area)
{
IBusIMClientPrivate *priv = client->priv;
gchar *ic = ibus_im_context_get_ic (context);
g_return_if_fail (ic != NULL);
_ibus_call_with_reply_and_block (client->priv->ibus,
"SetCursorLocation",
DBUS_TYPE_STRING, &priv->ic,
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INT32, &area->x,
DBUS_TYPE_INT32, &area->y,
DBUS_TYPE_INT32, &area->width,
@ -1176,43 +1165,22 @@ ibus_im_client_set_cursor_location (IBusIMClient *client, GdkRectangle *area)
}
gboolean
ibus_im_client_is_enabled (IBusIMClient *client)
void
ibus_im_client_release_im_context (IBusIMClient *client, IBusIMContext *context)
{
return (client->priv->ibus != NULL) && (client->priv->enable);
}
static void
ibus_im_client_sync_hotkeys (IBusIMClient *client)
{
GError *error;
gchar **hotkeys = NULL;
gint i;
IBusIMClientPrivate *priv = client->priv;
#if 0
g_return_if_fail (priv->imm != NULL);
gchar *ic = ibus_im_context_get_ic (context);
priv->contexts = g_list_remove (priv->contexts, context);
if (ic) {
g_hash_table_remove (priv->ic_table, ic);
_ibus_call_with_reply_and_block (priv->ibus, "ReleaseInputContext",
DBUS_TYPE_STRING, &ic,
DBUS_TYPE_INVALID,
DBUS_TYPE_INVALID);
error = NULL;
if (!dbus_g_proxy_call (priv->imm, "get_hotkeys", &error,
G_TYPE_INVALID,
G_TYPE_STRV, &hotkeys,
G_TYPE_INVALID)) {
if (error) {
g_warning ("%s", error->message);
g_error_free (error);
}
return;
}
for (i = 0; i < g_strv_length (hotkeys); i++) {
g_debug ("hotkeys[%d] = %s", i, hotkeys[i]);
}
g_strfreev (hotkeys);
#endif
}
/* Callback functions for slave context */
#if 0
static void

Просмотреть файл

@ -21,7 +21,7 @@
#define __IBUS_IM_CLIENT_H_
#include <gtk/gtk.h>
#include "ibusimcontext.h"
/*
* Type macros.
*/
@ -42,7 +42,7 @@
#if 0
#define DEBUG_FUNCTION_IN g_debug("%s IN", __FUNCTION__);
#define DEBUG_FUNCTION_OUT g_debug("%s OUT", __FUNCTION__);
#define DEBUG_FUNCTION_OUT g_debug("%s OUT", __FUNCTION__);
#else
#define DEBUG_FUNCTION_IN
#define DEBUG_FUNCTION_OUT
@ -70,27 +70,29 @@ struct _IBusIMClientClass {
/* class members */
};
extern IBusIMClient *_client;
GType ibus_im_client_get_type (void);
IBusIMClient *ibus_im_client_get_client (void);
void ibus_im_client_register_type (GTypeModule *type_module);
void ibus_im_client_register_type (GTypeModule *type_module);
IBusIMClient *ibus_im_client_new (void);
IBusIMContext *ibus_im_client_create_im_context (IBusIMClient *client);
void ibus_im_client_shutdown (void);
void ibus_im_client_focus_in (IBusIMClient *client);
void ibus_im_client_focus_out (IBusIMClient *client);
void ibus_im_client_set_im_context (IBusIMClient *client,
GtkIMContext *context);
GtkIMContext *ibus_im_client_get_im_context (IBusIMClient *client);
void ibus_im_client_reset (IBusIMClient *client);
void ibus_im_client_focus_in (IBusIMClient *client,
IBusIMContext *context);
void ibus_im_client_focus_out (IBusIMClient *client,
IBusIMContext *context);
void ibus_im_client_reset (IBusIMClient *client,
IBusIMContext *context);
gboolean ibus_im_client_filter_keypress (IBusIMClient *client,
GdkEventKey *key);
gboolean ibus_im_client_get_preedit_string
(IBusIMClient *client,
gchar **str,
PangoAttrList **attrs,
gint *cursor_pos);
IBusIMContext *context,
GdkEventKey *key);
void ibus_im_client_set_cursor_location
(IBusIMClient *client,
GdkRectangle *area);
(IBusIMClient *client,
IBusIMContext *context,
GdkRectangle *area);
gboolean ibus_im_client_is_enabled (IBusIMClient *client);
void ibus_im_client_release_im_context(IBusIMClient *client,
IBusIMContext *context);
G_END_DECLS

Просмотреть файл

@ -26,27 +26,20 @@
#include "ibusimcontext.h"
#include "ibusimclient.h"
/* define GOBJECT macros */
#define IBUS_TYPE_IM_CONTEXT \
(_ibus_type_im_context)
#define IBUS_IM_CONTEXT(obj) \
(GTK_CHECK_CAST ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContext))
#define IBUS_IM_CONTEXT_CLASS(klass) \
(GTK_CHECK_CLASS_CAST ((klass), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass))
#define IBUS_IS_IM_CONTEXT(obj) \
(GTK_CHECK_TYPE ((obj), IBUS_TYPE_IM_CONTEXT))
#define IBUS_IS_IM_CONTEXT_CLASS(klass) \
(GTK_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_IM_CONTEXT))
#define IBUS_IM_CONTEXT_GET_CLASS(obj) \
(GTK_CHECK_GET_CLASS ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass))
#define CURRENT_CONTEXT (ibus_im_client_get_im_context (priv->client))
/* IBusIMContextPriv */
struct _IBusIMContextPrivate {
GtkIMContext *slave;
IBusIMClient *client;
GdkWindow *client_window;
/* enabled */
gboolean enable;
gchar *ic;
/* preedit status */
gchar *preedit_string;
PangoAttrList *preedit_attrs;
gint preedit_cursor_pos;
gboolean preedit_visible;
};
@ -93,7 +86,7 @@ static void _slave_delete_surrounding_cb
static GType _ibus_type_im_context = 0;
GType _ibus_type_im_context = 0;
static GtkIMContextClass *parent_class = NULL;
void
@ -158,10 +151,20 @@ ibus_im_context_init (IBusIMContext *obj)
GError *error;
IBusIMContext *ibus = IBUS_IM_CONTEXT (obj);
ibus->priv = G_TYPE_INSTANCE_GET_PRIVATE (ibus, IBUS_TYPE_IM_CONTEXT, IBusIMContextPrivate);
IBusIMContextPrivate *priv = ibus->priv =
G_TYPE_INSTANCE_GET_PRIVATE (ibus, IBUS_TYPE_IM_CONTEXT, IBusIMContextPrivate);
priv->client_window = NULL;
// Init ibus status
priv->enable = FALSE;
// Init preedit status
priv->preedit_string = NULL;
priv->preedit_attrs = NULL;
priv->preedit_cursor_pos = 0;
priv->preedit_visible = FALSE;
ibus->priv->client = ibus_im_client_get_client ();
ibus->priv->client_window = NULL;
// Create slave im context
ibus->priv->slave = gtk_im_context_simple_new ();
@ -187,13 +190,13 @@ ibus_im_context_finalize (GObject *obj)
IBusIMContext *ibus = IBUS_IM_CONTEXT (obj);
IBusIMContextPrivate *priv = ibus->priv;
if (GTK_IM_CONTEXT (ibus) == CURRENT_CONTEXT) {
ibus_im_client_focus_out (priv->client);
ibus_im_client_set_im_context (priv->client, NULL);
}
ibus_im_client_release_im_context (_client, ibus);
g_object_unref (priv->slave);
g_object_unref (priv->client);
// release preedit
if (priv->preedit_string) g_free (priv->preedit_string);
if (priv->preedit_attrs) pango_attr_list_unref (priv->preedit_attrs);
G_OBJECT_CLASS(parent_class)->finalize (obj);
}
@ -207,12 +210,10 @@ ibus_im_context_filter_keypress (GtkIMContext *context,
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
if (context != CURRENT_CONTEXT)
return FALSE;
if (ibus_im_client_filter_keypress (priv->client, event))
if (ibus_im_client_filter_keypress (_client, ibus, event))
return TRUE;
return gtk_im_context_filter_keypress (priv->slave, event);
else
return gtk_im_context_filter_keypress (priv->slave, event);
}
static void
@ -223,12 +224,7 @@ ibus_im_context_focus_in (GtkIMContext *context)
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
if (context != CURRENT_CONTEXT) {
ibus_im_client_focus_out (priv->client);
ibus_im_client_set_im_context (priv->client, context);
}
ibus_im_client_focus_in (priv->client);
ibus_im_client_focus_in (_client, ibus);
gtk_im_context_focus_in (priv->slave);
}
@ -240,7 +236,7 @@ ibus_im_context_focus_out (GtkIMContext *context)
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
ibus_im_client_focus_out (priv->client);
ibus_im_client_focus_out (_client, ibus);
gtk_im_context_focus_out (priv->slave);
}
@ -252,9 +248,7 @@ ibus_im_context_reset (GtkIMContext *context)
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
if (context == CURRENT_CONTEXT) {
ibus_im_client_reset (priv->client);
}
ibus_im_client_reset (_client, ibus);
gtk_im_context_reset (priv->slave);
}
@ -270,12 +264,31 @@ ibus_im_context_get_preedit_string (GtkIMContext *context,
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
if (context == CURRENT_CONTEXT &&
ibus_im_client_is_enabled (priv->client)) {
ibus_im_client_get_preedit_string (priv->client, str, attrs, cursor_pos);
return;
if (priv->enable) {
if (priv->preedit_visible) {
if (str) {
*str = g_strdup (priv->preedit_string ? priv->preedit_string: "");
}
if (attrs) {
*attrs = priv->preedit_attrs ?
pango_attr_list_ref (priv->preedit_attrs):
pango_attr_list_new ();
}
if (cursor_pos) {
*cursor_pos = priv->preedit_cursor_pos;
}
}
else {
if (str) *str = g_strdup ("");
if (attrs) *attrs = pango_attr_list_new ();
if (cursor_pos) *cursor_pos = 0;
}
}
else {
gtk_im_context_get_preedit_string (priv->slave, str, attrs, cursor_pos);
}
gtk_im_context_get_preedit_string (ibus->priv->slave, str, attrs, cursor_pos);
}
@ -286,8 +299,9 @@ ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client)
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
priv->client_window = client;
gtk_im_context_set_client_window (ibus->priv->slave, client);
gtk_im_context_set_client_window (priv->slave, client);
}
static void
@ -297,7 +311,8 @@ ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area)
IBusIMContext *ibus = IBUS_IM_CONTEXT (context);
IBusIMContextPrivate *priv = ibus->priv;
if (context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) {
if (priv->enable) {
/* It is the focused context */
gint x, y;
if(priv->client_window) {
@ -305,7 +320,7 @@ ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area)
area->x += x;
area->y += y;
}
ibus_im_client_set_cursor_location (priv->client, area);
ibus_im_client_set_cursor_location (_client, ibus, area);
}
gtk_im_context_set_cursor_location (priv->slave, area);
}
@ -318,7 +333,7 @@ _slave_commit_cb (GtkIMContext *slave, gchar *string, IBusIMContext *context)
IBusIMContextPrivate *priv = context->priv;
#if 0
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client))
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (_client))
return;
#endif
g_signal_emit_by_name (context, "commit", string);
@ -329,8 +344,10 @@ _slave_preedit_changed_cb (GtkIMContext *slave, IBusIMContext *context)
{
DEBUG_FUNCTION_IN;
IBusIMContextPrivate *priv = context->priv;
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client))
if (priv->enable && priv->ic)
return;
g_signal_emit_by_name (context, "preedit-changed");
}
@ -339,7 +356,8 @@ _slave_preedit_start_cb (GtkIMContext *slave, IBusIMContext *context)
{
DEBUG_FUNCTION_IN;
IBusIMContextPrivate *priv = context->priv;
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client))
if (priv->enable && priv->ic)
return;
g_signal_emit_by_name (context, "preedit-start");
}
@ -349,7 +367,8 @@ _slave_preedit_end_cb (GtkIMContext *slave, IBusIMContext *context)
{
DEBUG_FUNCTION_IN;
IBusIMContextPrivate *priv = context->priv;
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client))
if (priv->enable && priv->ic)
return;
g_signal_emit_by_name (context, "preedit-end");
}
@ -359,7 +378,8 @@ _slave_retrieve_surrounding_cb (GtkIMContext *slave, IBusIMContext *context)
{
DEBUG_FUNCTION_IN;
IBusIMContextPrivate *priv = context->priv;
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client))
if (priv->enable && priv->ic)
return;
g_signal_emit_by_name (context, "retrieve-surrounding");
}
@ -369,8 +389,58 @@ _slave_delete_surrounding_cb (GtkIMContext *slave, gint a1, gint a2, IBusIMConte
{
DEBUG_FUNCTION_IN;
IBusIMContextPrivate *priv = context->priv;
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client))
if (priv->enable && priv->ic)
return;
g_signal_emit_by_name (context, "delete-surrounding", a1, a2);
}
gchar *
ibus_im_context_get_ic (IBusIMContext *context)
{
IBusIMContextPrivate *priv = context->priv;
return priv->ic;
}
void
ibus_im_context_set_ic (IBusIMContext *context, const gchar *ic)
{
IBusIMContextPrivate *priv = context->priv;
if (priv->ic) g_free (priv->ic);
priv->ic = g_strdup (ic);
}
void
ibus_im_context_enable (IBusIMContext *context)
{
IBusIMContextPrivate *priv = context->priv;
priv->enable = TRUE;
}
void
ibus_im_context_disable (IBusIMContext *context)
{
IBusIMContextPrivate *priv = context->priv;
priv->enable = FALSE;
}
void
ibus_im_context_commit_string (IBusIMContext *context, const gchar *string)
{
g_signal_emit_by_name (context, "commit", string);
}
void
ibus_im_context_update_preedit (IBusIMContext *context, const gchar *string,
PangoAttrList *attrs, gint cursor_pos, gboolean show)
{
IBusIMContextPrivate *priv = context->priv;
priv->preedit_string = g_strdup (string);
priv->preedit_attrs = pango_attr_list_ref (attrs);
priv->preedit_cursor_pos = cursor_pos;
priv->preedit_visible = show;
g_signal_emit_by_name (context, "preedit-changed");
}

Просмотреть файл

@ -25,6 +25,18 @@
/*
* Type macros.
*/
#define IBUS_TYPE_IM_CONTEXT \
(_ibus_type_im_context)
#define IBUS_IM_CONTEXT(obj) \
(GTK_CHECK_CAST ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContext))
#define IBUS_IM_CONTEXT_CLASS(klass) \
(GTK_CHECK_CLASS_CAST ((klass), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass))
#define IBUS_IS_IM_CONTEXT(obj) \
(GTK_CHECK_TYPE ((obj), IBUS_TYPE_IM_CONTEXT))
#define IBUS_IS_IM_CONTEXT_CLASS(klass) \
(GTK_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_IM_CONTEXT))
#define IBUS_IM_CONTEXT_GET_CLASS(obj) \
(GTK_CHECK_GET_CLASS ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass))
G_BEGIN_DECLS
typedef struct _IBusIMContext IBusIMContext;
@ -42,10 +54,28 @@ struct _IBusIMContextClass {
/* class members */
};
GtkIMContext *ibus_im_context_new (void);
void ibus_im_context_register_type (GTypeModule *type_module);
void ibus_im_context_shutdown (void);
extern GType _ibus_type_im_context;
GtkIMContext
*ibus_im_context_new (void);
void ibus_im_context_register_type
(GTypeModule *type_module);
void ibus_im_context_shutdown
(void);
gchar *ibus_im_context_get_ic (IBusIMContext *context);
void ibus_im_context_set_ic (IBusIMContext *context,
const gchar *ic);
void ibus_im_context_enable (IBusIMContext *context);
void ibus_im_context_disable (IBusIMContext *context);
void ibus_im_context_commit_string
(IBusIMContext *context,
const gchar *string);
void ibus_im_context_update_preedit
(IBusIMContext *context,
const gchar *string,
PangoAttrList *attrs,
gint cursor_pos,
gboolean show);
G_END_DECLS
#endif