diff -Nur trunk-bak/gtk/Makefile.am trunk/gtk/Makefile.am --- trunk-bak/gtk/Makefile.am 2004-07-27 12:31:45.000000000 +0900 +++ trunk/gtk/Makefile.am 2004-07-27 12:32:38.000000000 +0900 @@ -16,7 +16,9 @@ im_uim_la_LIBADD = ../uim/libuim.la -IM_UIM_SOURCES = gtk-im-uim.c +IM_UIM_SOURCES = \ + gtk-im-uim.c \ + uim-cand-win-gtk.c uim-cand-win-gtk.h install-data-hook: if test -f $(GTK_IMMODULES); then \ diff -Nur trunk-bak/gtk/gtk-im-uim.c trunk/gtk/gtk-im-uim.c --- trunk-bak/gtk/gtk-im-uim.c 2004-07-27 12:31:45.000000000 +0900 +++ trunk/gtk/gtk-im-uim.c 2004-07-27 12:32:22.000000000 +0900 @@ -47,6 +47,8 @@ #include #include +#include "uim-cand-win-gtk.h" + #define NR_CANDIDATES 20 #define DEFAULT_SEPARATOR_STR "|" @@ -59,27 +61,13 @@ char *str; }; -struct candidate_window { - GtkWidget *top_win; - GtkWidget *view; - GtkWidget *numlabel; - GtkListStore* store; - int nr_candidates; - int candidate_index; - int layout_begin; - int is_active; - int display_limit; - int select_count; - gboolean left; - GdkRectangle cursor; -}; - typedef struct _IMUIMContext { /**/ struct _GtkIMContext parent; struct _GtkIMContext *slave; uim_context uc; - struct candidate_window cwin; + UIMCandWinGtk *cwin; + gboolean cwin_is_active; int nr_psegs; struct preedit_segment *pseg; /**/ @@ -97,13 +85,14 @@ static GObjectClass *parent_class; -typedef struct _IMContextUIMClass +typedef struct _IMContextUIMClass { GtkIMContextClass parent_class; } IMContextUIMClass; static void im_uim_class_init (GtkIMContextClass *class); static void im_uim_class_finalize (GtkIMContextClass *class); +static void im_uim_init(IMUIMContext *uic); static void show_preedit(GtkIMContext *ic, GtkWidget *preedit_label); @@ -112,9 +101,6 @@ static GdkFilterReturn toplevel_window_candidate_cb (GdkXEvent *xevent, GdkEvent *ev, gpointer data); -static void layout_candidate(IMUIMContext *uic); -static void update_candidate(IMUIMContext *uic); - static void im_uim_parse_helper_str(char *str); @@ -129,7 +115,7 @@ NULL,/*for class data*/ sizeof(IMUIMContext), /* size of instance */ 0, - (GInstanceInitFunc)NULL, /* constructor */ + (GInstanceInitFunc) im_uim_init, /* constructor */ }; static GType type_im_uim = 0; @@ -170,7 +156,7 @@ { IMUIMContext *uic = (IMUIMContext *)ptr; g_return_if_fail(str); - + if(!strcmp(str,"") && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator))) return; @@ -395,14 +381,11 @@ { IMUIMContext *uic = IM_UIM_CONTEXT(ic); - if(uic->cwin.left && uic->nr_psegs > 1){ + if (uic->cwin->left && uic->nr_psegs > 1) { return; } - uic->cwin.cursor.x= area->x; - uic->cwin.cursor.y= area->y; - uic->cwin.cursor.height= area->height; - uic->cwin.cursor.width= area->width; + uim_cand_win_gtk_set_cursor_location(uic->cwin, area); uic->preedit_pos.x = area->x; uic->preedit_pos.y = area->y; @@ -445,17 +428,15 @@ uim_prop_label_update(uic->uc); for (cc = context_list.next; cc != &context_list; cc = cc->next) { - if (cc != uic) { - if (cc->cwin.top_win) { - gtk_widget_hide(cc->cwin.top_win); - } + if (cc != uic && cc->cwin) { + gtk_widget_hide(GTK_WIDGET(cc->cwin)); } } - - if(uic->cwin.top_win && uic->cwin.is_active){ - gtk_widget_show(uic->cwin.top_win); + + if(uic->cwin && uic->cwin_is_active){ + gtk_widget_show(GTK_WIDGET(uic->cwin)); } - + uim_helper_client_focus_in(uic->uc); } @@ -466,8 +447,8 @@ uim_helper_client_focus_out(uic->uc); - if(uic->cwin.top_win){ - gtk_widget_hide(uic->cwin.top_win); + if(uic->cwin){ + gtk_widget_hide(GTK_WIDGET(uic->cwin)); } } @@ -491,7 +472,7 @@ preedit_window = gtk_window_new(GTK_WINDOW_POPUP); preedit_label = gtk_label_new(""); gtk_container_add(GTK_CONTAINER(preedit_window), preedit_label); - + g_signal_connect(G_OBJECT(ic), "preedit-changed", G_CALLBACK(show_preedit), preedit_label ); gtk_widget_show_all(preedit_window); @@ -509,10 +490,10 @@ PangoAttrList *attrs; preedit_window = gtk_widget_get_parent(preedit_label); - + gtk_im_context_get_preedit_string (ic, &str, &attrs, &cursor_pos); - + if ( strlen (str) > 0) { gint x,y,w,h; PangoLayout *layout; @@ -521,7 +502,7 @@ gtk_label_set_attributes(GTK_LABEL(preedit_label), attrs); gdk_window_get_origin(uic->win, &x, &y); - + gtk_window_move( GTK_WINDOW(preedit_window), x + uic->preedit_pos.x, y + uic->preedit_pos.y ); @@ -543,7 +524,7 @@ } g_free (str); pango_attr_list_unref (attrs); - + } static GdkFilterReturn @@ -554,8 +535,11 @@ if(!uic) return GDK_FILTER_CONTINUE; - if(uic->cwin.top_win && uic->cwin.is_active ){ - layout_candidate(uic); + if(uic->cwin && uic->cwin_is_active){ + gint topwin_x, topwin_y; + + gdk_window_get_origin(uic->win, &topwin_x, &topwin_y); + uim_cand_win_gtk_layout(uic->cwin, topwin_x, topwin_y); } return GDK_FILTER_CONTINUE; } @@ -566,13 +550,36 @@ { IMUIMContext *uic = IM_UIM_CONTEXT(ic); - if(w) + if(w) { g_object_ref(w); - - if (uic->win) - g_object_unref(uic->win); - - uic->win = w; + uic->win = w; + } else { + if (uic->win) + g_object_unref(uic->win); + uic->win = NULL; + } +} + +static void +index_changed_cb(UIMCandWinGtk *cwin, IMUIMContext *uic) +{ + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + + uim_set_candidate_index(uic->uc, uim_cand_win_gtk_get_index(cwin)); +} + +static void +im_uim_init(IMUIMContext *uic) +{ + uic->win = NULL; + uic->menu = NULL; + uic->pseg = 0; + uic->nr_psegs = 0; + + uic->cwin = uim_cand_win_gtk_new(); + uic->cwin_is_active = FALSE; + g_signal_connect(G_OBJECT(uic->cwin), "index-changed", + G_CALLBACK(index_changed_cb), uic); } @@ -591,18 +598,16 @@ if (uic->menu) { gtk_widget_destroy(uic->menu); } - if (uic->cwin.store) { - g_object_unref(uic->cwin.store); - } - if (uic->cwin.top_win) { - gtk_widget_destroy(uic->cwin.top_win); + if (uic->cwin) { + gtk_widget_destroy(GTK_WIDGET(uic->cwin)); + uic->cwin = NULL; } uic->menu = NULL; uim_release_context(uic->uc); - + g_signal_handlers_disconnect_by_func(uic->slave, - im_uim_commit_cb, + (gpointer) im_uim_commit_cb, uic); g_object_unref(uic->slave); parent_class->finalize (obj); @@ -657,318 +662,39 @@ g_string_free(tmp, TRUE); } -/* This function is called by Gtk+, when user select candidate - by clicking candidate, etc. */ -static gboolean -tree_selection_changed(GtkTreeSelection *selection, - GtkTreeModel *model, - GtkTreePath *path, - gboolean path_currently_selected, - gpointer *data) -{ - gint *indices; - IMUIMContext *uic = IM_UIM_CONTEXT(data); - - if(!uic) - return TRUE; - - indices = gtk_tree_path_get_indices(path); - - if (uic->cwin.select_count == 0) { - int idx = *indices + uic->cwin.layout_begin; - - if( idx >= uic->cwin.nr_candidates ) { - uic->cwin.select_count++; - gtk_tree_view_set_cursor(GTK_TREE_VIEW(uic->cwin.view), - path, NULL, FALSE); - return TRUE; - } - - uim_set_candidate_index(uic->uc, idx); - uic->cwin.candidate_index = idx; - } else { - uic->cwin.select_count = 0; - } - return TRUE; -} - static void -init_candidate_win(IMUIMContext *uic) -{ - struct candidate_window *cwin = &uic->cwin; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkWidget *vbox; - GtkWidget *numlabel; - gchar *leftp; - GtkTreeSelection *selection; - - if (cwin->top_win) { - return ; - } - - leftp = uim_symbol_value_str("candidate-window-position"); - - if(leftp && !strcmp(leftp,"left")) { - cwin->left = TRUE; - } else { - cwin->left = FALSE; - } - g_free(leftp); - - cwin->top_win = gtk_window_new(GTK_WINDOW_POPUP); - cwin->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); - cwin->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(cwin->store)); - cwin->is_active = 0; - vbox = gtk_vbox_new(FALSE, 0); - numlabel = gtk_label_new(""); - cwin->numlabel = numlabel; - - gtk_box_pack_start(GTK_BOX(vbox), cwin->view, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), numlabel, FALSE, FALSE, 0); - - gtk_container_add(GTK_CONTAINER(cwin->top_win), vbox); - { - gint x,y,w,h,d; - gdk_window_get_geometry(uic->win, &x, &y,&w,&h,&d); - gdk_window_get_origin(uic->win, &x, &y); - gtk_window_move(GTK_WINDOW(cwin->top_win), x , y+h); - } - gtk_container_set_border_width(GTK_CONTAINER(cwin->top_win), 1); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(cwin->view)); - - gtk_tree_selection_set_select_function(selection, - tree_selection_changed, - uic, - NULL); - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes("No", - renderer, - "text", - 0, - NULL); - /* gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);*/ - gtk_tree_view_append_column(GTK_TREE_VIEW(cwin->view), column); - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes("Text", - renderer, - "text", - 1, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(cwin->view), column); - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(cwin->view), TRUE); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cwin->view), FALSE); - gtk_widget_show(cwin->view); - gtk_widget_show(numlabel); - gtk_widget_show(vbox); - -} - -static int -trim_index(IMUIMContext *uic) -{ - struct candidate_window *cwin = &uic->cwin; - int changed = 0; - - if(cwin->display_limit != 0){ - - while (cwin->layout_begin + cwin->display_limit <= cwin->candidate_index) { - changed = 1; - cwin->layout_begin += cwin->display_limit; - } - while (cwin->layout_begin > cwin->candidate_index) { - changed = 1; - cwin->layout_begin -= cwin->display_limit; - } - if (cwin->layout_begin < 0) { - changed = 1; - cwin->layout_begin = 0; - } - } - else { - while (cwin->layout_begin + NR_CANDIDATES <= cwin->candidate_index) { - changed = 1; - cwin->layout_begin += NR_CANDIDATES; - } - while (cwin->layout_begin > cwin->candidate_index) { - changed = 1; - cwin->layout_begin -= NR_CANDIDATES; - } - if (cwin->layout_begin < 0) { - changed = 1; - cwin->layout_begin = 0; - } - } - return changed; -} - -static gint -tree_view_max_width_request(GtkTreeView *tree_view) +cand_activate_cb(void *ptr, int nr, int display_limit) { - gint max_width = 0; - GList *column_list = gtk_tree_view_get_columns(tree_view); - - while(column_list) { - gint width,height; - GtkWidget *widget = gtk_tree_view_column_get_widget(GTK_TREE_VIEW_COLUMN(column_list->data)); - /* GtkRequisition req_column; */ - - gtk_tree_view_column_cell_get_size (GTK_TREE_VIEW_COLUMN(column_list->data), - NULL, - NULL, NULL, - &width, - &height); - if(!widget) { - column_list = g_list_next(column_list); - continue; - } + IMUIMContext *uic = (IMUIMContext *)ptr; + gint topwin_x, topwin_y; + gint x,y,w,h,d; + GSList *list = NULL; + uim_candidate cand; + gint i; + + gdk_window_get_geometry(uic->win, &x, &y,&w,&h,&d); + gdk_window_get_origin(uic->win, &x, &y); + gtk_window_move(GTK_WINDOW(uic->cwin), x , y+h); - /* gtk_widget_size_request(GTK_WIDGET(widget), &req_column); - width = req_column.width;*/ + uic->cwin_is_active = TRUE; - if(width > max_width) - max_width = width; - - column_list = g_list_next(column_list); + for (i = 0; i < nr; i++) { + cand = uim_get_candidate(uic->uc, i, i % display_limit); + list = g_slist_append(list, cand); } - return max_width; -} -static void -calc_candidate_window_size(struct candidate_window cwin, int *width, int *height) -{ - GtkRequisition req_view; - GtkRequisition req_numlabel; - gint max_width; - gtk_widget_size_request(GTK_WIDGET(cwin.view), &req_view); - gtk_widget_size_request(GTK_WIDGET(cwin.numlabel), &req_numlabel); - - max_width = tree_view_max_width_request(GTK_TREE_VIEW(cwin.view)); - *height = req_view.height + req_numlabel.height; - *width = /*max_width; */req_view.width; + uim_cand_win_gtk_set_candidates(uic->cwin, display_limit, list); - if(*width < 80) - *width = 80; - - gtk_window_resize(GTK_WINDOW(cwin.top_win), *width, *height); -} - -static void -layout_candidate(IMUIMContext *uic) -{ - int x, y, topwin_x, topwin_y; - int sc_he, cw_he; /*screen height, candidate window height*/ - int sc_wi, cw_wi; - char idx[20]; - - trim_index(uic); - - calc_candidate_window_size(uic->cwin, &cw_wi, &cw_he); - - sc_he = gdk_screen_get_height(gdk_screen_get_default ()); - sc_wi = gdk_screen_get_width (gdk_screen_get_default ()); + g_slist_foreach(list, (GFunc) uim_candidate_free, NULL); + g_slist_free(list); gdk_window_get_origin(uic->win, &topwin_x, &topwin_y); - - if(sc_wi < topwin_x + uic->cwin.cursor.x + cw_wi ) { - x = topwin_x + uic->cwin.cursor.x - cw_wi; - } else { - x = topwin_x + uic->cwin.cursor.x; - } - - if(sc_he < topwin_y + uic->cwin.cursor.y + uic->cwin.cursor.height + cw_he ) { - y = topwin_y + uic->cwin.cursor.y - cw_he; - } else { - y = topwin_y + uic->cwin.cursor.y + uic->cwin.cursor.height; - } - - gtk_window_move(GTK_WINDOW(uic->cwin.top_win), x, y ); - - update_candidate(uic); - -#if 0 - /* XXX: Consider if display_limit == 0 */ - for (i = 0; i < NR_CANDIDATES && i < uic->cwin.display_limit; i++) { - if (i < uic->cwin.nr_candidates - uic->cwin.layout_begin) { - uim_candidate new_cand = uim_get_candidate(uic->uc, uic->cwin.layout_begin + i, i); - g_return_if_fail(new_cand); - - new_cand_str = (gchar*)uim_candidate_get_cand_str(new_cand); - - if(!new_cand_str) - return; - - /* Checking old cand and new cand is the same or not. If not, call update. - Caching new result is good idea for speed up and should be implement.*/ - if(!old_cand_str || strcmp(new_cand_str, old_cand_str) != 0) { - - uim_candidate_free(new_cand); - break; - } - uim_candidate_free(new_cand); - } - } -#endif - - uic->cwin.select_count = 1; - - if(uic->cwin.candidate_index >= 0) { - GtkTreePath *path = gtk_tree_path_new_from_indices(uic->cwin.candidate_index - uic->cwin.layout_begin, -1); - gtk_tree_view_set_cursor(GTK_TREE_VIEW(uic->cwin.view), - path, NULL, FALSE); - - sprintf(idx, "%d / %d", uic->cwin.candidate_index + 1 , uic->cwin.nr_candidates); - } else { - GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(uic->cwin.view)); - gtk_tree_selection_unselect_all (selection); - sprintf(idx, "- / %d", uic->cwin.nr_candidates); - } - gtk_label_set_text( GTK_LABEL(uic->cwin.numlabel), idx); -} - -static void -update_candidate(IMUIMContext *uic) -{ - int i; - uim_candidate cand = NULL; - GtkTreeIter ti; - gtk_list_store_clear(uic->cwin.store); - for (i = 0; i < NR_CANDIDATES && i < uic->cwin.display_limit; i++) { - if (i < uic->cwin.nr_candidates - uic->cwin.layout_begin) { - cand = uim_get_candidate(uic->uc, uic->cwin.layout_begin + i, i); - gtk_list_store_append(uic->cwin.store, &ti); - gtk_list_store_set(uic->cwin.store, &ti, - 0, uim_candidate_get_heading_label(cand), - 1, uim_candidate_get_cand_str(cand), - -1); - uim_candidate_free(cand); - } else { - gtk_list_store_append(uic->cwin.store, &ti); - gtk_list_store_set(uic->cwin.store, &ti, - 0, "", - 1, "", -1); - } - } -} - -static void -cand_activate_cb(void *ptr, int nr, int display_limit) -{ - IMUIMContext *uic = (IMUIMContext *)ptr; - init_candidate_win(uic); - uic->cwin.is_active = 1; - uic->cwin.candidate_index = -1; - uic->cwin.nr_candidates = nr; - uic->cwin.display_limit = display_limit; - uic->cwin.layout_begin = 0; - layout_candidate(uic); - gtk_widget_show(uic->cwin.top_win); + uim_cand_win_gtk_layout(uic->cwin, topwin_x, topwin_y); + gtk_widget_show(GTK_WIDGET(uic->cwin)); if (uic->win) { GdkWindow *toplevel; + toplevel = gdk_window_get_toplevel(uic->win); gdk_window_add_filter(toplevel, toplevel_window_candidate_cb, @@ -977,56 +703,51 @@ } + /* This function called by libuim. Selected by keyboard, etc. */ static void cand_select_cb(void *ptr, int index) { IMUIMContext *uic = (IMUIMContext *)ptr; + gint topwin_x, topwin_y; - /* uim_set_candidate_index(uic->uc, index); */ - uic->cwin.candidate_index = index; - - layout_candidate(uic); + gdk_window_get_origin(uic->win, &topwin_x, &topwin_y); + uim_cand_win_gtk_layout(uic->cwin, topwin_x, topwin_y); + g_signal_handlers_block_by_func(uic->cwin, (gpointer) index_changed_cb, uic); + uim_cand_win_gtk_set_index(uic->cwin, index); + g_signal_handlers_unblock_by_func(uic->cwin, (gpointer) index_changed_cb, uic); } static void cand_shift_page_cb(void *ptr, int direction) { IMUIMContext *uic = (IMUIMContext *)ptr; + gint topwin_x, topwin_y; - if(direction){ - if(uic->cwin.nr_candidates < uic->cwin.candidate_index + uic->cwin.display_limit ) - uic->cwin.candidate_index = 0; - else - uic->cwin.candidate_index += uic->cwin.display_limit; - } - else { - if(uic->cwin.candidate_index - uic->cwin.display_limit < 0) - uic->cwin.candidate_index = uic->cwin.nr_candidates - 1; - else - uic->cwin.candidate_index -= uic->cwin.display_limit; - } - layout_candidate(uic); - uim_set_candidate_index(uic->uc, uic->cwin.candidate_index); + gdk_window_get_origin(uic->win, &topwin_x, &topwin_y); + uim_cand_win_gtk_layout(uic->cwin, topwin_x, topwin_y); + g_signal_handlers_block_by_func(uic->cwin, (gpointer) index_changed_cb, uic); + uim_cand_win_gtk_shift_page(uic->cwin, direction); + uim_set_candidate_index(uic->uc, uic->cwin->candidate_index); + g_signal_handlers_unblock_by_func(uic->cwin, (gpointer) index_changed_cb, uic); } static void cand_deactivate_cb(void *ptr) { IMUIMContext *uic = (IMUIMContext *)ptr; - if(uic->cwin.top_win) { - gtk_widget_hide(uic->cwin.top_win); - } - if (uic->win) { + uic->cwin_is_active = FALSE; + + if(uic->cwin) { GdkWindow *toplevel; + + gtk_widget_hide(GTK_WIDGET(uic->cwin)); + uim_cand_win_gtk_clear_candidates(uic->cwin); toplevel = gdk_window_get_toplevel(uic->win); gdk_window_remove_filter(toplevel, toplevel_window_candidate_cb, uic); } - - /* uic->nr_psegs = 0; */ - uic->cwin.is_active = 0; } @@ -1036,15 +757,6 @@ GObject *obj = g_object_new(type_im_uim, NULL); IMUIMContext *uic = IM_UIM_CONTEXT(obj); - uic->win = NULL; - uic->menu = NULL; - uic->pseg = 0; - uic->nr_psegs = 0; - - uic->cwin.top_win = NULL; - uic->cwin.view = NULL; - uic->cwin.select_count = 0; - if (!strncmp(context_id, "uim-", 4)) { context_id = &context_id[4]; } @@ -1075,7 +787,7 @@ cand_select_cb, cand_shift_page_cb, cand_deactivate_cb); - + uim_prop_list_update(uic->uc); @@ -1136,25 +848,25 @@ im_uim_parse_helper_str(char *str) { gchar **lines; - + if(focused_context && !disable_focused_context) { - if(strncmp("prop_list_get", str, 13) == 0){ + if(strstr(str, "prop_list_get") == str){ uim_prop_list_update(focused_context->uc); - } else if(strncmp("prop_label_get", str, 14) == 0) { + } else if(strstr(str, "prop_label_get") == str) { uim_prop_label_update(focused_context->uc); - } else if(strncmp("prop_activate", str, 13) == 0) { + } else if(strstr(str, "prop_activate") == str) { lines = g_strsplit(str, "\n", 0); if(lines && lines[0]) { uim_prop_activate(focused_context->uc, lines[1]); g_strfreev(lines); } - } else if(strncmp("prop_update_custom", str, 18) == 0) { + } else if(strstr(str, "prop_update_custom") == str) { lines = g_strsplit(str, "\n", 0); if(lines && lines[0] && lines[1] && lines[2]) { uim_prop_update_custom(focused_context->uc, lines[1], lines[2]); g_strfreev(lines); } - } else if(strncmp("focus_in", str, 8) == 0) { + } else if(strstr(str, "focus_in") == str) { disable_focused_context = TRUE; /* We shouldn't do "focused_context = NULL" here, because some window manager has some focus related bugs. */ @@ -1167,7 +879,6 @@ helper_read_cb(gpointer p, int fd, GdkInputCondition c) { char *tmp; - uim_helper_read_proc(fd); while ((tmp = uim_helper_get_message())) { im_uim_parse_helper_str(tmp); @@ -1183,14 +894,14 @@ } /* XXX:This is not a recommended way!! */ -gboolean +static gboolean uim_key_snoop(GtkWidget *grab_widget, GdkEventKey *key, gpointer data) { if (focused_context) { int rv; int kv = convert_keyval(key->keyval); int mod = convert_modifier(key->state); - + if (key->type == GDK_KEY_RELEASE) { rv = uim_release_key(focused_context->uc, kv, mod); } else { @@ -1214,6 +925,7 @@ GTK_TYPE_IM_CONTEXT, "GtkIMContextUIM", &class_info, 0); + uim_cand_win_gtk_register_type(type_module); /* XXX:This is not recommended way!! */ snooper_id = gtk_key_snooper_install( (GtkKeySnoopFunc)uim_key_snoop, NULL ); diff -Nur trunk-bak/gtk/uim-cand-win-gtk.c trunk/gtk/uim-cand-win-gtk.c --- trunk-bak/gtk/uim-cand-win-gtk.c 1970-01-01 09:00:00.000000000 +0900 +++ trunk/gtk/uim-cand-win-gtk.c 2004-07-27 12:32:32.000000000 +0900 @@ -0,0 +1,568 @@ +/* + + copyright (c) 2003,2004 uim Project http://uim.freedesktop.org/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ + +#include "uim-cand-win-gtk.h" +#include +#include + +#define NR_CANDIDATES 20 /* FIXME! not used yet */ + +enum { + INDEX_CHANGED_SIGNAL, + NR_SIGNALS +}; + +enum { + TERMINATOR = -1, + COLUMN_HEADING, + COLUMN_CANDIDATE +}; + +static void uim_cand_win_gtk_init (UIMCandWinGtk *cwin); +static void uim_cand_win_gtk_class_init (UIMCandWinGtkClass *klass); +static void uim_cand_win_gtk_dispose (GObject *obj); + +static gboolean tree_selection_changed (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer data); +static gboolean +tree_view_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data); + +static GType cand_win_type = 0; +static GTypeInfo const object_info = { + sizeof (UIMCandWinGtkClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) uim_cand_win_gtk_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (UIMCandWinGtk), + 0, /* n_preallocs */ + (GInstanceInitFunc) uim_cand_win_gtk_init, +}; + +static GtkWindowClass *parent_class = NULL; +static gint cand_win_gtk_signals[NR_SIGNALS] = {0}; + +GType +uim_cand_win_gtk_get_type(void) +{ + if (!cand_win_type) + cand_win_type = g_type_register_static(GTK_TYPE_WINDOW, "UIMCandWinGtk", + &object_info, (GTypeFlags)0); + return cand_win_type; +} + +void +uim_cand_win_gtk_register_type(GTypeModule *module) +{ + if (!cand_win_type) + cand_win_type = g_type_module_register_type(module, + GTK_TYPE_WINDOW, + "UIMCandWinGtk", + &object_info, 0); +} + +static void +uim_cand_win_gtk_class_init (UIMCandWinGtkClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + object_class->dispose = uim_cand_win_gtk_dispose; + + cand_win_gtk_signals[INDEX_CHANGED_SIGNAL] + = g_signal_new("index-changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(UIMCandWinGtkClass, index_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +uim_cand_win_gtk_init (UIMCandWinGtk *cwin) +{ + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkWidget *vbox; + gchar *leftp; + GtkTreeSelection *selection; + + uim_init(); + + gtk_window_set_default_size(GTK_WINDOW(cwin), 80, -1); + + /* init struct */ + cwin->scrolled_window = gtk_scrolled_window_new(NULL, NULL); + cwin->view = gtk_tree_view_new(); + cwin->num_label = gtk_label_new(""); + + cwin->stores = g_ptr_array_new(); + + cwin->nr_candidates = 0; + cwin->display_limit = 0; + cwin->candidate_index = -1; + cwin->page_index = -1; + + cwin->cursor.x = cwin->cursor.y = 0; + cwin->cursor.width = cwin->cursor.height = 0; + + leftp = uim_symbol_value_str("candidate-window-position"); + if (leftp && !strcmp(leftp, "left")) { + cwin->left = TRUE; + } else { + cwin->left = FALSE; + } + g_free(leftp); + + + /* build window */ + vbox = gtk_vbox_new(FALSE, 0); + + gtk_box_pack_start(GTK_BOX(vbox), cwin->scrolled_window, TRUE, TRUE, 0); + uim_cand_win_gtk_set_scrollable(cwin, FALSE); + + gtk_container_add(GTK_CONTAINER(cwin->scrolled_window), cwin->view); + gtk_box_pack_start(GTK_BOX(vbox), cwin->num_label, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(cwin), vbox); + gtk_container_set_border_width(GTK_CONTAINER(cwin), 1); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(cwin->view)); + + gtk_tree_selection_set_select_function(selection, + tree_selection_changed, + cwin, + NULL); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("No", + renderer, + "text", COLUMN_HEADING, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(cwin->view), column); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("Text", + renderer, + "text", COLUMN_CANDIDATE, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(cwin->view), column); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(cwin->view), TRUE); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cwin->view), FALSE); + + g_signal_connect(G_OBJECT(cwin->view), "button-press-event", + G_CALLBACK(tree_view_button_press), cwin); + + + /* show children */ + gtk_widget_show(cwin->scrolled_window); + gtk_widget_show(cwin->view); + gtk_widget_show(cwin->num_label); + gtk_widget_show(vbox); +} + +static void +uim_cand_win_gtk_dispose (GObject *obj) +{ + UIMCandWinGtk *cwin; + + g_return_if_fail(UIM_IS_CAND_WIN_GTK(obj)); + + cwin = UIM_CAND_WIN_GTK(obj); + + if (cwin->stores) { + guint i; + + for (i = 0; i < cwin->stores->len; i++) + g_object_unref(G_OBJECT(cwin->stores->pdata[i])); + g_ptr_array_free(cwin->stores, TRUE); + cwin->stores = NULL; + } + + if (G_OBJECT_CLASS (parent_class)->dispose) + G_OBJECT_CLASS (parent_class)->dispose(obj); +} + +UIMCandWinGtk * +uim_cand_win_gtk_new (void) +{ + GObject *obj = g_object_new(UIM_TYPE_CAND_WIN_GTK, + "type", GTK_WINDOW_POPUP, + NULL); + return UIM_CAND_WIN_GTK(obj); +} + +static void +update_label(UIMCandWinGtk *cwin) +{ + char label_str[20]; + + if (cwin->candidate_index >= 0) + g_snprintf(label_str, sizeof(label_str), "%d / %d", + cwin->candidate_index + 1 , cwin->nr_candidates); + else + g_snprintf(label_str, sizeof(label_str), "- / %d", + cwin->nr_candidates); + + gtk_label_set_text(GTK_LABEL(cwin->num_label), label_str); +} + +static gboolean +tree_selection_changed(GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer data) +{ + UIMCandWinGtk *cwin = data; + gint *indicies; + gint idx; + + if (!cwin) + return TRUE; + + indicies = gtk_tree_path_get_indices(path); + g_return_val_if_fail(indicies, TRUE); + idx = *indicies + cwin->display_limit * cwin->page_index; + + if (!path_currently_selected && cwin->candidate_index != idx) { + cwin->candidate_index = idx; + g_signal_emit(G_OBJECT(cwin), + cand_win_gtk_signals[INDEX_CHANGED_SIGNAL], 0); + + } + + update_label(cwin); + + return TRUE; +} + +static gboolean +tree_view_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + UIMCandWinGtk *cwin; + GtkTreePath *path; + gboolean exist, retval = FALSE; + gint *indicies; + + g_return_val_if_fail(GTK_IS_TREE_VIEW(widget), FALSE); + g_return_val_if_fail(UIM_CAND_WIN_GTK(data), FALSE); + + cwin = UIM_CAND_WIN_GTK(data); + + exist = gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), + event->x, event->y, + &path, NULL, NULL, NULL); + if (!exist) + return FALSE; + + indicies = gtk_tree_path_get_indices(path); + + /* don't relay button press event to empty row */ + if (cwin->display_limit * cwin->page_index + *indicies >= cwin->nr_candidates) + retval = TRUE; + + gtk_tree_path_free(path); + + return retval; +} + +void +uim_cand_win_gtk_set_candidates(UIMCandWinGtk *cwin, + guint display_limit, + GSList *candidates) +{ + guint i, nr_stores = 1; + + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + + if (cwin->stores == NULL) + cwin->stores = g_ptr_array_new(); + + /* remove old data */ + if (cwin->stores->len > 0) { + for (i = 0; i < cwin->stores->len; i++) + g_object_unref(cwin->stores->pdata[i]); + g_ptr_array_remove_range(cwin->stores, 0, cwin->stores->len); + } + + cwin->candidate_index = -1; + cwin->nr_candidates = g_slist_length(candidates); + cwin->display_limit = display_limit; + + if (candidates == NULL) + return; + + /* calculate number of GtkListStores to create */ + if (display_limit) { + nr_stores = cwin->nr_candidates / display_limit; + if (cwin->nr_candidates > display_limit * nr_stores) + nr_stores++; + } + + /* create GtkListStores, and set candidates */ + for (i = 0; i < nr_stores; i++) { + GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + GSList *node; + guint j; + + g_ptr_array_add(cwin->stores, store); + + /* set candidates */ + for (j = i * display_limit, node = g_slist_nth(candidates, j); + display_limit ? j < display_limit * (i + 1) : j < cwin->nr_candidates; + j++, node = g_slist_next(node)) + { + GtkTreeIter ti; + + + if (node) { + uim_candidate cand = node->data; + gtk_list_store_append(store, &ti); + gtk_list_store_set(store, &ti, + COLUMN_HEADING, uim_candidate_get_heading_label(cand), + COLUMN_CANDIDATE, uim_candidate_get_cand_str(cand), + TERMINATOR); + } else { +#if 1 + /* + * 2004-07-22 Takuro Ashie + * + * FIXME!: + * I think we shoudn't set any data for empty row. + * It may cause incorrect action. + */ + gtk_list_store_append(store, &ti); + gtk_list_store_set(store, &ti, + COLUMN_HEADING, "", + COLUMN_CANDIDATE, "", + TERMINATOR); +#endif + } + } + } + + uim_cand_win_gtk_set_page(cwin, 0); +} + +void +uim_cand_win_gtk_clear_candidates(UIMCandWinGtk *cwin) +{ + uim_cand_win_gtk_set_candidates(cwin, 0, NULL); +} + +guint +uim_cand_win_gtk_get_nr_candidates(UIMCandWinGtk *cwin) +{ + g_return_val_if_fail(UIM_IS_CAND_WIN_GTK(cwin), 0); + + return cwin->nr_candidates; +} + +gint +uim_cand_win_gtk_get_index(UIMCandWinGtk *cwin) +{ + g_return_val_if_fail(UIM_IS_CAND_WIN_GTK(cwin), -1); + + return cwin->candidate_index; +} + +void +uim_cand_win_gtk_set_index(UIMCandWinGtk *cwin, gint index) +{ + gint new_page = 0; + + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + + if (index < 0) + cwin->candidate_index = cwin->nr_candidates - 1; + else if ((guint) index >= cwin->nr_candidates) + cwin->candidate_index = 0; + else + cwin->candidate_index = index; + + if (cwin->display_limit) + new_page = cwin->candidate_index / cwin->display_limit; + + if (cwin->page_index != new_page) + uim_cand_win_gtk_set_page(cwin, new_page); + + if (cwin->candidate_index >= 0) { + GtkTreePath *path; + gint pos = index; + + if (cwin->display_limit) + pos = cwin->candidate_index % cwin->display_limit; + + path = gtk_tree_path_new_from_indices(pos, -1); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(cwin->view), + path, NULL, FALSE); + gtk_tree_path_free(path); + + } else { + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cwin->view)); + + gtk_tree_selection_unselect_all(selection); + } +} + +guint +uim_cand_win_gtk_get_nr_pages(UIMCandWinGtk *cwin) +{ + g_return_val_if_fail(UIM_IS_CAND_WIN_GTK(cwin), 0); + g_return_val_if_fail(UIM_IS_CAND_WIN_GTK(cwin->stores), 0); + + return cwin->stores->len; +} + +gint +uim_cand_win_gtk_get_page(UIMCandWinGtk *cwin) +{ + g_return_val_if_fail(UIM_IS_CAND_WIN_GTK(cwin), -1); + + return cwin->page_index; +} + +void +uim_cand_win_gtk_set_page(UIMCandWinGtk *cwin, gint page) +{ + guint len, new_page; + guint new_index; + + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + g_return_if_fail(cwin->stores); + + len = cwin->stores->len; + g_return_if_fail(len); + + if (page < 0) { + gtk_tree_view_set_model(GTK_TREE_VIEW(cwin->view), + GTK_TREE_MODEL(cwin->stores->pdata[len - 1])); + new_page = len - 1; + } else if (page >= (gint) len) { + gtk_tree_view_set_model(GTK_TREE_VIEW(cwin->view), + GTK_TREE_MODEL(cwin->stores->pdata[0])); + new_page = 0; + } else { + gtk_tree_view_set_model(GTK_TREE_VIEW(cwin->view), + GTK_TREE_MODEL(cwin->stores->pdata[page])); + new_page = page; + } + + cwin->page_index = new_page; + + if (cwin->display_limit) { + if (cwin->candidate_index >= 0) + new_index + = (new_page * cwin->display_limit) + (cwin->candidate_index % cwin->display_limit); + else + new_index = new_page * cwin->display_limit; + } else { + new_index = cwin->candidate_index; + } + + if (new_index >= cwin->nr_candidates) + new_index = cwin->nr_candidates - 1; + + uim_cand_win_gtk_set_index(cwin, new_index); +} + +void +uim_cand_win_gtk_set_scrollable(UIMCandWinGtk *cwin, gboolean scrollable) +{ + GtkPolicyType policy = scrollable ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER; + + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cwin->scrolled_window), + GTK_POLICY_NEVER, policy); +} + +void +uim_cand_win_gtk_shift_page(UIMCandWinGtk *cwin, gboolean forward) +{ + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + + if (forward) { + uim_cand_win_gtk_set_page(cwin, cwin->page_index + 1); + } else { + uim_cand_win_gtk_set_page(cwin, cwin->page_index - 1); + } +} + +void +uim_cand_win_gtk_layout(UIMCandWinGtk *cwin, gint topwin_x, int topwin_y) +{ + GtkRequisition req; + int x, y; + int sc_he, cw_he; /*screen height, candidate window height*/ + int sc_wi, cw_wi; + + g_return_if_fail(UIM_IS_CAND_WIN_GTK(cwin)); + + /* FIXME! enable to shrink the window */ + gtk_widget_size_request(GTK_WIDGET(cwin), &req); + cw_wi = req.width; + cw_he = req.height; + + sc_he = gdk_screen_get_height(gdk_screen_get_default ()); + sc_wi = gdk_screen_get_width (gdk_screen_get_default ()); + + if (sc_wi < topwin_x + cwin->cursor.x + cw_he) { + x = topwin_x + cwin->cursor.x - cw_wi; + } else { + x = topwin_x + cwin->cursor.x; + } + + if (sc_he < topwin_y + cwin->cursor.y + cwin->cursor.height + cw_he ) { + y = topwin_y + cwin->cursor.y - cw_he; + } else { + y = topwin_y + cwin->cursor.y + cwin->cursor.height; + } + + gtk_window_move(GTK_WINDOW(cwin), x, y ); +} + +void +uim_cand_win_gtk_set_cursor_location(UIMCandWinGtk *cwin, GdkRectangle *area) +{ + g_return_if_fail(UIM_CAND_WIN_GTK(cwin)); + g_return_if_fail(area); + + cwin->cursor = *area; +} diff -Nur trunk-bak/gtk/uim-cand-win-gtk.h trunk/gtk/uim-cand-win-gtk.h --- trunk-bak/gtk/uim-cand-win-gtk.h 1970-01-01 09:00:00.000000000 +0900 +++ trunk/gtk/uim-cand-win-gtk.h 2004-07-27 12:32:32.000000000 +0900 @@ -0,0 +1,109 @@ +/* + + Copyright (c) 2003,2004 uim Project http://uim.freedesktop.org/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ + +#ifndef _uim_cand_win_gtk_h_included_ +#define _uim_cand_win_gtk_h_included_ + +#include + +G_BEGIN_DECLS + +#define UIM_TYPE_CAND_WIN_GTK (uim_cand_win_gtk_get_type ()) +#define UIM_CAND_WIN_GTK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UIM_TYPE_CAND_WIN_GTK, UIMCandWinGtk)) +#define UIM_CAND_WIN_GTK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UIM_TYPE_CAND_WIN_GTK, UIMCandWinGtkClass)) +#define UIM_IS_CAND_WIN_GTK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UIM_TYPE_CAND_WIN_GTK)) +#define UIM_IS_CAND_WIN_GTK_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE ((klass), UIM_TYPE_CAND_WIN_GTK)) +#define UIM_CAND_WIN_GTK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UIM_TYPE_CAND_WIN_GTK, UIMCandWinGtkClass)) + +typedef struct _UIMCandWinGtk UIMCandWinGtk; +typedef struct _UIMCandWinGtkClass UIMCandWinGtkClass; + +struct _UIMCandWinGtk { + GtkWindow parent; + + GtkWidget *scrolled_window; + GtkWidget *view; + GtkWidget *num_label; + + GPtrArray *stores; + + guint nr_candidates; + guint display_limit; + gint candidate_index; + gint page_index; + + gboolean left; + + GdkRectangle cursor; +}; + +struct _UIMCandWinGtkClass { + GtkWindowClass parent_class; + + /* signals */ + void (*index_changed) (UIMCandWinGtkClass *cwin); +}; + + +void uim_cand_win_gtk_register_type (GTypeModule *module); +GType uim_cand_win_gtk_get_type (void); +UIMCandWinGtk *uim_cand_win_gtk_new (void); + +void uim_cand_win_gtk_set_candidates (UIMCandWinGtk *cwin, + guint disp_limit, + GSList *candidates); +void uim_cand_win_gtk_clear_candidates (UIMCandWinGtk *cwin); +guint uim_cand_win_gtk_get_nr_candidates (UIMCandWinGtk *cwin); +gint uim_cand_win_gtk_get_index (UIMCandWinGtk *cwin); +void uim_cand_win_gtk_set_index (UIMCandWinGtk *cwin, + gint index); + +guint uim_cand_win_gtk_get_nr_pages (UIMCandWinGtk *cwin); +gint uim_cand_win_gtk_get_page (UIMCandWinGtk *cwin); +void uim_cand_win_gtk_set_page (UIMCandWinGtk *cwin, + gint page); +void uim_cand_win_gtk_shift_page (UIMCandWinGtk *cwin, + gboolean forward); + +void uim_cand_win_gtk_set_scrollable (UIMCandWinGtk *cwin, + gboolean scrollable); + +void uim_cand_win_gtk_layout (UIMCandWinGtk *cwin, + gint topwin_x, + gint topwin_y); +void uim_cand_win_gtk_set_cursor_location (UIMCandWinGtk *cwin, + GdkRectangle *area); + +G_END_DECLS + +#endif /*_uim_cand_win_gtk_h_included_ */