void bus_engine_proxy_process_key_event (BusEngineProxy *engine, guint keyval, guint keycode, guint state, GFunc return_cb, gpointer user_data) { g_assert (BUS_IS_ENGINE_PROXY (engine)); g_assert (return_cb); IBusPendingCall *pending = NULL; CallData *call_data; IBusError *error; gboolean retval; if (keycode != 0 && !BUS_DEFAULT_IBUS->use_sys_layout && engine->keymap != NULL) { guint t = ibus_keymap_lookup_keysym (engine->keymap, keycode, state); if (t != IBUS_VoidSymbol) { keyval = t; } } retval = ibus_proxy_call_with_reply ((IBusProxy *) engine, "ProcessKeyEvent", &pending, g_dbus_timeout, &error, G_TYPE_UINT, &keyval, G_TYPE_UINT, &keycode, G_TYPE_UINT, &state, G_TYPE_INVALID); if (!retval) { g_warning ("%s: %s", error->name, error->message); ibus_error_free (error); return_cb (GINT_TO_POINTER (FALSE), user_data); return; } call_data = g_slice_new0 (CallData); call_data->func = return_cb; call_data->user_data = user_data; g_object_ref (engine); call_data->engine = engine; retval = ibus_pending_call_set_notify (pending, (IBusPendingCallNotifyFunction) bus_engine_proxy_process_key_event_reply_cb, call_data, NULL); ibus_pending_call_unref (pending); if (!retval) { g_object_unref (call_data->engine); g_slice_free (CallData, call_data); g_warning ("%s : ProcessKeyEvent", DBUS_ERROR_NO_MEMORY); return_cb (GINT_TO_POINTER (FALSE), user_data); return; } }
/** * ibus_chewing_engine_keycode_to_keysym: * * Convert keycode to keysym. */ guint ibus_chewing_engine_keycode_to_keysym(IBusChewingEngine *self, guint keysym, guint keycode, guint modifiers){ /* Get system layout */ GValue gValue={0}; gboolean useSysKeyLayout=TRUE; if (ibus_chewing_config_get_value(self->config, "general", "use_system_keyboard_layout", &gValue)){ useSysKeyLayout=g_value_get_boolean(&gValue); } guint kSym; if (useSysKeyLayout && (!chewing_get_ChiEngMode(self->context))){ // English mode. kSym=keysym; }else{ /* ibus_keymap_lookup_keysym only handles keycode under 256 */ if ((kSym=ibus_keymap_lookup_keysym(self->keymap_us,keycode,modifiers))==IBUS_VoidSymbol){ kSym=keysym; } } return kSym; }
/* Note on AltGr (Level3 Shift) handling: While currently we expect AltGr == mod5, it would be better to not expect the modifier always be assigned to particular modX. However, it needs some code like: KeyCode altgr = XKeysymToKeycode (display, XK_ISO_Level3_Shift); XModifierKeymap *mods = XGetModifierMapping (display); for (i = 3; i < 8; i++) for (j = 0; j < mods->max_keypermod; j++) { KeyCode code = mods->modifiermap[i * mods->max_keypermod + j]; if (code == altgr) ... } Since IBus engines are supposed to be cross-platform, the code should go into IBus core, instead of ibus-m17n. */ MSymbol ibus_m17n_key_event_to_symbol (guint keycode, guint keyval, guint modifiers) { GString *keysym; MSymbol mkeysym = Mnil; guint mask = 0; IBusKeymap *keymap; if (keyval >= IBUS_Shift_L && keyval <= IBUS_Hyper_R) { return Mnil; } /* Here, keyval is already translated by IBUS_MOD5_MASK. Obtain the untranslated keyval from the underlying keymap and represent the translated keyval as the form "G-<untranslated keyval>", which m17n-lib accepts. */ if (modifiers & IBUS_MOD5_MASK) { keymap = ibus_keymap_get ("us"); keyval = ibus_keymap_lookup_keysym (keymap, keycode, modifiers & ~IBUS_MOD5_MASK); g_object_unref (keymap); } keysym = g_string_new (""); if (keyval >= IBUS_space && keyval <= IBUS_asciitilde) { gint c = keyval; if (keyval == IBUS_space && modifiers & IBUS_SHIFT_MASK) mask |= IBUS_SHIFT_MASK; if (modifiers & IBUS_CONTROL_MASK) { if (c >= IBUS_a && c <= IBUS_z) c += IBUS_A - IBUS_a; mask |= IBUS_CONTROL_MASK; } g_string_append_c (keysym, c); } else { mask |= modifiers & (IBUS_CONTROL_MASK | IBUS_SHIFT_MASK); g_string_append (keysym, ibus_keyval_name (keyval)); if (keysym->len == 0) { g_string_free (keysym, TRUE); return Mnil; } } mask |= modifiers & (IBUS_MOD1_MASK | IBUS_MOD5_MASK | IBUS_META_MASK | IBUS_SUPER_MASK | IBUS_HYPER_MASK); if (mask & IBUS_HYPER_MASK) { g_string_prepend (keysym, "H-"); } if (mask & IBUS_SUPER_MASK) { g_string_prepend (keysym, "s-"); } if (mask & IBUS_MOD5_MASK) { g_string_prepend (keysym, "G-"); } if (mask & IBUS_MOD1_MASK) { g_string_prepend (keysym, "A-"); } if (mask & IBUS_META_MASK) { g_string_prepend (keysym, "M-"); } if (mask & IBUS_CONTROL_MASK) { g_string_prepend (keysym, "C-"); } if (mask & IBUS_SHIFT_MASK) { g_string_prepend (keysym, "S-"); } mkeysym = msymbol (keysym->str); g_string_free (keysym, TRUE); return mkeysym; }
static gboolean ibus_hangul_engine_process_key_event (IBusEngine *engine, guint keyval, guint keycode, guint modifiers) { IBusHangulEngine *hangul = (IBusHangulEngine *) engine; guint mask; gboolean retval; const ucschar *str; if (modifiers & IBUS_RELEASE_MASK) return FALSE; // if we don't ignore shift keys, shift key will make flush the preedit // string. So you cannot input shift+key. // Let's think about these examples: // dlTek (2 set) // qhRdmaqkq (2 set) if (keyval == IBUS_Shift_L || keyval == IBUS_Shift_R) return FALSE; // If hanja key has any modifiers, we ignore that modifier keyval, // or we cannot make the hanja key work. // Because when we get the modifier key alone, we commit the // current preedit string. So after that, even if we get the // right hanja key event, we don't have preedit string to be changed // to hanja word. // See this bug: http://code.google.com/p/ibus/issues/detail?id=1036 if (hanja_key_list_has_modifier(&hanja_keys, keyval)) return FALSE; if (hanja_key_list_match(&hanja_keys, keyval, modifiers)) { if (hangul->hanja_list == NULL) { ibus_hangul_engine_update_lookup_table (hangul); } else { ibus_hangul_engine_hide_lookup_table (hangul); } return TRUE; } if (hangul->hanja_list != NULL) { retval = ibus_hangul_engine_process_candidate_key_event (hangul, keyval, modifiers); if (hangul->hanja_mode) { if (retval) return TRUE; } else { return TRUE; } } // If we've got a key event with some modifiers, commit current // preedit string and ignore this key event. // So, if you want to add some key event handler, put it // before this code. // Ignore key event with control, alt, super or mod5 mask = IBUS_CONTROL_MASK | IBUS_MOD1_MASK | IBUS_MOD3_MASK | IBUS_MOD4_MASK | IBUS_MOD5_MASK; if (modifiers & mask) { ibus_hangul_engine_flush (hangul); return FALSE; } if (keyval == IBUS_BackSpace) { retval = hangul_ic_backspace (hangul->context); if (!retval) { guint preedit_len = ustring_length (hangul->preedit); if (preedit_len > 0) { ustring_erase (hangul->preedit, preedit_len - 1, 1); retval = TRUE; } } ibus_hangul_engine_update_preedit_text (hangul); if (hangul->hanja_mode) { if (ibus_hangul_engine_has_preedit (hangul)) { ibus_hangul_engine_update_lookup_table (hangul); } else { ibus_hangul_engine_hide_lookup_table (hangul); } } } else { // We need to normalize the keyval to US qwerty keylayout, // because the korean input method is depend on the position of // each key, not the character. We make the keyval from keycode // as if the keyboard is US qwerty layout. Then we can assume the // keyval represent the position of the each key. // But if the hic is in transliteration mode, then we should not // normalize the keyval. bool is_transliteration_mode = hangul_ic_is_transliteration(hangul->context); if (!is_transliteration_mode) { if (keymap != NULL) keyval = ibus_keymap_lookup_keysym(keymap, keycode, modifiers); } // ignore capslock if (modifiers & IBUS_LOCK_MASK) { if (keyval >= 'A' && keyval <= 'z') { if (isupper(keyval)) keyval = tolower(keyval); else keyval = toupper(keyval); } } retval = hangul_ic_process (hangul->context, keyval); str = hangul_ic_get_commit_string (hangul->context); if (word_commit || hangul->hanja_mode) { const ucschar* hic_preedit; hic_preedit = hangul_ic_get_preedit_string (hangul->context); if (hic_preedit != NULL && hic_preedit[0] != 0) { ustring_append_ucs4 (hangul->preedit, str, -1); } else { IBusText *text; const ucschar* preedit; ustring_append_ucs4 (hangul->preedit, str, -1); if (ustring_length (hangul->preedit) > 0) { /* clear preedit text before commit */ ibus_hangul_engine_clear_preedit_text (hangul); preedit = ustring_begin (hangul->preedit); text = ibus_text_new_from_ucs4 ((gunichar*)preedit); ibus_engine_commit_text (engine, text); } ustring_clear (hangul->preedit); } } else { if (str != NULL && str[0] != 0) { IBusText *text; /* clear preedit text before commit */ ibus_hangul_engine_clear_preedit_text (hangul); text = ibus_text_new_from_ucs4 (str); ibus_engine_commit_text (engine, text); } } ibus_hangul_engine_update_preedit_text (hangul); if (hangul->hanja_mode) { ibus_hangul_engine_update_lookup_table (hangul); } if (!retval) ibus_hangul_engine_flush (hangul); } return retval; }