Beispiel #1
0
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;
}
Beispiel #3
0
/* 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;
}
Beispiel #4
0
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;
}