Exemplo n.º 1
0
uint32_t KeyboardEngine::processCompose(uint32_t keyval, uint32_t state) {
    // FIXME, should we check if state is 0?
    FCITX_UNUSED(state);
    if (!m_xkbComposeState) {
        return 0;
    }

    enum xkb_compose_feed_result result = xkb_compose_state_feed(m_xkbComposeState.get(), keyval);
    if (result == XKB_COMPOSE_FEED_IGNORED) {
        return 0;
    }

    enum xkb_compose_status status = xkb_compose_state_get_status(m_xkbComposeState.get());
    if (status == XKB_COMPOSE_NOTHING) {
        return 0;
    } else if (status == XKB_COMPOSE_COMPOSED) {
        char buffer[FCITX_UTF8_MAX_LENGTH + 1] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0'};
        int length = xkb_compose_state_get_utf8(m_xkbComposeState.get(), buffer, sizeof(buffer));
        xkb_compose_state_reset(m_xkbComposeState.get());
        if (length == 0) {
            return INVALID_COMPOSE_RESULT;
        }

        uint32_t c = 0;
        fcitx_utf8_get_char(buffer, &c);
        return c;
    } else if (status == XKB_COMPOSE_CANCELLED) {
        xkb_compose_state_reset(m_xkbComposeState.get());
    }

    return INVALID_COMPOSE_RESULT;
}
Exemplo n.º 2
0
/*
 * Handle key presses. Fixes state, then looks up the key symbol for the
 * given keycode, then looks up the key symbol (as UCS-2), converts it to
 * UTF-8 and stores it in the password array.
 *
 */
static void handle_key_press(xcb_key_press_event_t *event) {
    xkb_keysym_t ksym;
    char buffer[128];
    int n;
    bool ctrl;
    bool composed = false;

    ksym = xkb_state_key_get_one_sym(xkb_state, event->detail);
    ctrl = xkb_state_mod_name_is_active(xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED);

    /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */
    memset(buffer, '\0', sizeof(buffer));

    if (xkb_compose_state && xkb_compose_state_feed(xkb_compose_state, ksym) == XKB_COMPOSE_FEED_ACCEPTED) {
        switch (xkb_compose_state_get_status(xkb_compose_state)) {
        case XKB_COMPOSE_NOTHING:
            break;
        case XKB_COMPOSE_COMPOSING:
            return;
        case XKB_COMPOSE_COMPOSED:
            /* xkb_compose_state_get_utf8 doesn't include the terminating byte in the return value
            * as xkb_keysym_to_utf8 does. Adding one makes the variable n consistent. */
            n = xkb_compose_state_get_utf8(xkb_compose_state, buffer, sizeof(buffer)) + 1;
            ksym = xkb_compose_state_get_one_sym(xkb_compose_state);
            composed = true;
            break;
        case XKB_COMPOSE_CANCELLED:
            xkb_compose_state_reset(xkb_compose_state);
            return;
        }
    }

    if (!composed) {
        n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer));
    }

    switch (ksym) {
    case XKB_KEY_Return:
    case XKB_KEY_KP_Enter:
    case XKB_KEY_XF86ScreenSaver:
        if (pam_state == STATE_PAM_WRONG)
            return;

        if (skip_without_validation()) {
            clear_input();
            return;
        }
        password[input_position] = '\0';
        unlock_state = STATE_KEY_PRESSED;
        redraw_screen();
        input_done();
        skip_repeated_empty_password = true;
        return;
    default:
        skip_repeated_empty_password = false;
    }

    switch (ksym) {
    case XKB_KEY_u:
        if (ctrl) {
            DEBUG("C-u pressed\n");
            clear_input();
            return;
        }
        break;

    case XKB_KEY_Escape:
        clear_input();
        return;

    case XKB_KEY_BackSpace:
        if (input_position == 0)
            return;

        /* decrement input_position to point to the previous glyph */
        u8_dec(password, &input_position);
        password[input_position] = '\0';

        /* Hide the unlock indicator after a bit if the password buffer is
        * empty. */
        START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb);
        unlock_state = STATE_BACKSPACE_ACTIVE;
        redraw_screen();
        unlock_state = STATE_KEY_PRESSED;
        return;
    }

    if ((input_position + 8) >= sizeof(password))
        return;

#if 0
    /* FIXME: handle all of these? */
    printf("is_keypad_key = %d\n", xcb_is_keypad_key(sym));
    printf("is_private_keypad_key = %d\n", xcb_is_private_keypad_key(sym));
    printf("xcb_is_cursor_key = %d\n", xcb_is_cursor_key(sym));
    printf("xcb_is_pf_key = %d\n", xcb_is_pf_key(sym));
    printf("xcb_is_function_key = %d\n", xcb_is_function_key(sym));
    printf("xcb_is_misc_function_key = %d\n", xcb_is_misc_function_key(sym));
    printf("xcb_is_modifier_key = %d\n", xcb_is_modifier_key(sym));
#endif

    if (n < 2)
        return;

    /* store it in the password array as UTF-8 */
    memcpy(password + input_position, buffer, n - 1);
    input_position += n - 1;
    DEBUG("current password = %.*s\n", input_position, password);

    if (unlock_indicator) {
        unlock_state = STATE_KEY_ACTIVE;
        redraw_screen();
        unlock_state = STATE_KEY_PRESSED;

        struct ev_timer *timeout = NULL;
        START_TIMER(timeout, TSTAMP_N_SECS(0.25), redraw_timeout);
        STOP_TIMER(clear_indicator_timeout);
    }

    START_TIMER(discard_passwd_timeout, TSTAMP_N_MINS(3), discard_passwd_cb);
}
Exemplo n.º 3
0
static int keyboard_feed_evdev(idev_keyboard *k, idev_data *data) {
        struct input_event *ev = &data->evdev.event;
        enum xkb_state_component compch;
        enum xkb_compose_status cstatus;
        const xkb_keysym_t *keysyms;
        idev_device *d = &k->device;
        int num, r;

        if (ev->type != EV_KEY || ev->value > KBDKEY_DOWN)
                return 0;

        /* TODO: We should audit xkb-actions, whether they need @resync as
         * flag. Most actions should just be executed, however, there might
         * be actions that depend on modifier-orders. Those should be
         * suppressed. */

        num = xkb_state_key_get_syms(k->xkb_state, ev->code + KBDXKB_SHIFT, &keysyms);
        compch = xkb_state_update_key(k->xkb_state, ev->code + KBDXKB_SHIFT, ev->value);

        if (compch & XKB_STATE_LEDS) {
                /* TODO: update LEDs */
        }

        if (num < 0) {
                r = num;
                goto error;
        }

        if (k->xkb_compose && ev->value == KBDKEY_DOWN) {
                if (num == 1 && !data->resync) {
                        xkb_compose_state_feed(k->xkb_compose, keysyms[0]);
                        cstatus = xkb_compose_state_get_status(k->xkb_compose);
                } else {
                        cstatus = XKB_COMPOSE_CANCELLED;
                }

                switch (cstatus) {
                case XKB_COMPOSE_NOTHING:
                        /* keep produced keysyms and forward unchanged */
                        break;
                case XKB_COMPOSE_COMPOSING:
                        /* consumed by compose-state, drop keysym */
                        keysyms = NULL;
                        num = 0;
                        break;
                case XKB_COMPOSE_COMPOSED:
                        /* compose-state produced sth, replace keysym */
                        num = keyboard_read_compose(k, &keysyms);
                        xkb_compose_state_reset(k->xkb_compose);
                        break;
                case XKB_COMPOSE_CANCELLED:
                        /* canceled compose, reset, forward cancellation sym */
                        xkb_compose_state_reset(k->xkb_compose);
                        break;
                }
        } else if (k->xkb_compose &&
                   num == 1 &&
                   keysyms[0] == XKB_KEY_Multi_key &&
                   !data->resync &&
                   ev->value == KBDKEY_UP) {
                /* Reset compose state on Multi-Key UP events. This effectively
                 * requires you to hold the key during the whole sequence. I
                 * think it's pretty handy to avoid accidental
                 * Compose-sequences, but this may break Compose for disabled
                 * people. We really need to make this opional! (TODO) */
                xkb_compose_state_reset(k->xkb_compose);
        }

        if (ev->value == KBDKEY_UP) {
                /* never produce keysyms for UP */
                keysyms = NULL;
                num = 0;
        }

        r = keyboard_fill(k, &k->evdata, data->resync, ev->code, ev->value, num, keysyms);
        if (r < 0)
                goto error;

        keyboard_repeat(k);
        return keyboard_raise_data(k, &k->evdata);

error:
        log_debug_errno(r, "idev-keyboard: %s/%s: cannot handle event: %m",
                        d->session->name, d->name);
        k->repeating = false;
        keyboard_arm(k, 0);
        return 0;
}