[uim-commit] r3001 - trunk/gtk
ekato at freedesktop.org
ekato at freedesktop.org
Fri Jan 27 00:34:35 PST 2006
Author: ekato
Date: 2006-01-27 00:34:29 -0800 (Fri, 27 Jan 2006)
New Revision: 3001
Modified:
trunk/gtk/gtk-im-uim.c
Log:
* gtk/gtk-im-uim.c
- Reorder functions to get rid of static prototypes.
- Rename functions which have im_uim prefix but not used for
class function.
- Add im_uim prefix for class functions which lack the prefix.
(im_uim_commit_string) : Rename to commit_string.
(im_uim_commit_cb) : Rename to commit_cb.
(focus_in) : Rename to im_uim_focus_in.
(focus_out) : Rename to im_uim_focus_out.
(set_use_preedit) : Rename to im_uim_set_use_preedit.
(set_client_window) : Rename to im_uim_set_client_window.
(im_uim_send_im_list) : Rename to send_im_list.
(im_uim_helper_disconnect_cb) : Rename to helper_disconnect_cb.
(im_uim_parse_helper_str_im_change) : Rename to
parse_helper_str_im_change.
(im_uim_parse_helper_str) : Rename to parse_helper_str.
(filter_keypress) : Rename to im_uim_filter_keypress.
(uim_key_snoop) : Rename to key_snoop.
Modified: trunk/gtk/gtk-im-uim.c
===================================================================
--- trunk/gtk/gtk-im-uim.c 2006-01-27 05:32:30 UTC (rev 3000)
+++ trunk/gtk/gtk-im-uim.c 2006-01-27 08:34:29 UTC (rev 3001)
@@ -38,8 +38,11 @@
#include <gtk/gtkimcontext.h>
#include <gtk/gtkimmodule.h>
#include <gdk/gdkkeysyms.h>
+#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
+#endif
#include <glib/gprintf.h>
+
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
@@ -57,6 +60,7 @@
#include "caret-state-indicator.h"
#include "key-util-gtk.h"
+/* select either of these two, or filter key event will be used */
#define IM_UIM_USE_SNOOPER 0
#define IM_UIM_USE_TOPLEVEL 1
@@ -69,16 +73,6 @@
#define NR_CANDIDATES 20
#define DEFAULT_SEPARATOR_STR "|"
-static int im_uim_fd = -1;
-static unsigned int read_tag;
-#if IM_UIM_USE_SNOOPER
-static guint snooper_id;
-#elif IM_UIM_USE_TOPLEVEL
-static GtkWidget *cur_toplevel;
-gulong cur_key_press_handler_id;
-gulong cur_key_release_handler_id;
-#endif
-
struct preedit_segment {
int attr;
char *str;
@@ -94,7 +88,6 @@
int prev_preedit_len;
struct preedit_segment *pseg;
- GtkWidget *menu;
GdkWindow *win;
GtkWidget *caret_state_indicator;
@@ -113,13 +106,21 @@
struct _IMUIMContext *prev, *next;
} IMUIMContext;
-static IMUIMContext context_list;
-static IMUIMContext *focused_context = NULL;
-static gboolean disable_focused_context = FALSE;
+static int im_uim_fd = -1;
+static unsigned int read_tag;
#if IM_UIM_USE_SNOOPER
+static guint snooper_id;
static gboolean snooper_installed = FALSE;
+#elif IM_UIM_USE_TOPLEVEL
+static GtkWidget *cur_toplevel;
+static gulong cur_key_press_handler_id;
+static gulong cur_key_release_handler_id;
#endif
+static IMUIMContext context_list;
+static IMUIMContext *focused_context = NULL;
+static gboolean disable_focused_context = FALSE;
+
static GObjectClass *parent_class;
typedef struct _IMContextUIMClass
@@ -132,16 +133,8 @@
static void im_uim_class_finalize(GtkIMContextClass *class);
static void im_uim_init(IMUIMContext *uic);
-static void show_preedit(GtkIMContext *ic, GtkWidget *preedit_label);
-
-static void im_uim_helper_disconnect_cb(void);
-static gboolean helper_read_cb(GIOChannel *channel, GIOCondition c, gpointer p);
-static GdkFilterReturn toplevel_window_candidate_cb(GdkXEvent *xevent, GdkEvent *ev, gpointer data);
-
-static void im_uim_parse_helper_str(const char *str);
-static gboolean get_user_defined_color(PangoColor *color, const gchar *uim_symbol);
#if IM_UIM_USE_SNOOPER
-static gboolean uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data);
+static gboolean key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data);
#elif IM_UIM_USE_TOPLEVEL
static gboolean handle_key_on_toplevel(GtkWidget *widget, GdkEventKey *event, gpointer data);
#endif
@@ -175,8 +168,11 @@
};
+
+/* gtk's string handling */
+
static void
-im_uim_commit_string(void *ptr, const char *str)
+commit_string(void *ptr, const char *str)
{
IMUIMContext *uic = (IMUIMContext *)ptr;
uim_bool show_state;
@@ -193,110 +189,13 @@
}
static void
-clear_cb(void *ptr)
+commit_cb(GtkIMContext *ic, const gchar *str, IMUIMContext *is)
{
- IMUIMContext *uic = (IMUIMContext *)ptr;
- int i;
-
- for (i = 0; i < uic->nr_psegs; i++)
- free(uic->pseg[i].str);
- free(uic->pseg);
-
- uic->pseg = NULL;
- uic->nr_psegs = 0;
-}
-
-static void
-pushback_cb(void *ptr, int attr, const char *str)
-{
- IMUIMContext *uic = (IMUIMContext *)ptr;
g_return_if_fail(str);
-
- if (!strcmp(str, "")
- && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator)))
- return;
-
- uic->pseg = realloc(uic->pseg,
- sizeof(struct preedit_segment) * (uic->nr_psegs + 1));
- uic->pseg[uic->nr_psegs].str = g_strdup(str);
- uic->pseg[uic->nr_psegs].attr = attr;
- uic->nr_psegs++;
+ g_signal_emit_by_name(is, "commit", str);
}
-static int
-preedit_strlen(IMUIMContext *uic)
-{
- int i, len = 0;
-
- for (i = 0; i < uic->nr_psegs; i++)
- len += strlen(uic->pseg[i].str);
-
- return len;
-}
-
-static void
-update_cb(void *ptr)
-{
- IMUIMContext *uic = (IMUIMContext *)ptr;
- int preedit_len;
-
- g_return_if_fail(uic);
-
- preedit_len = preedit_strlen(uic);
-
- if (uic->prev_preedit_len == 0 && preedit_len)
- g_signal_emit_by_name(uic, "preedit_start");
-
- g_signal_emit_by_name(uic, "preedit_changed");
-
- if (uic->prev_preedit_len && preedit_len == 0)
- g_signal_emit_by_name(uic, "preedit_end");
-
- uic->prev_preedit_len = preedit_len;
-}
-
-/*
- * filter key event handler
- *
- * uim uses key snooper or toplevel key event for IM. So filter key
- * event is just for fallbacks.
- *
- */
static gboolean
-filter_keypress(GtkIMContext *ic, GdkEventKey *key)
-{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-#if IM_UIM_USE_SNOOPER
- if (!snooper_installed) {
-#elif IM_UIM_USE_TOPLEVEL
- /*
- * Sometimes key events are emitted from other than top level
- * widget, so check time of the event...
- */
- if (!cur_toplevel || key->time != uic->event_rec.time) {
-#else
- if (TRUE) {
-#endif
- int rv, kv, mod;
-
- im_uim_convert_keyevent(key, &kv, &mod);
-
- if (key->type == GDK_KEY_RELEASE)
- rv = uim_release_key(uic->uc, kv, mod);
- else
- rv = uim_press_key(uic->uc, kv, mod);
-
- if (rv)
- return gtk_im_context_filter_keypress(uic->slave, key);
-
- return TRUE;
- }
-
- return gtk_im_context_filter_keypress(uic->slave, key);
-}
-
-static gboolean
get_user_defined_color(PangoColor *color, const gchar *uim_symbol)
{
gboolean parsed = FALSE;
@@ -382,178 +281,8 @@
return str;
}
-
+/* only used when use_preedit == FALSE */
static void
-im_uim_get_preedit_string(GtkIMContext *ic, gchar **str, PangoAttrList **attrs,
- gint *cursor_pos)
-{
- char *tmp;
- int i, pos = 0;
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
- if (attrs)
- *attrs = pango_attr_list_new();
-
- tmp = g_strdup("");
-
- for (i = 0; i < uic->nr_psegs; i++) {
- if (uic->pseg[i].attr & UPreeditAttr_Cursor)
- pos = g_utf8_strlen(tmp, -1);
-
- if (attrs)
- tmp = get_preedit_segment(&uic->pseg[i], *attrs, tmp);
- else
- tmp = get_preedit_segment(&uic->pseg[i], NULL, tmp);
- }
- if (cursor_pos)
- *cursor_pos = pos;
-
- if (str)
- *str = tmp;
- else
- free(tmp);
-}
-
-static void
-im_uim_set_cursor_location(GtkIMContext *ic, GdkRectangle *area)
-{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
- uic->preedit_pos = *area;
- uim_cand_win_gtk_set_cursor_location(uic->cwin, area);
- caret_state_indicator_set_cursor_location(uic->caret_state_indicator, area);
-}
-
-
-static void
-im_uim_commit_cb(GtkIMContext *ic, const gchar *str, IMUIMContext *is)
-{
- g_return_if_fail(str);
- g_signal_emit_by_name(is, "commit", str);
-}
-
-static void
-check_helper_connection()
-{
- if (im_uim_fd < 0) {
- im_uim_fd = uim_helper_init_client_fd(im_uim_helper_disconnect_cb);
- if (im_uim_fd >= 0) {
- GIOChannel *channel;
- channel = g_io_channel_unix_new(im_uim_fd);
- read_tag = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
- helper_read_cb, NULL);
- g_io_channel_unref(channel);
- }
- }
-}
-
-static void
-focus_in(GtkIMContext *ic)
-{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
- IMUIMContext *cc;
-#if IM_UIM_USE_TOPLEVEL
- GtkWidget *toplevel;
-#endif
-
- focused_context = uic;
- disable_focused_context = FALSE;
-
-#if IM_UIM_USE_SNOOPER
- /* Using key snooper is not recommended */
- if (snooper_installed == FALSE) {
- snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)uim_key_snoop, NULL );
- snooper_installed = TRUE;
- }
-#elif IM_UIM_USE_TOPLEVEL
- toplevel = gtk_widget_get_toplevel(uic->widget);
- cur_toplevel = toplevel;
-
- if (toplevel && GTK_WIDGET_TOPLEVEL(toplevel)) {
- cur_key_press_handler_id = g_signal_connect(cur_toplevel, "key-press-event", G_CALLBACK(handle_key_on_toplevel), uic);
- cur_key_release_handler_id = g_signal_connect(cur_toplevel, "key-release-event", G_CALLBACK(handle_key_on_toplevel), uic);
- }
-#endif
-
- check_helper_connection();
-
- uim_helper_client_focus_in(uic->uc);
-
- uim_prop_list_update(uic->uc);
- uim_prop_label_update(uic->uc);
-
- for (cc = context_list.next; cc != &context_list; cc = cc->next) {
- if (cc != uic && cc->cwin)
- gtk_widget_hide(GTK_WIDGET(cc->cwin));
- }
-
- if (uic->cwin && uic->cwin_is_active)
- gtk_widget_show(GTK_WIDGET(uic->cwin));
-}
-
-static void
-focus_out(GtkIMContext *ic)
-{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
-
-#if IM_UIM_USE_SNOOPER
- if (snooper_installed == TRUE) {
- gtk_key_snooper_remove(snooper_id);
- snooper_installed = FALSE;
- }
-#elif IM_UIM_USE_TOPLEVEL
- if (cur_toplevel) {
- g_signal_handler_disconnect(cur_toplevel, cur_key_press_handler_id);
- g_signal_handler_disconnect(cur_toplevel, cur_key_release_handler_id);
- cur_toplevel = NULL;
- }
-#endif
-
- check_helper_connection();
- uim_helper_client_focus_out(uic->uc);
-
- if (uic->cwin)
- gtk_widget_hide(GTK_WIDGET(uic->cwin));
-
- gtk_widget_hide(uic->caret_state_indicator);
-}
-
-static void
-im_uim_reset(GtkIMContext *ic)
-{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
- uim_reset_context(uic->uc);
-}
-
-static void
-set_use_preedit(GtkIMContext *ic, gboolean use_preedit)
-{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
- GtkWidget *preedit_label = NULL;
-
- if (use_preedit == FALSE) {
- if (!uic->preedit_window) {
- uic->preedit_window = gtk_window_new(GTK_WINDOW_POPUP);
- preedit_label = gtk_label_new("");
- gtk_container_add(GTK_CONTAINER(uic->preedit_window), preedit_label);
- }
- uic->preedit_handler_id =
- g_signal_connect(G_OBJECT(ic), "preedit-changed",
- G_CALLBACK(show_preedit), preedit_label);
- gtk_widget_show_all(uic->preedit_window);
- } else {
- if (uic->preedit_handler_id) {
- g_signal_handler_disconnect(G_OBJECT(ic), uic->preedit_handler_id);
- uic->preedit_handler_id = 0;
- }
- if (uic->preedit_window) {
- gtk_widget_destroy(uic->preedit_window);
- uic->preedit_window = NULL;
- }
- }
-}
-
-static void
show_preedit(GtkIMContext *ic, GtkWidget *preedit_label)
{
IMUIMContext *uic = IM_UIM_CONTEXT(ic);
@@ -596,25 +325,10 @@
pango_attr_list_unref(attrs);
}
-static GdkFilterReturn
-toplevel_window_candidate_cb(GdkXEvent *xevent, GdkEvent *ev, gpointer data)
-{
- IMUIMContext *uic = data;
- if (!uic)
- return GDK_FILTER_CONTINUE;
- if (uic->cwin && uic->cwin_is_active) {
- gint x, y, width, height, depth;
+/* widget utilities */
- gdk_window_get_geometry(uic->win, &x, &y, &width, &height, &depth);
- gdk_window_get_origin(uic->win, &x, &y);
- uim_cand_win_gtk_layout(uic->cwin, x, y, width, height);
- }
-
- return GDK_FILTER_CONTINUE;
-}
-
#if IM_UIM_USE_TOPLEVEL
static void
update_in_toplevel(IMUIMContext *uic)
@@ -628,15 +342,15 @@
}
static GtkWidget *
-widget_for_window (GdkWindow *window)
+widget_for_window(GdkWindow *window)
{
while (window) {
gpointer user_data;
- gdk_window_get_user_data (window, &user_data);
+ gdk_window_get_user_data(window, &user_data);
if (user_data)
return user_data;
- window = gdk_window_get_parent (window);
+ window = gdk_window_get_parent(window);
}
return NULL;
@@ -652,7 +366,7 @@
update_client_widget(IMUIMContext *uic)
{
GtkWidget *new_widget = widget_for_window(uic->win);
-
+
if (new_widget != uic->widget) {
if (uic->widget)
g_signal_handlers_disconnect_by_func(uic->widget,
@@ -667,22 +381,17 @@
}
#endif /* IM_UIM_USE_TOPLEVEL */
-static void
-set_client_window(GtkIMContext *ic, GdkWindow *w)
+/* utility functions */
+
+static int
+preedit_strlen(IMUIMContext *uic)
{
- IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+ int i, len = 0;
- if (w) {
- g_object_ref(w);
- uic->win = w;
- } else {
- if (uic->win)
- g_object_unref(uic->win);
- uic->win = NULL;
- }
-#if IM_UIM_USE_TOPLEVEL
- update_client_widget(uic);
-#endif
+ for (i = 0; i < uic->nr_psegs; i++)
+ len += strlen(uic->pseg[i].str);
+
+ return len;
}
static void
@@ -693,101 +402,78 @@
uim_set_candidate_index(uic->uc, uim_cand_win_gtk_get_index(cwin));
}
-static void
-im_uim_init(IMUIMContext *uic)
+static GdkFilterReturn
+toplevel_window_candidate_cb(GdkXEvent *xevent, GdkEvent *ev, gpointer data)
{
- uic->win = NULL;
-#if IM_UIM_USE_TOPLEVEL
- uic->widget = NULL;
- uic->in_toplevel = FALSE;
- uic->event_rec.time = 0;
-#endif
- uic->menu = NULL;
- uic->caret_state_indicator = NULL;
- uic->pseg = NULL;
- uic->nr_psegs = 0;
- uic->prev_preedit_len = 0;
+ IMUIMContext *uic = data;
- uic->cwin = uim_cand_win_gtk_new();
- uic->cwin_is_active = FALSE;
- uic->preedit_window = NULL;
- uic->preedit_handler_id = 0;
- g_signal_connect(G_OBJECT(uic->cwin), "index-changed",
- G_CALLBACK(index_changed_cb), uic);
+ if (!uic)
+ return GDK_FILTER_CONTINUE;
+
+ if (uic->cwin && uic->cwin_is_active) {
+ gint x, y, width, height, depth;
+
+ gdk_window_get_geometry(uic->win, &x, &y, &width, &height, &depth);
+ gdk_window_get_origin(uic->win, &x, &y);
+ uim_cand_win_gtk_layout(uic->cwin, x, y, width, height);
+ }
+
+ return GDK_FILTER_CONTINUE;
}
-/*
- * DESTRUCTOR
- */
+
+/* callback functions for libuim */
+
static void
-im_uim_finalize(GObject *obj)
+clear_cb(void *ptr)
{
- IMUIMContext *uic = IM_UIM_CONTEXT(obj);
- /* set_client_window(GTK_IM_CONTEXT(uic), NULL); */
+ IMUIMContext *uic = (IMUIMContext *)ptr;
+ int i;
- uic->next->prev = uic->prev;
- uic->prev->next = uic->next;
+ for (i = 0; i < uic->nr_psegs; i++)
+ free(uic->pseg[i].str);
+ free(uic->pseg);
- if (uic->menu) {
- gtk_widget_destroy(uic->menu);
- uic->menu = NULL;
- }
- if (uic->cwin) {
- gtk_widget_destroy(GTK_WIDGET(uic->cwin));
- uic->cwin = NULL;
- }
- if (uic->caret_state_indicator) {
- guint tag = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(uic->caret_state_indicator), "timeout-tag"));
- if (tag > 0)
- g_source_remove(tag);
- gtk_widget_destroy(uic->caret_state_indicator);
- uic->caret_state_indicator = NULL;
- }
+ uic->pseg = NULL;
+ uic->nr_psegs = 0;
+}
- if (uic->preedit_handler_id) {
- g_signal_handler_disconnect(obj, uic->preedit_handler_id);
- uic->preedit_handler_id = 0;
- }
- if (uic->preedit_window) {
- gtk_widget_destroy(uic->preedit_window);
- uic->preedit_window = NULL;
- }
+static void
+pushback_cb(void *ptr, int attr, const char *str)
+{
+ IMUIMContext *uic = (IMUIMContext *)ptr;
+ g_return_if_fail(str);
- uim_release_context(uic->uc);
+ if (!strcmp(str, "")
+ && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator)))
+ return;
- g_signal_handlers_disconnect_by_func(uic->slave, (gpointer)im_uim_commit_cb,
- uic);
- g_object_unref(uic->slave);
- parent_class->finalize(obj);
-
- if (uic == focused_context) {
- focused_context = NULL;
- disable_focused_context = TRUE;
- }
+ uic->pseg = realloc(uic->pseg,
+ sizeof(struct preedit_segment) * (uic->nr_psegs + 1));
+ uic->pseg[uic->nr_psegs].str = g_strdup(str);
+ uic->pseg[uic->nr_psegs].attr = attr;
+ uic->nr_psegs++;
}
static void
-im_uim_class_init(GtkIMContextClass *class)
+update_cb(void *ptr)
{
- GObjectClass *object_class = G_OBJECT_CLASS(class);
+ IMUIMContext *uic = (IMUIMContext *)ptr;
+ int preedit_len;
- parent_class = g_type_class_peek_parent(class);
- class->set_client_window = set_client_window;
- class->filter_keypress = filter_keypress;
- class->get_preedit_string = im_uim_get_preedit_string;
- class->set_cursor_location = im_uim_set_cursor_location;
- class->focus_in = focus_in;
- class->focus_out = focus_out;
- class->reset = im_uim_reset;
- class->set_use_preedit = set_use_preedit;
+ g_return_if_fail(uic);
- object_class->finalize = im_uim_finalize;
-}
+ preedit_len = preedit_strlen(uic);
+ if (uic->prev_preedit_len == 0 && preedit_len)
+ g_signal_emit_by_name(uic, "preedit_start");
-static void
-im_uim_class_finalize(GtkIMContextClass *class)
-{
+ g_signal_emit_by_name(uic, "preedit_changed");
+
+ if (uic->prev_preedit_len && preedit_len == 0)
+ g_signal_emit_by_name(uic, "preedit_end");
+
+ uic->prev_preedit_len = preedit_len;
}
static void
@@ -839,103 +525,6 @@
}
static void
-im_uim_send_im_list(void)
-{
- int nr, i;
- GString *msg;
- const char *current_im_name;
-
- if (!focused_context)
- return;
-
- nr = uim_get_nr_im(focused_context->uc);
- current_im_name = uim_get_current_im_name(focused_context->uc);
-
- msg = g_string_new("im_list\ncharset=UTF-8\n");
- for (i = 0; i < nr; i++) {
- /*
- * Return value of uim_get_im_language() is an ISO 639-1
- * compatible language code such as "ja". Since it is unfriendly
- * for human reading, we convert it into friendly one by
- * uim_get_language_name_from_locale() here.
- */
- const char *name = uim_get_im_name(focused_context->uc, i);
- const char *langcode = uim_get_im_language(focused_context->uc, i);
- const char *lang = uim_get_language_name_from_locale(langcode);
- const char *short_desc = uim_get_im_short_desc(focused_context->uc, i);
-
- g_string_append(msg, name);
- g_string_append(msg, "\t");
- if (lang)
- g_string_append(msg, lang);
- g_string_append(msg, "\t");
- if (short_desc)
- g_string_append(msg, short_desc);
- g_string_append(msg, "\t");
- if (strcmp(name, current_im_name) == 0)
- g_string_append(msg, "selected");
- g_string_append(msg, "\n");
- }
- uim_helper_send_message(im_uim_fd, msg->str);
- g_string_free(msg, TRUE);
-}
-
-/* Copied from helper-common-gtk.c. Maybe we need common GTK+ utility file. */
-static gchar *
-get_charset(gchar *line)
-{
- gchar **splitted = NULL;
-
- splitted = g_strsplit(line, "=", 0);
-
- if (splitted && splitted[0] && splitted[1]
- && strcmp("charset", splitted[0]) == 0) {
- gchar *charset = g_strdup(splitted[1]);
- g_strfreev(splitted);
- return charset;
- } else {
- g_strfreev(splitted);
- return NULL;
- }
-}
-
-static void
-commit_string_from_other_process(const gchar *str)
-{
- gchar **lines = g_strsplit(str, "\n", 0);
- gchar *commit_string;
-
- if (!lines || !lines[0] || !lines[1] || !lines[2])
- return; /* Message is broken, do nothing. */
-
- /*
- * If second line exists, we assume the first line as a charset
- * specifier. This (rotten) convention is influenced by old design
- * mistake (character encoding was forgotten!).
- */
- if (strcmp(lines[2], "") != 0) {
- gchar *encoding, *commit_string_utf8;
-
- encoding = get_charset(lines[1]);
- commit_string = lines[2];
- commit_string_utf8 = g_convert(commit_string, strlen(commit_string),
- "UTF-8", encoding,
- NULL, /* gsize *bytes_read */
- NULL, /* size *bytes_written */
- NULL); /* GError **error */
- g_signal_emit_by_name(focused_context, "commit", commit_string_utf8);
- g_free(encoding);
- g_free(commit_string_utf8);
- } else {
- /* Assuming character encoding as UTF-8. */
- commit_string = lines[1];
- g_signal_emit_by_name(focused_context, "commit", commit_string);
- }
-
- g_strfreev(lines);
-}
-
-static void
cand_activate_cb(void *ptr, int nr, int display_limit)
{
IMUIMContext *uic = (IMUIMContext *)ptr;
@@ -969,9 +558,6 @@
}
}
-/*
- * This function called by libuim. Selected by keyboard, etc.
- */
static void
cand_select_cb(void *ptr, int index)
{
@@ -1025,62 +611,19 @@
}
}
-GtkIMContext *
-im_module_create(const gchar *context_id)
-{
- GObject *obj;
- IMUIMContext *uic;
- const char *im_name;
- g_return_val_if_fail(context_id, NULL);
- g_return_val_if_fail(!strcmp(context_id, "uim"), NULL);
- obj = g_object_new(type_im_uim, NULL);
- uic = IM_UIM_CONTEXT(obj);
- im_name = uim_get_default_im_name(setlocale(LC_CTYPE, NULL));
- uic->uc = uim_create_context(uic, "UTF-8",
- NULL, im_name,
- uim_iconv,
- im_uim_commit_string);
- if (uic->uc == NULL) {
- parent_class->finalize(obj);
- return NULL;
- }
+/* uim helper related */
- check_helper_connection();
-
- uim_set_preedit_cb(uic->uc, clear_cb, pushback_cb, update_cb);
- uim_set_prop_list_update_cb(uic->uc, update_prop_list_cb);
- uim_set_prop_label_update_cb(uic->uc, update_prop_label_cb);
- uim_set_candidate_selector_cb(uic->uc, cand_activate_cb, cand_select_cb,
- cand_shift_page_cb, cand_deactivate_cb);
-
- uim_prop_list_update(uic->uc);
-
- /* slave exists for using gtk+'s table based input method */
- uic->slave = g_object_new(GTK_TYPE_IM_CONTEXT_SIMPLE, NULL);
- g_signal_connect(G_OBJECT(uic->slave), "commit",
- G_CALLBACK(im_uim_commit_cb), uic);
-
- uic->caret_state_indicator = caret_state_indicator_new();
-
- uic->next = context_list.next;
- uic->prev = (IMUIMContext *)&context_list;
- context_list.next->prev = uic;
- context_list.next = uic;
- return GTK_IM_CONTEXT(uic);
-}
-
-void
-im_module_list(const GtkIMContextInfo ***contexts,
- int *n_contexts)
+static void
+helper_disconnect_cb(void)
{
- *contexts = &im_uim_info_list;
- *n_contexts = 1;
+ im_uim_fd = -1;
+ g_source_remove(read_tag);
}
static void
-im_uim_parse_helper_str_im_change(const char *str)
+parse_helper_str_im_change(const char *str)
{
IMUIMContext *cc;
gchar **lines = g_strsplit(str, "\n", -1);
@@ -1118,12 +661,109 @@
}
static void
-im_uim_parse_helper_str(const char *str)
+send_im_list(void)
{
+ int nr, i;
+ GString *msg;
+ const char *current_im_name;
+
+ if (!focused_context)
+ return;
+
+ nr = uim_get_nr_im(focused_context->uc);
+ current_im_name = uim_get_current_im_name(focused_context->uc);
+
+ msg = g_string_new("im_list\ncharset=UTF-8\n");
+ for (i = 0; i < nr; i++) {
+ /*
+ * Return value of uim_get_im_language() is an ISO 639-1
+ * compatible language code such as "ja". Since it is unfriendly
+ * for human reading, we convert it into friendly one by
+ * uim_get_language_name_from_locale() here.
+ */
+ const char *name = uim_get_im_name(focused_context->uc, i);
+ const char *langcode = uim_get_im_language(focused_context->uc, i);
+ const char *lang = uim_get_language_name_from_locale(langcode);
+ const char *short_desc = uim_get_im_short_desc(focused_context->uc, i);
+
+ g_string_append(msg, name);
+ g_string_append(msg, "\t");
+ if (lang)
+ g_string_append(msg, lang);
+ g_string_append(msg, "\t");
+ if (short_desc)
+ g_string_append(msg, short_desc);
+ g_string_append(msg, "\t");
+ if (strcmp(name, current_im_name) == 0)
+ g_string_append(msg, "selected");
+ g_string_append(msg, "\n");
+ }
+ uim_helper_send_message(im_uim_fd, msg->str);
+ g_string_free(msg, TRUE);
+}
+
+/* Copied from helper-common-gtk.c. Maybe we need common GTK+ utility file. */
+static gchar *
+get_charset(gchar *line)
+{
+ gchar **splitted = NULL;
+
+ splitted = g_strsplit(line, "=", 0);
+
+ if (splitted && splitted[0] && splitted[1]
+ && strcmp("charset", splitted[0]) == 0) {
+ gchar *charset = g_strdup(splitted[1]);
+ g_strfreev(splitted);
+ return charset;
+ } else {
+ g_strfreev(splitted);
+ return NULL;
+ }
+}
+
+static void
+commit_string_from_other_process(const gchar *str)
+{
+ gchar **lines = g_strsplit(str, "\n", 0);
+ gchar *commit_string;
+
+ if (!lines || !lines[0] || !lines[1] || !lines[2])
+ return; /* Message is broken, do nothing. */
+
+ /*
+ * If second line exists, we assume the first line as a charset
+ * specifier. This (rotten) convention is influenced by old design
+ * mistake (character encoding was forgotten!).
+ */
+ if (strcmp(lines[2], "") != 0) {
+ gchar *encoding, *commit_string_utf8;
+
+ encoding = get_charset(lines[1]);
+ commit_string = lines[2];
+ commit_string_utf8 = g_convert(commit_string, strlen(commit_string),
+ "UTF-8", encoding,
+ NULL, /* gsize *bytes_read */
+ NULL, /* size *bytes_written */
+ NULL); /* GError **error */
+ g_signal_emit_by_name(focused_context, "commit", commit_string_utf8);
+ g_free(encoding);
+ g_free(commit_string_utf8);
+ } else {
+ /* Assuming character encoding as UTF-8. */
+ commit_string = lines[1];
+ g_signal_emit_by_name(focused_context, "commit", commit_string);
+ }
+
+ g_strfreev(lines);
+}
+
+static void
+parse_helper_str(const char *str)
+{
gchar **lines;
if (g_str_has_prefix(str, "im_change") == TRUE) {
- im_uim_parse_helper_str_im_change(str);
+ parse_helper_str_im_change(str);
} else if (g_str_has_prefix(str, "prop_update_custom") == TRUE) {
IMUIMContext *cc;
@@ -1149,7 +789,7 @@
g_strfreev(lines);
}
} else if (g_str_has_prefix(str, "im_list_get") == TRUE) {
- im_uim_send_im_list();
+ send_im_list();
} else if (g_str_has_prefix(str, "commit_string")) {
commit_string_from_other_process(str);
} else if (g_str_has_prefix(str, "focus_in") == TRUE) {
@@ -1170,23 +810,388 @@
uim_helper_read_proc(fd);
while ((msg = uim_helper_get_message())) {
- im_uim_parse_helper_str(msg);
+ parse_helper_str(msg);
free(msg);
}
return TRUE;
}
static void
-im_uim_helper_disconnect_cb(void)
+check_helper_connection()
{
- im_uim_fd = -1;
- g_source_remove(read_tag);
+ if (im_uim_fd < 0) {
+ im_uim_fd = uim_helper_init_client_fd(helper_disconnect_cb);
+ if (im_uim_fd >= 0) {
+ GIOChannel *channel;
+ channel = g_io_channel_unix_new(im_uim_fd);
+ read_tag = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
+ helper_read_cb, NULL);
+ g_io_channel_unref(channel);
+ }
+ }
}
+
+
+/* class functions */
+
+/*
+ * filter key event handler
+ *
+ * uim uses key snooper or toplevel key event for IM. So filter key
+ * event is just for fallbacks.
+ *
+ */
+static gboolean
+im_uim_filter_keypress(GtkIMContext *ic, GdkEventKey *key)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
#if IM_UIM_USE_SNOOPER
+ if (!snooper_installed) {
+#elif IM_UIM_USE_TOPLEVEL
+ /*
+ * Sometimes key events are emitted from other than top level
+ * widget, so check time of the event...
+ */
+ if (!cur_toplevel || key->time != uic->event_rec.time) {
+#else
+ if (TRUE) {
+#endif
+ int rv, kv, mod;
+
+ im_uim_convert_keyevent(key, &kv, &mod);
+
+ if (key->type == GDK_KEY_RELEASE)
+ rv = uim_release_key(uic->uc, kv, mod);
+ else
+ rv = uim_press_key(uic->uc, kv, mod);
+
+ if (rv)
+ return gtk_im_context_filter_keypress(uic->slave, key);
+
+ return TRUE;
+ }
+
+ return gtk_im_context_filter_keypress(uic->slave, key);
+}
+
+static void
+im_uim_get_preedit_string(GtkIMContext *ic, gchar **str, PangoAttrList **attrs,
+ gint *cursor_pos)
+{
+ char *tmp;
+ int i, pos = 0;
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+ if (attrs)
+ *attrs = pango_attr_list_new();
+
+ tmp = g_strdup("");
+
+ for (i = 0; i < uic->nr_psegs; i++) {
+ if (uic->pseg[i].attr & UPreeditAttr_Cursor)
+ pos = g_utf8_strlen(tmp, -1);
+
+ if (attrs)
+ tmp = get_preedit_segment(&uic->pseg[i], *attrs, tmp);
+ else
+ tmp = get_preedit_segment(&uic->pseg[i], NULL, tmp);
+ }
+ if (cursor_pos)
+ *cursor_pos = pos;
+
+ if (str)
+ *str = tmp;
+ else
+ free(tmp);
+}
+
+static void
+im_uim_set_cursor_location(GtkIMContext *ic, GdkRectangle *area)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+ uic->preedit_pos = *area;
+ uim_cand_win_gtk_set_cursor_location(uic->cwin, area);
+ caret_state_indicator_set_cursor_location(uic->caret_state_indicator, area);
+}
+
+static void
+im_uim_focus_in(GtkIMContext *ic)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+ IMUIMContext *cc;
+#if IM_UIM_USE_TOPLEVEL
+ GtkWidget *toplevel;
+#endif
+
+ focused_context = uic;
+ disable_focused_context = FALSE;
+
+#if IM_UIM_USE_SNOOPER
+ /* Using key snooper is not recommended */
+ if (snooper_installed == FALSE) {
+ snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)key_snoop, NULL);
+ snooper_installed = TRUE;
+ }
+#elif IM_UIM_USE_TOPLEVEL
+ toplevel = gtk_widget_get_toplevel(uic->widget);
+ cur_toplevel = toplevel;
+
+ if (toplevel && GTK_WIDGET_TOPLEVEL(toplevel)) {
+ cur_key_press_handler_id = g_signal_connect(cur_toplevel,
+ "key-press-event", G_CALLBACK(handle_key_on_toplevel),
+ uic);
+ cur_key_release_handler_id = g_signal_connect(cur_toplevel,
+ "key-release-event", G_CALLBACK(handle_key_on_toplevel),
+ uic);
+ }
+#endif
+
+ check_helper_connection();
+
+ uim_helper_client_focus_in(uic->uc);
+
+ uim_prop_list_update(uic->uc);
+ uim_prop_label_update(uic->uc);
+
+ for (cc = context_list.next; cc != &context_list; cc = cc->next) {
+ if (cc != uic && cc->cwin)
+ gtk_widget_hide(GTK_WIDGET(cc->cwin));
+ }
+
+ if (uic->cwin && uic->cwin_is_active)
+ gtk_widget_show(GTK_WIDGET(uic->cwin));
+}
+
+static void
+im_uim_focus_out(GtkIMContext *ic)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+#if IM_UIM_USE_SNOOPER
+ if (snooper_installed == TRUE) {
+ gtk_key_snooper_remove(snooper_id);
+ snooper_installed = FALSE;
+ }
+#elif IM_UIM_USE_TOPLEVEL
+ if (cur_toplevel) {
+ g_signal_handler_disconnect(cur_toplevel, cur_key_press_handler_id);
+ g_signal_handler_disconnect(cur_toplevel, cur_key_release_handler_id);
+ cur_toplevel = NULL;
+ }
+#endif
+
+ check_helper_connection();
+ uim_helper_client_focus_out(uic->uc);
+
+ if (uic->cwin)
+ gtk_widget_hide(GTK_WIDGET(uic->cwin));
+
+ gtk_widget_hide(uic->caret_state_indicator);
+}
+
+static void
+im_uim_reset(GtkIMContext *ic)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+ uim_reset_context(uic->uc);
+}
+
+static void
+im_uim_set_use_preedit(GtkIMContext *ic, gboolean use_preedit)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+ GtkWidget *preedit_label = NULL;
+
+ if (use_preedit == FALSE) {
+ if (!uic->preedit_window) {
+ uic->preedit_window = gtk_window_new(GTK_WINDOW_POPUP);
+ preedit_label = gtk_label_new("");
+ gtk_container_add(GTK_CONTAINER(uic->preedit_window), preedit_label);
+ }
+ uic->preedit_handler_id =
+ g_signal_connect(G_OBJECT(ic), "preedit-changed",
+ G_CALLBACK(show_preedit), preedit_label);
+ gtk_widget_show_all(uic->preedit_window);
+ } else {
+ if (uic->preedit_handler_id) {
+ g_signal_handler_disconnect(G_OBJECT(ic), uic->preedit_handler_id);
+ uic->preedit_handler_id = 0;
+ }
+ if (uic->preedit_window) {
+ gtk_widget_destroy(uic->preedit_window);
+ uic->preedit_window = NULL;
+ }
+ }
+}
+
+static void
+im_uim_set_client_window(GtkIMContext *ic, GdkWindow *w)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(ic);
+
+ if (w) {
+ g_object_ref(w);
+ uic->win = w;
+ } else {
+ if (uic->win)
+ g_object_unref(uic->win);
+ uic->win = NULL;
+ }
+#if IM_UIM_USE_TOPLEVEL
+ update_client_widget(uic);
+#endif
+}
+
+static void
+im_uim_init(IMUIMContext *uic)
+{
+ uic->win = NULL;
+#if IM_UIM_USE_TOPLEVEL
+ uic->widget = NULL;
+ uic->in_toplevel = FALSE;
+ uic->event_rec.time = 0;
+#endif
+ uic->caret_state_indicator = NULL;
+ uic->pseg = NULL;
+ uic->nr_psegs = 0;
+ uic->prev_preedit_len = 0;
+
+ uic->cwin = uim_cand_win_gtk_new();
+ uic->cwin_is_active = FALSE;
+ uic->preedit_window = NULL;
+ uic->preedit_handler_id = 0;
+
+ g_signal_connect(G_OBJECT(uic->cwin), "index-changed",
+ G_CALLBACK(index_changed_cb), uic);
+}
+
+static void
+im_uim_finalize(GObject *obj)
+{
+ IMUIMContext *uic = IM_UIM_CONTEXT(obj);
+ /* im_uim_set_client_window(GTK_IM_CONTEXT(uic), NULL); */
+
+ uic->next->prev = uic->prev;
+ uic->prev->next = uic->next;
+
+ if (uic->cwin) {
+ gtk_widget_destroy(GTK_WIDGET(uic->cwin));
+ uic->cwin = NULL;
+ }
+ if (uic->caret_state_indicator) {
+ guint tag = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(uic->caret_state_indicator), "timeout-tag"));
+ if (tag > 0)
+ g_source_remove(tag);
+ gtk_widget_destroy(uic->caret_state_indicator);
+ uic->caret_state_indicator = NULL;
+ }
+
+ if (uic->preedit_handler_id) {
+ g_signal_handler_disconnect(obj, uic->preedit_handler_id);
+ uic->preedit_handler_id = 0;
+ }
+ if (uic->preedit_window) {
+ gtk_widget_destroy(uic->preedit_window);
+ uic->preedit_window = NULL;
+ }
+
+ uim_release_context(uic->uc);
+
+ g_signal_handlers_disconnect_by_func(uic->slave, (gpointer)commit_cb, uic);
+ g_object_unref(uic->slave);
+ parent_class->finalize(obj);
+
+ if (uic == focused_context) {
+ focused_context = NULL;
+ disable_focused_context = TRUE;
+ }
+}
+
+static void
+im_uim_class_init(GtkIMContextClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(class);
+
+ parent_class = g_type_class_peek_parent(class);
+ class->set_client_window = im_uim_set_client_window;
+ class->filter_keypress = im_uim_filter_keypress;
+ class->get_preedit_string = im_uim_get_preedit_string;
+ class->set_cursor_location = im_uim_set_cursor_location;
+ class->focus_in = im_uim_focus_in;
+ class->focus_out = im_uim_focus_out;
+ class->reset = im_uim_reset;
+ class->set_use_preedit = im_uim_set_use_preedit;
+
+ object_class->finalize = im_uim_finalize;
+}
+
+static void
+im_uim_class_finalize(GtkIMContextClass *class)
+{
+}
+
+
+GtkIMContext *
+im_module_create(const gchar *context_id)
+{
+ GObject *obj;
+ IMUIMContext *uic;
+ const char *im_name;
+
+ g_return_val_if_fail(context_id, NULL);
+ g_return_val_if_fail(!strcmp(context_id, "uim"), NULL);
+
+ obj = g_object_new(type_im_uim, NULL);
+ uic = IM_UIM_CONTEXT(obj);
+ im_name = uim_get_default_im_name(setlocale(LC_CTYPE, NULL));
+ uic->uc = uim_create_context(uic, "UTF-8",
+ NULL, im_name,
+ uim_iconv,
+ commit_string);
+ if (uic->uc == NULL) {
+ parent_class->finalize(obj);
+ return NULL;
+ }
+
+ check_helper_connection();
+
+ uim_set_preedit_cb(uic->uc, clear_cb, pushback_cb, update_cb);
+ uim_set_prop_list_update_cb(uic->uc, update_prop_list_cb);
+ uim_set_prop_label_update_cb(uic->uc, update_prop_label_cb);
+ uim_set_candidate_selector_cb(uic->uc, cand_activate_cb, cand_select_cb,
+ cand_shift_page_cb, cand_deactivate_cb);
+
+ uim_prop_list_update(uic->uc);
+
+ /* slave exists for using gtk+'s table based input method */
+ uic->slave = g_object_new(GTK_TYPE_IM_CONTEXT_SIMPLE, NULL);
+ g_signal_connect(G_OBJECT(uic->slave), "commit",
+ G_CALLBACK(commit_cb), uic);
+
+ uic->caret_state_indicator = caret_state_indicator_new();
+
+ uic->next = context_list.next;
+ uic->prev = (IMUIMContext *)&context_list;
+ context_list.next->prev = uic;
+ context_list.next = uic;
+ return GTK_IM_CONTEXT(uic);
+}
+
+void
+im_module_list(const GtkIMContextInfo ***contexts,
+ int *n_contexts)
+{
+ *contexts = &im_uim_info_list;
+ *n_contexts = 1;
+}
+
+#if IM_UIM_USE_SNOOPER
/* snooper is not recommended! */
static gboolean
-uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data)
+key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data)
{
if (focused_context) {
int rv, kv, mod;
@@ -1212,7 +1217,7 @@
handle_key_on_toplevel(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
IMUIMContext *uic = data;
- GtkWindow *window = GTK_WINDOW(widget);
+ /* GtkWindow *window = GTK_WINDOW(widget); */
if (focused_context == uic) {
int rv, kv, mod;
@@ -1257,7 +1262,7 @@
#if IM_UIM_USE_SNOOPER
/* Using snooper is not recommended! */
- snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)uim_key_snoop, NULL );
+ snooper_id = gtk_key_snooper_install((GtkKeySnoopFunc)key_snoop, NULL);
snooper_installed = TRUE;
#endif
More information about the uim-commit
mailing list