static void fcitx_im_context_focus_out(GtkIMContext *context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_out"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (!fcitxcontext->has_focus) { return; } g_assert (context == _focus_im_context); g_object_remove_weak_pointer ((GObject *) context, (gpointer *) &_focus_im_context); _focus_im_context = NULL; fcitxcontext->has_focus = false; if (fcitx_client_is_valid(fcitxcontext->client)) { fcitx_client_focus_out(fcitxcontext->client); } fcitxcontext->cursor_pos = 0; if (fcitxcontext->preedit_string != NULL) { g_free(fcitxcontext->preedit_string); fcitxcontext->preedit_string = NULL; g_signal_emit(fcitxcontext, _signal_preedit_changed_id, 0); g_signal_emit(fcitxcontext, _signal_preedit_end_id, 0); } gtk_im_context_focus_out(fcitxcontext->slave); return; }
static void fcitx_im_context_finalize(GObject *obj) { FcitxLog(LOG_LEVEL, "fcitx_im_context_finalize"); FcitxIMContext *context = FCITX_IM_CONTEXT(obj); fcitx_im_context_set_client_window(GTK_IM_CONTEXT(context), NULL); g_object_unref(context->client); context->client = NULL; if (context->slave) { g_object_unref(context->slave); context->slave = NULL; } if (context->preedit_string) g_free(context->preedit_string); context->preedit_string = NULL; if (context->attrlist) pango_attr_list_unref(context->attrlist); context->attrlist = NULL; G_OBJECT_CLASS(parent_class)->finalize (obj); }
static void fcitx_im_context_focus_out(ClutterIMContext *context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_out"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (!fcitxcontext->has_focus) { return; } fcitxcontext->has_focus = false; if (IsFcitxIMClientValid(fcitxcontext->client)) { FcitxIMClientFocusOut(fcitxcontext->client); } if (fcitxcontext->preedit_string != NULL) g_free(fcitxcontext->preedit_string); fcitxcontext->preedit_string = NULL; fcitxcontext->cursor_pos = 0; g_signal_emit(fcitxcontext, _signal_preedit_changed_id, 0); g_signal_emit(fcitxcontext, _signal_preedit_end_id, 0); return; }
static void fcitx_im_context_set_client_window(GtkIMContext *context, GdkWindow *client_window) { FcitxLog(LOG_LEVEL, "fcitx_im_context_set_client_window"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); set_ic_client_window(fcitxcontext, client_window); }
void _fcitx_im_context_forward_key_cb(FcitxClient* im, guint keyval, guint state, gint type, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_forward_key_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); FcitxKeyEventType tp = (FcitxKeyEventType) type; GdkEventKey* event = _create_gdk_event(context, keyval, state, tp); event->state |= FcitxKeyState_IgnoredMask; gdk_event_put((GdkEvent *)event); gdk_event_free((GdkEvent *)event); }
static void fcitx_im_context_set_use_preedit(ClutterIMContext *context, gboolean use_preedit) { FcitxLog(LOG_LEVEL, "fcitx_im_context_set_use_preedit"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); fcitxcontext->use_preedit = use_preedit; _fcitx_im_context_set_capacity(fcitxcontext); }
static void fcitx_im_context_reset(ClutterIMContext *context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_reset"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (IsFcitxIMClientValid(fcitxcontext->client)) { FcitxIMClientReset(fcitxcontext->client); } }
static void _fcitx_im_context_delete_surrounding_text_cb (FcitxClient* im, gint offset_from_cursor, guint nchars, void* user_data) { FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); gboolean return_value; g_signal_emit (context, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value); }
static void fcitx_im_context_set_use_preedit(GtkIMContext *context, gboolean use_preedit) { FcitxLog(LOG_LEVEL, "fcitx_im_context_set_use_preedit"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); fcitxcontext->use_preedit = use_preedit; _fcitx_im_context_set_capacity(fcitxcontext, FALSE); gtk_im_context_set_use_preedit(fcitxcontext->slave, use_preedit); }
static void fcitx_im_context_reset(GtkIMContext *context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_reset"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitx_client_is_valid(fcitxcontext->client)) { fcitx_client_reset(fcitxcontext->client); } gtk_im_context_reset(fcitxcontext->slave); }
void _fcitx_im_context_close_im_cb(FcitxClient* im, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_close_im_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); if (context->preedit_string != NULL) g_free(context->preedit_string); context->preedit_string = NULL; context->cursor_pos = 0; g_signal_emit(context, _signal_preedit_changed_id, 0); g_signal_emit(context, _signal_preedit_end_id, 0); }
static void fcitx_im_context_finalize(GObject *obj) { FcitxLog(LOG_LEVEL, "fcitx_im_context_finalize"); FcitxIMContext *context = FCITX_IM_CONTEXT(obj); FcitxIMClientClose(context->client); context->client = NULL; if (context->preedit_string) g_free(context->preedit_string); context->preedit_string = NULL; }
void fcitx_im_context_hide(ClutterIMContext* context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_out"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (IsFcitxIMClientValid(fcitxcontext->client) && IsFcitxIMClientEnabled(fcitxcontext->client)) { FcitxIMClientCloseIC(fcitxcontext->client); } if (fcitxcontext->has_focus) { clutter_im_context_focus_out(context); } }
void _fcitx_im_context_connect_cb(FcitxIMClient* client, void* user_data) { FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); if (IsFcitxIMClientValid(client)) { FcitxIMClientConnectSignal(client, G_CALLBACK(_fcitx_im_context_enable_im_cb), G_CALLBACK(_fcitx_im_context_close_im_cb), G_CALLBACK(_fcitx_im_context_commit_string_cb), G_CALLBACK(_fcitx_im_context_forward_key_cb), G_CALLBACK(_fcitx_im_context_update_preedit_cb), context, NULL); _fcitx_im_context_set_capacity(context); } }
static void _fcitx_im_context_update_preedit_cb(DBusGProxy* proxy, char* str, int cursor_pos, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); gboolean visible = false; if (context->preedit_string != NULL) { if (strlen(context->preedit_string) != 0) visible = true; g_free(context->preedit_string); context->preedit_string = NULL; } context->preedit_string = g_strdup(str); char* tempstr = g_strndup(str, cursor_pos); context->cursor_pos = fcitx_utf8_strlen(tempstr); g_free(tempstr); gboolean new_visible = false; if (context->preedit_string != NULL) { if (strlen(context->preedit_string) != 0) new_visible = true; } gboolean flag = new_visible != visible; if (new_visible) { if (flag) { /* invisible => visible */ g_signal_emit(context, _signal_preedit_start_id, 0); } g_signal_emit(context, _signal_preedit_changed_id, 0); } else { if (flag) { /* visible => invisible */ g_signal_emit(context, _signal_preedit_changed_id, 0); g_signal_emit(context, _signal_preedit_end_id, 0); } else { /* still invisible */ /* do nothing */ } } g_signal_emit(context, _signal_preedit_changed_id, 0); }
static void fcitx_im_context_get_preedit_string(ClutterIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { FcitxLog(LOG_LEVEL, "fcitx_im_context_get_preedit_string"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (IsFcitxIMClientValid(fcitxcontext->client) && IsFcitxIMClientEnabled(fcitxcontext->client)) { if (str) { if (fcitxcontext->preedit_string) *str = strdup(fcitxcontext->preedit_string); else *str = strdup(""); } if (attrs) { *attrs = pango_attr_list_new(); if (str) { PangoAttribute *pango_attr; pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr->start_index = 0; pango_attr->end_index = strlen(*str); pango_attr_list_insert(*attrs, pango_attr); } } if (cursor_pos) *cursor_pos = fcitxcontext->cursor_pos; } else { if (str) { *str = g_strdup(""); } if (attrs) { *attrs = pango_attr_list_new(); } if (cursor_pos) *cursor_pos = 0; } return ; }
static void fcitx_im_context_set_cursor_location(ClutterIMContext *context, ClutterIMRectangle *area) { FcitxLog(LOG_LEVEL, "fcitx_im_context_set_cursor_location %d %d %d %d", area->x, area->y, area->height, area->width); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitxcontext->area.x == area->x && fcitxcontext->area.y == area->y && fcitxcontext->area.width == area->width && fcitxcontext->area.height == area->height) { return; } fcitxcontext->area = *area; if (IsFcitxIMClientValid(fcitxcontext->client)) { _set_cursor_location_internal(fcitxcontext); } return; }
static void fcitx_im_context_focus_in(GtkIMContext *context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_in"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitxcontext->has_focus) return; _fcitx_im_context_set_capacity(fcitxcontext, FALSE); fcitxcontext->has_focus = true; if (_focus_im_context != NULL) { g_assert (_focus_im_context != context); gtk_im_context_focus_out (_focus_im_context); g_assert (_focus_im_context == NULL); } if (fcitx_client_is_valid(fcitxcontext->client)) { fcitx_client_focus_in(fcitxcontext->client); } gtk_im_context_focus_in(fcitxcontext->slave); /* set_cursor_location_internal() will get origin from X server, * it blocks UI. So delay it to idle callback. */ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) _set_cursor_location_internal, g_object_ref(fcitxcontext), (GDestroyNotify) g_object_unref); _request_surrounding_text (fcitxcontext); g_object_add_weak_pointer ((GObject *) context, (gpointer *) &_focus_im_context); _focus_im_context = context; return; }
static void fcitx_im_context_get_preedit_string(GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos) { FcitxLog(LOG_LEVEL, "fcitx_im_context_get_preedit_string"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitx_client_is_valid(fcitxcontext->client)) { if (str) { if (fcitxcontext->preedit_string) *str = strdup(fcitxcontext->preedit_string); else *str = strdup(""); } if (attrs) { if (fcitxcontext->attrlist == NULL) { *attrs = pango_attr_list_new(); if (str) { PangoAttribute *pango_attr; pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr->start_index = 0; pango_attr->end_index = strlen(*str); pango_attr_list_insert(*attrs, pango_attr); } } else { *attrs = pango_attr_list_ref (fcitxcontext->attrlist); } } if (cursor_pos) *cursor_pos = fcitxcontext->cursor_pos; } else gtk_im_context_get_preedit_string(fcitxcontext->slave, str, attrs, cursor_pos); return ; }
static gboolean fcitx_im_context_filter_keypress(ClutterIMContext *context, ClutterKeyEvent *event) { FcitxLog(LOG_LEVEL, "fcitx_im_context_filter_keypress"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (G_UNLIKELY(event->modifier_state & FcitxKeyState_HandledMask)) return TRUE; if (G_UNLIKELY(event->modifier_state & FcitxKeyState_IgnoredMask)) return FALSE; if (IsFcitxIMClientValid(fcitxcontext->client) && fcitxcontext->has_focus) { if (!IsFcitxIMClientEnabled(fcitxcontext->client)) { if (!FcitxIsHotKey(event->keyval, event->modifier_state, FcitxIMClientGetTriggerKey(fcitxcontext->client))) return FALSE; } fcitxcontext->time = event->time; int ret = FcitxIMClientProcessKeySync(fcitxcontext->client, event->keyval, event->hardware_keycode, event->modifier_state, (event->type == CLUTTER_KEY_PRESS) ? (FCITX_PRESS_KEY) : (FCITX_RELEASE_KEY), event->time); if (ret <= 0) { event->modifier_state |= FcitxKeyState_IgnoredMask; return FALSE; } else { event->modifier_state |= FcitxKeyState_HandledMask; return TRUE; } } else { return FALSE; } return FALSE; }
static void fcitx_im_context_set_cursor_location(GtkIMContext *context, GdkRectangle *area) { FcitxLog(LOG_LEVEL, "fcitx_im_context_set_cursor_location %d %d %d %d", area->x, area->y, area->height, area->width); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitxcontext->area.x == area->x && fcitxcontext->area.y == area->y && fcitxcontext->area.width == area->width && fcitxcontext->area.height == area->height) { return; } fcitxcontext->area = *area; if (fcitx_client_is_valid(fcitxcontext->client)) { _set_cursor_location_internal(fcitxcontext); } gtk_im_context_set_cursor_location(fcitxcontext->slave, area); return; }
static void fcitx_im_context_set_surrounding (GtkIMContext *context, const gchar *text, gint len, gint cursor_index) { g_return_if_fail (context != NULL); g_return_if_fail (FCITX_IS_IM_CONTEXT (context)); g_return_if_fail (text != NULL); g_return_if_fail (strlen (text) >= len); g_return_if_fail (0 <= cursor_index && cursor_index <= len); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT (context); if (fcitx_client_is_valid(fcitxcontext->client) && !(fcitxcontext->capacity & CAPACITY_PASSWORD)) { guint cursor_pos; guint utf8_len; gchar *p; p = g_strndup (text, len); cursor_pos = g_utf8_strlen (p, cursor_index); utf8_len = g_utf8_strlen(p, len); guint anchor_pos = get_selection_anchor_point (fcitxcontext, cursor_pos, utf8_len); fcitx_client_set_surrounding_text (fcitxcontext->client, p, cursor_pos, anchor_pos); g_free (p); } gtk_im_context_set_surrounding (fcitxcontext->slave, text, len, cursor_index); }
static void fcitx_im_context_focus_in(ClutterIMContext *context) { FcitxLog(LOG_LEVEL, "fcitx_im_context_focus_in"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); if (fcitxcontext->has_focus) return; fcitxcontext->has_focus = true; if (IsFcitxIMClientValid(fcitxcontext->client)) { FcitxIMClientFocusIn(fcitxcontext->client); } /* set_cursor_location_internal() will get origin from X server, * it blocks UI. So delay it to idle callback. */ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) _set_cursor_location_internal, g_object_ref(fcitxcontext), (GDestroyNotify) g_object_unref); return; }
void _fcitx_im_context_commit_string_cb(DBusGProxy* proxy, char* str, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); g_signal_emit(context, _signal_commit_id, 0, str); }
void _fcitx_im_context_enable_im_cb(DBusGProxy* proxy, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_enable_im_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); FcitxIMClientSetEnabled(context->client, true); }
/* Copy from gdk */ static GdkEventKey * _create_gdk_event(FcitxIMContext *fcitxcontext, guint keyval, guint state, FcitxKeyEventType type ) { gunichar c = 0; gchar buf[8]; GdkEventKey *event = (GdkEventKey *)gdk_event_new((type == FCITX_RELEASE_KEY) ? GDK_KEY_RELEASE : GDK_KEY_PRESS); if (fcitxcontext && fcitxcontext->client_window) event->window = g_object_ref(fcitxcontext->client_window); /* The time is copied the latest value from the previous * GdkKeyEvent in filter_keypress(). * * We understand the best way would be to pass the all time value * to Fcitx functions process_key_event() and Fcitx DBus functions * ProcessKeyEvent() in IM clients and IM engines so that the * _create_gdk_event() could get the correct time values. * However it would causes to change many functions and the time value * would not provide the useful meanings for each Fcitx engines but just * pass the original value to ForwardKeyEvent(). * We use the saved value at the moment. * * Another idea might be to have the time implementation in X servers * but some Xorg uses clock_gettime() and others use gettimeofday() * and the values would be different in each implementation and * locale/remote X server. So probably that idea would not work. */ if (fcitxcontext) { event->time = fcitxcontext->time; } else { event->time = GDK_CURRENT_TIME; } event->send_event = FALSE; event->state = state; event->keyval = keyval; event->string = NULL; event->length = 0; event->hardware_keycode = 0; if (event->window) { #ifndef NEW_GDK_WINDOW_GET_DISPLAY GdkDisplay *display = gdk_display_get_default(); #else GdkDisplay *display = gdk_window_get_display(event->window); #endif GdkKeymap *keymap = gdk_keymap_get_for_display(display); GdkKeymapKey *keys; gint n_keys = 0; if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) { if (n_keys) event->hardware_keycode = keys[0].keycode; g_free(keys); } } event->group = 0; event->is_modifier = _key_is_modifier(keyval); #ifdef DEPRECATED_GDK_KEYSYMS if (keyval != GDK_VoidSymbol) #else if (keyval != GDK_KEY_VoidSymbol) #endif c = gdk_keyval_to_unicode(keyval); if (c) { gsize bytes_written; gint len; /* Apply the control key - Taken from Xlib */ if (event->state & GDK_CONTROL_MASK) { if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; else if (c == '2') { event->string = g_memdup("\0\0", 2); event->length = 1; buf[0] = '\0'; goto out; } else if (c >= '3' && c <= '7') c -= ('3' - '\033'); else if (c == '8') c = '\177'; else if (c == '/') c = '_' & 0x1F; } len = g_unichar_to_utf8(c, buf); buf[len] = '\0'; event->string = g_locale_from_utf8(buf, len, NULL, &bytes_written, NULL); if (event->string) event->length = bytes_written; #ifdef DEPRECATED_GDK_KEYSYMS } else if (keyval == GDK_Escape) { #else } else if (keyval == GDK_KEY_Escape) { #endif event->length = 1; event->string = g_strdup("\033"); } #ifdef DEPRECATED_GDK_KEYSYMS else if (keyval == GDK_Return || keyval == GDK_KP_Enter) { #else else if (keyval == GDK_KEY_Return || keyval == GDK_KEY_KP_Enter) { #endif event->length = 1; event->string = g_strdup("\r"); } if (!event->string) { event->length = 0; event->string = g_strdup(""); } out: return event; } static gboolean _key_is_modifier(guint keyval) { /* See gdkkeys-x11.c:_gdk_keymap_key_is_modifier() for how this * really should be implemented */ switch (keyval) { #ifdef DEPRECATED_GDK_KEYSYMS case GDK_Shift_L: case GDK_Shift_R: case GDK_Control_L: case GDK_Control_R: case GDK_Caps_Lock: case GDK_Shift_Lock: case GDK_Meta_L: case GDK_Meta_R: case GDK_Alt_L: case GDK_Alt_R: case GDK_Super_L: case GDK_Super_R: case GDK_Hyper_L: case GDK_Hyper_R: case GDK_ISO_Lock: case GDK_ISO_Level2_Latch: case GDK_ISO_Level3_Shift: case GDK_ISO_Level3_Latch: case GDK_ISO_Level3_Lock: case GDK_ISO_Group_Shift: case GDK_ISO_Group_Latch: case GDK_ISO_Group_Lock: return TRUE; #else case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: case GDK_KEY_Control_L: case GDK_KEY_Control_R: case GDK_KEY_Caps_Lock: case GDK_KEY_Shift_Lock: case GDK_KEY_Meta_L: case GDK_KEY_Meta_R: case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Super_L: case GDK_KEY_Super_R: case GDK_KEY_Hyper_L: case GDK_KEY_Hyper_R: case GDK_KEY_ISO_Lock: case GDK_KEY_ISO_Level2_Latch: case GDK_KEY_ISO_Level3_Shift: case GDK_KEY_ISO_Level3_Latch: case GDK_KEY_ISO_Level3_Lock: case GDK_KEY_ISO_Level5_Shift: case GDK_KEY_ISO_Level5_Latch: case GDK_KEY_ISO_Level5_Lock: case GDK_KEY_ISO_Group_Shift: case GDK_KEY_ISO_Group_Latch: case GDK_KEY_ISO_Group_Lock: return TRUE; #endif default: return FALSE; } } void _fcitx_im_context_connect_cb(FcitxClient* im, void* user_data) { FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); _fcitx_im_context_set_capacity(context, TRUE); /* set_cursor_location_internal() will get origin from X server, * it blocks UI. So delay it to idle callback. */ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) _set_cursor_location_internal, g_object_ref(context), (GDestroyNotify) g_object_unref); }
static gboolean fcitx_im_context_filter_keypress(GtkIMContext *context, GdkEventKey *event) { FcitxLog(LOG_LEVEL, "fcitx_im_context_filter_keypress"); FcitxIMContext *fcitxcontext = FCITX_IM_CONTEXT(context); /* check this first, since we use key snooper, most key will be handled. */ if (fcitx_client_is_valid(fcitxcontext->client) ) { /* XXX it is a workaround for some applications do not set client window. */ if (fcitxcontext->client_window == NULL && event->window != NULL) { gtk_im_context_set_client_window((GtkIMContext *)fcitxcontext, event->window); /* set_cursor_location_internal() will get origin from X server, * it blocks UI. So delay it to idle callback. */ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) _set_cursor_location_internal, g_object_ref(fcitxcontext), (GDestroyNotify) g_object_unref); } } if (G_UNLIKELY(event->state & FcitxKeyState_HandledMask)) return TRUE; if (G_UNLIKELY(event->state & FcitxKeyState_IgnoredMask)) return gtk_im_context_filter_keypress(fcitxcontext->slave, event); if (fcitx_client_is_valid(fcitxcontext->client) && fcitxcontext->has_focus) { _request_surrounding_text (fcitxcontext); fcitxcontext->time = event->time; if (_use_sync_mode) { int ret = fcitx_client_process_key_sync(fcitxcontext->client, event->keyval, event->hardware_keycode, event->state, (event->type == GDK_KEY_PRESS) ? (FCITX_PRESS_KEY) : (FCITX_RELEASE_KEY), event->time); if (ret <= 0) { event->state |= FcitxKeyState_IgnoredMask; return gtk_im_context_filter_keypress(fcitxcontext->slave, event); } else { event->state |= FcitxKeyState_HandledMask; return TRUE; } } else { ProcessKeyStruct* pks = g_malloc0(sizeof(ProcessKeyStruct)); pks->context = fcitxcontext; pks->event = (GdkEventKey *) gdk_event_copy((GdkEvent *) event); fcitx_client_process_key(fcitxcontext->client, _fcitx_im_context_process_key_cb, pks, event->keyval, event->hardware_keycode, event->state, (event->type == GDK_KEY_PRESS) ? (FCITX_PRESS_KEY) : (FCITX_RELEASE_KEY), event->time); event->state |= FcitxKeyState_HandledMask; return TRUE; } } else { return gtk_im_context_filter_keypress(fcitxcontext->slave, event); } return FALSE; }
static void _fcitx_im_context_update_formatted_preedit_cb(FcitxClient* im, GPtrArray* array, int cursor_pos, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); gboolean visible = false; if (context->preedit_string != NULL) { if (strlen(context->preedit_string) != 0) visible = true; g_free(context->preedit_string); context->preedit_string = NULL; } if (context->attrlist != NULL) { pango_attr_list_unref(context->attrlist); } context->attrlist = pango_attr_list_new(); GString* gstr = g_string_new(NULL); int i = 0; for (i = 0; i < array->len; i++) { size_t bytelen = strlen(gstr->str); FcitxPreeditItem* preedit = g_ptr_array_index(array, i); const gchar* s = preedit->string; gint type = preedit->type; PangoAttribute *pango_attr = NULL; if ((type & MSG_NOUNDERLINE) == 0) { pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr->start_index = bytelen; pango_attr->end_index = bytelen + strlen(s); pango_attr_list_insert(context->attrlist, pango_attr); } if (type & MSG_HIGHLIGHT) { gboolean hasColor; GdkColor fg; GdkColor bg; if (context->client_window) { GtkWidget *widget; gdk_window_get_user_data (context->client_window, (gpointer *)&widget); if (GTK_IS_WIDGET(widget)) { hasColor = true; GtkStyle* style = gtk_widget_get_style(widget); fg = style->text[GTK_STATE_SELECTED]; bg = style->bg[GTK_STATE_SELECTED]; } } if (!hasColor) { fg.red = 0xffff; fg.green = 0xffff; fg.blue = 0xffff; bg.red = 0x43ff; bg.green = 0xacff; bg.blue = 0xe8ff; } pango_attr = pango_attr_foreground_new(fg.red, fg.green, fg.blue); pango_attr->start_index = bytelen; pango_attr->end_index = bytelen + strlen(s); pango_attr_list_insert(context->attrlist, pango_attr); pango_attr = pango_attr_background_new(bg.red, bg.green, bg.blue); pango_attr->start_index = bytelen; pango_attr->end_index = bytelen + strlen(s); pango_attr_list_insert(context->attrlist, pango_attr); } gstr = g_string_append(gstr, s); } gchar* str = g_string_free(gstr, FALSE); context->preedit_string = g_strdup(str); char* tempstr = g_strndup(str, cursor_pos); context->cursor_pos = fcitx_utf8_strlen(tempstr); g_free(tempstr); gboolean new_visible = false; if (context->preedit_string != NULL) { if (strlen(context->preedit_string) != 0) new_visible = true; } gboolean flag = new_visible != visible; if (new_visible) { if (flag) { /* invisible => visible */ g_signal_emit(context, _signal_preedit_start_id, 0); } g_signal_emit(context, _signal_preedit_changed_id, 0); } else { if (flag) { /* visible => invisible */ g_signal_emit(context, _signal_preedit_changed_id, 0); g_signal_emit(context, _signal_preedit_end_id, 0); } else { /* still invisible */ /* do nothing */ } } g_signal_emit(context, _signal_preedit_changed_id, 0); }
FcitxIMContext * fcitx_im_context_new(void) { GObject *obj = g_object_new(FCITX_TYPE_IM_CONTEXT, NULL); return FCITX_IM_CONTEXT(obj); }