diff options
author | Huang Peng <shawn.p.huang@gmail.com> | 2008-10-01 11:58:34 +0800 |
---|---|---|
committer | Huang Peng <shawn.p.huang@gmail.com> | 2008-10-01 11:58:34 +0800 |
commit | 295919568bad10b35c9013df19f9550efa06469f (patch) | |
tree | cbc3ff110c42bcb5f464c09f494153b9a76e343b /client/x11 | |
parent | 8bd15c58cc3cb2e3b547f1ab1b415c529f5fc794 (diff) | |
download | ibus-295919568bad10b35c9013df19f9550efa06469f.tar.gz ibus-295919568bad10b35c9013df19f9550efa06469f.tar.xz ibus-295919568bad10b35c9013df19f9550efa06469f.zip |
WIP.
Diffstat (limited to 'client/x11')
-rw-r--r-- | client/x11/main.c | 194 |
1 files changed, 179 insertions, 15 deletions
diff --git a/client/x11/main.c b/client/x11/main.c index 3fd942c..1980706 100644 --- a/client/x11/main.c +++ b/client/x11/main.c @@ -63,7 +63,15 @@ struct _X11IC { gchar *lang; gboolean has_preedit_area; GdkRectangle preedit_area; + + gchar *preedit_string; + PangoAttrList *preedit_attrs; + gint preedit_cursor; + gboolean preedit_visible; + gboolean preedit_started; + gint onspot_preedit_length; }; + typedef struct _X11IC X11IC; static void _xim_set_cursor_location (X11IC *x11ic); @@ -90,30 +98,139 @@ static gint g_debug_level = 0; static IBusIMClient *_client = NULL; -#if 0 static void -_xim_preedit_start (XIMS xims, int icid, int connect_id) +_xim_preedit_start (XIMS xims, const X11IC *x11ic) { IMPreeditStateStruct ips; ips.major_code = 0; ips.minor_code = 0; - ips.icid = icid; - ips.connect_id = connect_id; + ips.icid = x11ic->icid; + ips.connect_id = x11ic->connect_id; IMPreeditStart (xims, (XPointer)&ips); } static void -_xim_preedit_end (XIMS xims, int icid, int connect_id) +_xim_preedit_end (XIMS xims, const X11IC *x11ic) { IMPreeditStateStruct ips; ips.major_code = 0; ips.minor_code = 0; - ips.icid = icid; - ips.connect_id = connect_id; + ips.icid = x11ic->icid; + ips.connect_id = x11ic->connect_id; IMPreeditEnd (xims, (XPointer)&ips); } + + +static void +_xim_preedit_callback_start (XIMS xims, const X11IC *x11ic) +{ + IMPreeditCBStruct pcb; + + pcb.major_code = XIM_PREEDIT_START; + pcb.minor_code = 0; + pcb.connect_id = x11ic->connect_id; + pcb.icid = x11ic->icid; + pcb.todo.return_value = 0; + IMCallCallback (xims, (XPointer) & pcb); +} + + +static void +_xim_preedit_callback_done (XIMS xims, const X11IC *x11ic) +{ + IMPreeditCBStruct pcb; + + pcb.major_code = XIM_PREEDIT_DONE; + pcb.minor_code = 0; + pcb.connect_id = x11ic->connect_id; + pcb.icid = x11ic->icid; + pcb.todo.return_value = 0; + IMCallCallback (xims, (XPointer) & pcb); +} + + +static void +_xim_preedit_callback_draw (XIMS xims, X11IC *x11ic, const gchar *preedit_string) +{ + IMPreeditCBStruct pcb; + XIMText text; + XTextProperty tp; + + static XIMFeedback *feedback = NULL; + static guint feedback_len = 0; + + guint i, len; + + if (preedit_string == NULL) + return; + + len = g_utf8_strlen (preedit_string, -1); + len = strlen (preedit_string); + + g_debug ("len=%d, onspot_len=%d", len, x11ic->onspot_preedit_length); + + if (len + 1 > feedback_len) { + feedback_len = (len + 1 + 63) & ~63; + // feedback_len = len + 1; + if (feedback == NULL) { + feedback = (XIMFeedback *)g_alloca (sizeof (XIMFeedback) * feedback_len); + } + else { + feedback = (XIMFeedback *)g_realloc (feedback, sizeof (XIMFeedback) * feedback_len); + } + } + + for (i = 0; i < feedback_len; i++) { + feedback[i] = XIMUnderline; + } + feedback[feedback_len] = 0; + +#if 0 + for (i = 0; i < attrs.size (); ++i) { + attr = 0; + if (attrs [i].get_type () == SCIM_ATTR_DECORATE) { + if (attrs [i].get_value () == SCIM_ATTR_DECORATE_REVERSE) + attr = XIMReverse; + else if (attrs [i].get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) + attr = XIMHighlight; + } + for (j = attrs [i].get_start (); j < attrs [i].get_end () && j < len; ++j) + feedback [j] |= attr; + } + + for (i = 0; i < len; ++i) + if (!feedback [i]) + feedback [i] = XIMUnderline; #endif + pcb.major_code = XIM_PREEDIT_DRAW; + pcb.connect_id = x11ic->connect_id; + pcb.icid = x11ic->icid; + + pcb.todo.draw.caret = len; + pcb.todo.draw.chg_first = 0; + pcb.todo.draw.chg_length = x11ic->onspot_preedit_length; + pcb.todo.draw.text = &text; + + text.feedback = feedback; + + if (len > 0) { + Xutf8TextListToTextProperty (GDK_DISPLAY (), (char **)&preedit_string, 1, XCompoundTextStyle, &tp); + text.encoding_is_wchar = 0; + text.length = strlen ((char*)tp.value); + text.string.multi_byte = (char*)tp.value; + IMCallCallback (xims, (XPointer) & pcb); + XFree (tp.value); + } else { + text.encoding_is_wchar = 0; + text.length = 0; + text.string.multi_byte = ""; + IMCallCallback (xims, (XPointer) & pcb); + len = 0; + } + x11ic->onspot_preedit_length = len; +} + int _xim_store_ic_values (X11IC *x11ic, IMChangeICStruct *call_data) { @@ -195,7 +312,7 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data) g_hash_table_insert (_ibus_ic_table, x11ic->ibus_ic, (gpointer)x11ic); - ibus_im_client_set_capabilities (_client, x11ic->ibus_ic, IBUS_CAP_FOCUS); + ibus_im_client_set_capabilities (_client, x11ic->ibus_ic, IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT); g_hash_table_insert (_x11_ic_table, (gpointer)x11ic->icid, (gpointer)x11ic); x11ic->conn->clients = g_list_append (x11ic->conn->clients, (gpointer)x11ic); @@ -542,12 +659,10 @@ _client_commit_string_cb (IBusIMClient *client, const gchar *ic, const gchar *st X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); g_return_if_fail (x11ic != NULL); - char *clist[1]; XTextProperty tp; IMCommitStruct cms = {0}; - clist[0] = (gchar *)string; - Xutf8TextListToTextProperty (GDK_DISPLAY (), clist, 1, XCompoundTextStyle, &tp); + Xutf8TextListToTextProperty (GDK_DISPLAY (), (char **)&string, 1, XCompoundTextStyle, &tp); cms.major_code = XIM_COMMIT; cms.icid = x11ic->icid; @@ -569,33 +684,84 @@ _client_forward_event_cb (IBusIMClient *client, const gchar *ic, GdkEvent *event _xim_forward_gdk_event (&(event->key), x11ic); } -#if 0 +static void +_update_preedit (X11IC *x11ic) +{ + if (x11ic->preedit_visible == FALSE && x11ic->preedit_started == TRUE) { + _xim_preedit_callback_draw (_xims, x11ic, ""); + _xim_preedit_callback_done (_xims, x11ic); + x11ic->preedit_started = FALSE; + } + + if (x11ic->preedit_visible == TRUE && x11ic->preedit_started == FALSE) { + _xim_preedit_callback_start (_xims, x11ic); + x11ic->preedit_started = TRUE; + } + if (x11ic->preedit_visible == TRUE) { + _xim_preedit_callback_draw (_xims, x11ic, x11ic->preedit_string); + } +} + static void _client_update_preedit_cb (IBusIMClient *client, const gchar *ic, const gchar *string, PangoAttrList *attrs, gint cursor_pos, gboolean visible, gpointer user_data) { + X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); + g_return_if_fail (x11ic != NULL); + + if (x11ic->preedit_string) { + g_free(x11ic->preedit_string); + } + x11ic->preedit_string = g_strdup(string); + + if (x11ic->preedit_attrs) { + pango_attr_list_unref (x11ic->preedit_attrs); + } + x11ic->preedit_attrs = pango_attr_list_ref(attrs); + + x11ic->preedit_cursor = cursor_pos; + x11ic->preedit_visible = visible; + + _update_preedit (x11ic); } static void _client_show_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) { + X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); + g_return_if_fail (x11ic != NULL); + + x11ic->preedit_visible = TRUE; + _update_preedit (x11ic); } static void _client_hide_preedit_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) { + X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); + g_return_if_fail (x11ic != NULL); + + x11ic->preedit_visible = FALSE; + _update_preedit (x11ic); } static void _client_enabled_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) { + X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); + g_return_if_fail (x11ic != NULL); + + _xim_preedit_start (_xims, x11ic); } static void _client_disabled_cb (IBusIMClient *client, const gchar *ic, gpointer user_data) { + X11IC *x11ic = g_hash_table_lookup (_ibus_ic_table, ic); + g_return_if_fail (x11ic != NULL); + + _xim_preedit_end (_xims, x11ic); } -#endif static void _init_ibus_client (void) @@ -623,7 +789,6 @@ _init_ibus_client (void) g_signal_connect (_client, "forward-event", G_CALLBACK (_client_forward_event_cb), NULL); -#if 0 g_signal_connect (_client, "update-preedit", G_CALLBACK (_client_update_preedit_cb), NULL); g_signal_connect (_client, "show-preedit", @@ -634,7 +799,6 @@ _init_ibus_client (void) G_CALLBACK (_client_enabled_cb), NULL); g_signal_connect (_client, "disabled", G_CALLBACK (_client_disabled_cb), NULL); -#endif } static void |