bool InputMethodController::confirmCompositionOrInsertText(const String& text, ConfirmCompositionBehavior confirmBehavior)
{
    if (!hasComposition()) {
        if (!text.length())
            return false;
        editor().insertText(text, 0);
        return true;
    }

    if (text.length()) {
        confirmComposition(text);
        return true;
    }

    if (confirmBehavior != KeepSelection)
        return confirmComposition();

    SelectionOffsetsScope selectionOffsetsScope(this);
    return confirmComposition();
}
bool GtkInputMethodFilter::filterKeyEvent(GdkEventKey* event)
{
    if (!canEdit() || !m_enabled)
        return sendSimpleKeyEvent(event);

    m_preeditChanged = false;
    m_filteringKeyEvent = true;

    unsigned int lastFilteredKeyPressCodeWithNoResults = m_lastFilteredKeyPressCodeWithNoResults;
    m_lastFilteredKeyPressCodeWithNoResults = GDK_KEY_VoidSymbol;

    bool filtered = gtk_im_context_filter_keypress(m_context.get(), event);
    m_filteringKeyEvent = false;

    bool justSentFakeKeyUp = m_justSentFakeKeyUp;
    m_justSentFakeKeyUp = false;
    if (justSentFakeKeyUp && event->type == GDK_KEY_RELEASE)
        return true;

    // Simple input methods work such that even normal keystrokes fire the
    // commit signal. We detect those situations and treat them as normal
    // key events, supplying the commit string as the key character.
    if (filtered && !m_composingTextCurrently && !m_preeditChanged && m_confirmedComposition.length() == 1) {
        bool result = sendSimpleKeyEvent(event, m_confirmedComposition);
        m_confirmedComposition = String();
        return result;
    }

    if (filtered && event->type == GDK_KEY_PRESS) {
        if (!m_preeditChanged && m_confirmedComposition.isNull()) {
            m_composingTextCurrently = true;
            m_lastFilteredKeyPressCodeWithNoResults = event->keyval;
            return true;
        }

        bool result = sendKeyEventWithCompositionResults(event);
        if (!m_confirmedComposition.isEmpty()) {
            m_composingTextCurrently = false;
            m_confirmedComposition = String();
        }
        return result;
    }

    // If we previously filtered a key press event and it yielded no results. Suppress
    // the corresponding key release event to avoid confusing the web content.
    if (event->type == GDK_KEY_RELEASE && lastFilteredKeyPressCodeWithNoResults == event->keyval)
        return true;

    // At this point a keystroke was either:
    // 1. Unfiltered
    // 2. A filtered keyup event. As the IME code in EditorClient.h doesn't
    //    ever look at keyup events, we send any composition results before
    //    the key event.
    // Both might have composition results or not.
    //
    // It's important to send the composition results before the event
    // because some IM modules operate that way. For example (taken from
    // the Chromium source), the latin-post input method gives this sequence
    // when you press 'a' and then backspace:
    //  1. keydown 'a' (filtered)
    //  2. preedit changed to "a"
    //  3. keyup 'a' (unfiltered)
    //  4. keydown Backspace (unfiltered)
    //  5. commit "a"
    //  6. preedit end
    if (!m_confirmedComposition.isEmpty())
        confirmComposition();
    if (m_preeditChanged)
        updatePreedit();
    return sendSimpleKeyEvent(event);
}
Esempio n. 3
0
bool InputMethodController::confirmComposition()
{
    return confirmComposition(plainText(compositionEphemeralRange()));
}
bool InputMethodController::confirmComposition()
{
    return confirmComposition(composingText());
}