Android Open Source - VKB-VirtualKeyBoard Virtual Key Board






From Project

Back to project page VKB-VirtualKeyBoard.

License

The source code is released under:

GNU General Public License

If you think the Android project VKB-VirtualKeyBoard listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * <tt>VirtualKeyBoard.java</tt>
 *//from   www.j  a  v  a  2  s  .c  o  m
 * VKB (Virtual KeyBoard) is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * VKB (Virtual KeyBoard) is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * You should have received a copy of the GNU General Public License along with
 * VKB (Virtual KeyBoard).  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author  Tobias Groch <tgroch@stud.hs-bremen.de>
 * @author  Florian Wolters <flwolters@stud.hs-bremen.de>
 * @license http://gnu.org/licenses/gpl.txt GNU General Public License
 * @version SVN: Id:$
 * @since   File available since Release 1.0.0
 */

package de.hs_bremen.vkb;

import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.os.SystemClock;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.util.Log;

/**
 * The input method editor (IME) for VKB (Virtual KeyBoard).
 *
 * @author  Tobias Groch <tgroch@stud.hs-bremen.de>
 * @author  Florian Wolters <flwolters@stud.hs-bremen.de>
 * @version Release: @package_version@
 * @see     <a href=
 * "http://developer.android.com/resources/articles/creating-input-method.html"
 *          >Creating an Input Method</a>
 * @see     <a href=
 * "http://developer.android.com/resources/articles/on-screen-inputs.html"
 *          >Onscreen Input Methods</a>
 * @since   Class available since Release 1.0.0
 */
public class VirtualKeyBoard extends InputMethodService implements
    OnKeyboardActionListener {

    /**
     * Enable debug mode if <tt>true</tt>, <tt>false</tt> otherwise.
     */
    public static final boolean DEBUG_MODE = false;

    /**
     * The possible languages for the Virtual KeyBoard.
     */
    private static enum KeyboardLanguage {
        /**
         * Germany (German).
         */
        DE,
        /**
         * United Kingdom (English).
         */
        UK,
        /**
         * France (French).
         */
        FR
    }

    /**
     * The current language of the Virtual KeyBoard.
     */
    private KeyboardLanguage _eCurrentLanguage;

    /**
     * The currently used <tt>LatinKeyboard</tt>.
     *
     * An example for a keyboard is a <i>QWERTY</i> based layout for Latin
     * script.
     */
    private LatinKeyboard _oKeyboardCurrent = null;

    /**
     * The <tt>LatinKeyboard</tt> which was used before the currently used
     * <tt>LatinKeyboard</tt>.
     */
    private LatinKeyboard _oKeyboardLast = null;

    /**
     * The currently used <tt>LatinKeyboardView</tt>.
     */
    private LatinKeyboardView _oKeyboardView;

    /**
     * The <tt>LatinKeyboard</tt> with the lowercase layout.
     */
    private LatinKeyboard _oKeyboardLowercase;

    /**
     * The <tt>LatinKeyboard</tt> with the uppercase layout.
     */
    private LatinKeyboard _oKeyboardUppercase;

    /**
     * The <tt>LatinKeyboard</tt> with the lowercase and Alt Gr layout.
     */
    private LatinKeyboard _oKeyboardLowercaseAltGr;

    /**
     * The <tt>LatinKeyboard</tt> with the uppercase and Alt Gr layout.
     */
    private LatinKeyboard _oKeyboardUppercaseAltGr;

    /**
     * The <tt>LatinKeyboard</tt> with the Math layout.
     */
    private LatinKeyboard _oKeyboardMath;

    /**
     * The mask that includes the modifier key meta state bits <tt>{@link
     * KeyEvent#META_ALT_ON}</tt>, <tt>{@link KeyEvent#META_CTRL_ON}</tt> and
     * <tt>{@link KeyEvent#META_SHIFT_ON}</tt>.
     */
    private int _iCurrentMetaKeyMask = 0;

    /**
     * The maximum width, in pixels, of this input method (IME).
     */
    private int _iLastDisplayWidth;

    /**
     * Called by the system when the service is first created.
     */
    @Override
    public final void onCreate() {
        // Do not forget to call the onCreate method of the super class.
        super.onCreate();
    }

    /**
     * This is a hook that subclasses can use to perform initialization of their
     * interface. It is called for you prior to any of your UI objects being
     * created, both after the service is first created and after a
     * configuration change happens.
     */
    @Override
    public final void onInitializeInterface() {
        // Configuration changes can happen after the keyboard gets recreated,
        // so we need to be able to re-build the keyboards if the available
        // space has changed.
        if (null != this._oKeyboardCurrent) {
            // Return the maximum width (in pixels) available for the input
            // method.
            int iDisplayWidth = this.getMaxWidth();
            if (iDisplayWidth == this._iLastDisplayWidth) {
                // The width has not changed.
                return;
            }

            this._iLastDisplayWidth = iDisplayWidth;
        }

        // Creates the mathematical keyboard from the given xml key layout file.
        this._oKeyboardMath = new LatinKeyboard(this, R.xml.math);
        // Sets the language German as the default language.
        this._eCurrentLanguage = KeyboardLanguage.DE;
        // Creates the keyboards for the given language and sets the current
        // keyboard to lowercase.
        this._createKeyboardsForCurrentLanguage();
    }

    /**
     * Creates the keyboards for the given language and sets the current
     * keyboard to lowercase.
     */
    private void _createKeyboardsForCurrentLanguage() {
        int lcXml, lcAltGrXml, ucXml, ucAltGrXml;

        switch (this._eCurrentLanguage) {
        case UK:
            lcXml = R.xml.en_uk_lc;
            lcAltGrXml = R.xml.en_uk_lc_alt_gr;
            ucXml = R.xml.en_uk_uc;
            ucAltGrXml = R.xml.en_uk_uc_alt_gr;
            break;
        case FR:
            lcXml = R.xml.fr_fr_lc;
            lcAltGrXml = R.xml.fr_fr_lc_alt_gr;
            ucXml = R.xml.fr_fr_uc;
            ucAltGrXml = R.xml.fr_fr_uc_alt_gr;
            break;
        default:
            lcXml = R.xml.de_de_lc;
            lcAltGrXml = R.xml.de_de_lc_alt_gr;
            ucXml = R.xml.de_de_uc;
            ucAltGrXml = R.xml.de_de_uc_alt_gr;
        }

        this._oKeyboardLowercase = new LatinKeyboard(this, lcXml);
        this._oKeyboardLowercaseAltGr = new LatinKeyboard(this, lcAltGrXml);
        this._oKeyboardUppercase = new LatinKeyboard(this, ucXml);
        this._oKeyboardUppercaseAltGr = new LatinKeyboard(this, ucAltGrXml);
        this._oKeyboardCurrent = this._oKeyboardLowercase;
    }

    /**
     * Create and return the view hierarchy used to show candidates.
     *
     * This will be called once, when the candidates are first displayed. You
     * can return <tt>null</tt> to have no candidates view; the default
     * implementation returns <tt>null</tt>.
     *
     * To control when the candidates view is displayed, use
     * <tt>setCandidatesViewShown(boolean)</tt>. To change the candidates view
     * after the first one is created by this function, use
     * <tt>setCandidatesView(View)</tt>.
     *
     * @return <tt>null</tt>
     */
    @Override
    public final View onCreateCandidatesView() {
        return null;
    }

    /**
     * Create and return the view hierarchy used for the input area (such as a
     * soft keyboard).
     *
     * This will be called once, when the input area is first displayed. You can
     * return <tt>null</tt> to have no input area; the default implementation
     * returns <tt>null</tt>.
     *
     * To control when the input view is displayed, implement
     * <tt>onEvaluateInputViewShown()</tt>. To change the input view after the
     * first one is created by this function, use <tt>setInputView(View)</tt>.
     *
     * @return the view hierarchy used for the input area
     */
    @Override
    public final View onCreateInputView() {
        this._oKeyboardView = (LatinKeyboardView) getLayoutInflater().inflate(
            R.layout.input, null
        );

        this._oKeyboardView.setOnKeyboardActionListener(this);

        // Apply the selected keyboard to the input view.
        this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);

        // Return the input view.
        return this._oKeyboardView;
    }

    /**
     * Called when the input view is being shown and input has started on a new
     * editor.
     *
     * This will always be called after <tt>{@link #onStartInput(EditorInfo,
     * boolean)}</tt>, allowing you to do your general setup there and just
     * view-specific setup here. You are guaranteed that
     * <tt>onCreateInputView()</tt> will have been called some time before this
     * function is called.
     *
     * @param info       the description of the type of text being edited.
     * @param restarting <tt>true</tt> if we are restarting input on the same
     *                   text field as before.
     */
    @Override
    public final void onStartInputView(
        final EditorInfo info, final boolean restarting
    ) {
        super.onStartInputView(info, restarting);
        // Apply the selected keyboard to the input view.
        this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);
    }

    /**
     * Called to inform the input method that text input has started in an
     * editor.
     *
     * You should use this callback to initialize the state of your input to
     * match the state of the editor given to it.
     *
     * @param attribute  the attributes of the editor that input is starting in.
     * @param restarting set to <tt>true</tt> if input is restarting in the same
     *                   editor such as because the application has changed the
     *                   text in the editor. Otherwise will be <tt>false</tt>,
     *                   indicating this is a new session with the editor.
     */
    @Override
    public final void onStartInput(
        final EditorInfo attribute, final boolean restarting
    ) {
        super.onStartInput(attribute, restarting);
    }

    /**
     * Called to inform the input method that text input has finished in the
     * last editor.
     *
     * At this point there may be a call to
     * <tt>onStartInput(EditorInfo, boolean)</tt> to perform input in a new
     * editor, or the input method may be left idle. This method is not called
     * when input restarts in the same editor.
     *
     * The default implementation uses the <tt>InputConnection</tt> to clear any
     * active composing text; you can override this (not calling the base class
     * implementation) to perform whatever behavior you would like.
     */
    @Override
    public final void onFinishInput() {
        super.onFinishInput();
    }

    /**
     * Called when the application has reported a new selection region of the
     * text.
     *
     * This is called whether or not the input method has requested extracted
     * text updates, although if so it will not receive this call if the
     * extracted text has changed as well.
     *
     * The default implementation takes care of updating the cursor in the
     * extract text, if it is being shown.
     *
     * @param oldSelStart     the start position of the old selection.
     * @param oldSelEnd       the end position of the old selection.
     * @param newSelStart     the start position of the new selection.
     * @param newSelEnd       the end position of the new selection.
     * @param candidatesStart the start position of the candidates.
     * @param candidatesEnd   the end position of the candidates.
     */
    @Override
    public final void onUpdateSelection(
        final int oldSelStart, final int oldSelEnd, final int newSelStart,
        final int newSelEnd, final int candidatesStart, final int candidatesEnd
    ) {
        super.onUpdateSelection(
            oldSelStart, oldSelEnd, newSelStart, newSelEnd,
            candidatesStart, candidatesEnd
        );
    }

    /**
     * Called when the application has reported auto-completion candidates that
     * it would like to have the input method displayed.
     *
     * Typically these are only used when an input method is running in
     * full-screen mode, since otherwise the user can see and interact with the
     * pop-up window of completions shown by the application.
     *
     * The default implementation here does nothing.
     *
     * @param completions the auto-completion candidates. Each contains
     *                    information about a single text completion that an
     *                    editor has reported to an input method.
     */
    @Override
    public final void onDisplayCompletions(final CompletionInfo[] completions) {
        super.onDisplayCompletions(completions);
    }

    // Implementation of KeyboardViewListener.

    /**
     * Helper method to send an alternate key (<i>Alt</i>) to the current
     * editor.
     */
    private void _handleAlt() {
        this._iCurrentMetaKeyMask ^= KeyEvent.META_ALT_ON;
    }

    /**
     * Helper method to send a control key (<i>Ctrl</i>) to the current editor.
     */
    private void _handleCtrl() {
        this._iCurrentMetaKeyMask ^= KeyEvent.META_CTRL_ON;
    }

    /**
     * Helper method to send <i>Shift</i> to the current editor.
     */
    private void _handleShift() {
        this._iCurrentMetaKeyMask ^= KeyEvent.META_SHIFT_ON;
    }

    /**
     * Helper method to manage the current state of the keyboard.
     */
    private void _switchCapitalization() {
        if (DEBUG_MODE) {
            Log.w(
                "Keyboard::isShifted", //$NON-NLS-1$
                String.valueOf(this._oKeyboardCurrent.isShifted())
            );
            Log.w(
                "KeyboardView::isShifted", //$NON-NLS-1$
                String.valueOf(this._oKeyboardView.isShifted())
            );
        }

        if (this._oKeyboardCurrent == this._oKeyboardLowercase) {
            // this._oKeyboardLowercase.setShifted(true);
            // this._oKeyboardLowercaseAltGr.setShifted(true);
            this._oKeyboardCurrent = this._oKeyboardUppercase;
            // this._oKeyboardUppercase.setShifted(true);
            // this._oKeyboardUppercaseAltGr.setShifted(true);

        } else if (this._oKeyboardCurrent == this._oKeyboardUppercase) {
            // this._oKeyboardUppercase.setShifted(false);
            // this._oKeyboardUppercaseAltGr.setShifted(false);
            this._oKeyboardCurrent = this._oKeyboardLowercase;
            // this._oKeyboardLowercase.setShifted(false);
            // this._oKeyboardLowercaseAltGr.setShifted(false);

        } else if (this._oKeyboardCurrent == this._oKeyboardLowercaseAltGr) {
            // this._oKeyboardLowercase.setShifted(true);
            // this._oKeyboardLowercaseAltGr.setShifted(true);
            this._oKeyboardCurrent = this._oKeyboardUppercaseAltGr;
            // this._oKeyboardUppercase.setShifted(true);
            // this._oKeyboardUppercaseAltGr.setShifted(true);

        } else if (this._oKeyboardCurrent == this._oKeyboardUppercaseAltGr) {
            // this._oKeyboardUppercase.setShifted(false);
            // this._oKeyboardUppercaseAltGr.setShifted(false);
            this._oKeyboardCurrent = this._oKeyboardLowercaseAltGr;
            // this._oKeyboardLowercase.setShifted(false);
            // this._oKeyboardLowercaseAltGr.setShifted(false);
        }
        // Apply the selected keyboard to the input view.
        this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);

        if (DEBUG_MODE) {
            Log.w(
                "Keyboard::isShifted", //$NON-NLS-1$
                String.valueOf(this._oKeyboardCurrent.isShifted())
            );
            Log.w(
                "KeyboardView::isShifted", //$NON-NLS-1$
                String.valueOf(this._oKeyboardView.isShifted())
            );
        }
    }

    /**
     * Helper method to manage the current state of the keyboard.
     */
    private void _switchAltGr() {
        if (DEBUG_MODE) {
            Log.w(
                "LatinKeyboard.isPcAltGrActive", //$NON-NLS-1$
                String.valueOf(this._oKeyboardCurrent.isPcAltGrActive())
            );
            Log.w(
                "LatinKeyboardView.isPcAltGrActive", //$NON-NLS-1$
                String.valueOf(this._oKeyboardView.isPcAltGrActive())
            );
        }

        if (this._oKeyboardCurrent == this._oKeyboardLowercase
                || this._oKeyboardCurrent == this._oKeyboardMath) {
            // this._oKeyboardLowercase.setPcAltGrState(true);
            // this._oKeyboardUppercase.setPcAltGrState(true);
            this._oKeyboardCurrent = this._oKeyboardLowercaseAltGr;
            // this._oKeyboardLowercaseAltGr.setPcAltGrState(true);
            // this._oKeyboardUppercaseAltGr.setPcAltGrState(true);

        } else if (this._oKeyboardCurrent == this._oKeyboardLowercaseAltGr) {
            // this._oKeyboardLowercase.setPcAltGrState(false);
            // this._oKeyboardUppercase.setPcAltGrState(false);
            this._oKeyboardCurrent = this._oKeyboardLowercase;
            // this._oKeyboardLowercaseAltGr.setPcAltGrState(false);
            // this._oKeyboardUppercaseAltGr.setPcAltGrState(false);

        } else if (this._oKeyboardCurrent == this._oKeyboardUppercase) {
            // this._oKeyboardLowercase.setPcAltGrState(true);
            // this._oKeyboardUppercase.setPcAltGrState(true);
            this._oKeyboardCurrent = this._oKeyboardUppercaseAltGr;
            // this._oKeyboardLowercaseAltGr.setPcAltGrState(true);
            // this._oKeyboardUppercaseAltGr.setPcAltGrState(true);

        } else if (this._oKeyboardCurrent == this._oKeyboardUppercaseAltGr) {
            // this._oKeyboardLowercase.setPcAltGrState(false);
            // this._oKeyboardUppercase.setPcAltGrState(false);
            this._oKeyboardCurrent = this._oKeyboardUppercase;
            // this._oKeyboardLowercaseAltGr.setPcAltGrState(false);
            // this._oKeyboardUppercaseAltGr.setPcAltGrState(false);
        }
        // Apply the selected keyboard to the input view.
        this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);

        if (DEBUG_MODE) {
            Log.w(
                "LatinKeyboard.isPcAltGrActive", //$NON-NLS-1$
                String.valueOf(this._oKeyboardCurrent.isPcAltGrActive())
            );
            Log.w(
                "LatinKeyboardView.isPcAltGrActive", //$NON-NLS-1$
                String.valueOf(this._oKeyboardView.isPcAltGrActive())
            );
        }
    }

    /**
     * Helper method to manage the current state of the keyboard.
     */
    private void _switchFn() {
        if (this._oKeyboardCurrent != this._oKeyboardMath) {
            this._oKeyboardLast = this._oKeyboardCurrent;
            this._oKeyboardCurrent = this._oKeyboardMath;
            this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);
            this._oKeyboardView.setPcFnState(true);
        } else {
            this._oKeyboardCurrent = this._oKeyboardLast;
            this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);
        }
        // Apply the selected keyboard to the input view.
        this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);
    }

    /**
     * Switched from the current language of the Virtual KeyBoard to the next
     * language (round-robin).
     */
    private void _switchLanguage() {
        switch (this._eCurrentLanguage) {
        case DE:
            this._eCurrentLanguage = KeyboardLanguage.UK;
            break;
        case UK:
            this._eCurrentLanguage = KeyboardLanguage.FR;
            break;
        case FR:
            this._eCurrentLanguage = KeyboardLanguage.DE;
            break;
        default:
            break;
        }
        // Create the Keyboard instances for the current language.
        this._createKeyboardsForCurrentLanguage();
        // Apply the selected keyboard to the input view.
        this._oKeyboardView.setKeyboard(this._oKeyboardCurrent);
    }

    /**
     * Helper method to send a character key to the current editor.
     *
     * @param primaryCode the unicode code of the key that was pressed.
     */
    private void _handleCharacter(final int primaryCode) {
        this.getCurrentInputConnection().commitText(
            String.valueOf((char) primaryCode), 1
        );
    }

    /**
     * Helper method to send a <tt>{@link KeyEvent}</tt> to the current editor.
     *
     * @param primaryCode the unicode code of the key that was pressed.
     */
    private void _handleKeyEvent(final int primaryCode) {
        InputConnection ic = this.getCurrentInputConnection();
        long eventTime = SystemClock.uptimeMillis();

        try {
            ic.sendKeyEvent(
                new KeyEvent(
                    eventTime, // The time (in uptimeMillis()) at which this key code originally went down.
                    eventTime, // The time (in uptimeMillis()) at which this event happened.
                    KeyEvent.ACTION_DOWN, // Action code: either ACTION_DOWN, ACTION_UP, or ACTION_MULTIPLE.
                    ASCIICodeToKeyEventConstantTranslator.translate(primaryCode),  // The key code.
                    0,  // A repeat count for down events (> 0 if this is after the initial down) or event count for multiple events.
                    this._iCurrentMetaKeyMask, // Flags indicating which meta keys are currently pressed.
                    KeyCharacterMap.FULL, // The device ID that generated the key event.
                    0, // Raw device scan code of the event.
                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE, // The flags for this key event.
                    InputDevice.SOURCE_KEYBOARD // The input source such as SOURCE_KEYBOARD.
                )
            );
        } catch (NullPointerException ex) {
            ic.commitText(String.valueOf((char) primaryCode), 1);
        }
    }

    /**
     * Sends one of the four cursor movement keys (arrow keys) to the current
     * editor.
     *
     * Nothing is done if <tt>primaryCode</tt> doesn't specify one of the cursor
     * movement keys.
     *
     * @param primaryCode the unicode code of the key that was pressed.
     */
    private void _handleArrowKeys(final int primaryCode) {
        switch (primaryCode) {
        case LatinKeyboard.KEYCODE_ARROW_DOWN:
            // Down cursor movement key or arrow key.
            // Send the key event code for the Directional Pad Down key to the
            // current input connection as a key down + key up event pair.
            this.sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_DOWN);
            break;
        case LatinKeyboard.KEYCODE_ARROW_LEFT:
            // Left cursor movement key or arrow key.
            // Send the key event code for the Directional Pad Left key to the
            // current input connection as a key down + key up event pair.
            this.sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT);
            break;
        case LatinKeyboard.KEYCODE_ARROW_RIGHT:
            // Right cursor movement key or arrow key.
            // Send the key event code for the Directional Pad Right key to the
            // current input connection as a key down + key up event pair.
            this.sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_RIGHT);
            break;
        case LatinKeyboard.KEYCODE_ARROW_UP:
            // Up cursor movement key or arrow key.
            // Send the key event code for the Directional Pad Up key to the
            // current input connection as a key down + key up event pair.
            this.sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_UP);
            break;
        default:
            // primaryCode doesn't specify a cursor movement key or arrow key.
            break;
        }
    }

    /**
     * Helper method to send a backspace key (<i>BS</i>) to the current editor.
     */
    private void _handleBackspaceKey() {
        this.sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
    }

    // Start: Implementation of the abstracts methods of class
    // android.inputmethodservice.KeyboardView.OnKeyboardActionListener.

    /**
     * Called when the user presses a key. This is sent before the
     * {@link #onKey(int, int[])} is called.
     *
     * For keys that repeat, this is only called once.
     *
     * @param primaryCode the unicode code of the key that was pressed. If the
     *                    touch is not on a valid key, the value will be zero.
     */
    @Override
    public void onPress(final int primaryCode) {
        // Empty block.
    }

    /**
     * Sends a key press to the listener.
     *
     * @param primaryCode the unicode code of the key that was released.
     * @param keyCodes    the codes for all the possible alternative keys with
     *                    the primary code being the first. If the primary key
     *                    code is a single character such as an alphabet o
     *                    number or symbol, the alternatives will include other
     *                    characters that may be on the same key or adjacent
     *                    keys. These codes are useful to correct for accidental
     *                    presses of a key adjacent to the intended key.
     */
    @Override
    public final void onKey(final int primaryCode, final int[] keyCodes) {
        if (DEBUG_MODE) {
            Log.w(
                "CURRENT_META_MASK", //$NON-NLS-1$
                String.valueOf(this._iCurrentMetaKeyMask)
            );
        }
        switch (primaryCode) {
        case LatinKeyboard.KEYCODE_ARROW_DOWN:
            // Right cursor movement key or arrow key.
        case LatinKeyboard.KEYCODE_ARROW_LEFT:
            // Left cursor movement key or arrow key.
        case LatinKeyboard.KEYCODE_ARROW_RIGHT:
            // Up cursor movement key or arrow key.
        case LatinKeyboard.KEYCODE_ARROW_UP:
            // Down cursor movement key or arrow key.
            this._handleArrowKeys(primaryCode);
            break;
        case Keyboard.KEYCODE_CANCEL:
        case Keyboard.KEYCODE_DONE:
            this._handleClose();
            break;
        case Keyboard.KEYCODE_DELETE:
            this._handleBackspaceKey();
            break;
        case Keyboard.KEYCODE_SHIFT:
            this._switchCapitalization();
            break;
        case Keyboard.KEYCODE_ALT:
            this._switchAltGr();
            break;
        case Keyboard.KEYCODE_MODE_CHANGE:
            this._switchFn();
            break;
        case LatinKeyboard.KEYCODE_PC_ALT:
            this._handleAlt();
            break;
        case LatinKeyboard.KEYCODE_PC_CTRL:
            this._handleCtrl();
            break;
        case LatinKeyboard.KEYCODE_PC_SHIFT:
            this._handleShift();
            break;
        case LatinKeyboard.KEYCODE_LANGUAGE:
            this._switchLanguage();
            break;
        default:
            // Check whether the current bit mask of the meta keys is set.
            if (0 != this._iCurrentMetaKeyMask) {
                this._handleKeyEvent(primaryCode);
            } else {
                this._handleCharacter(primaryCode);
            }
        }
    }

    /**
     * Called when the user releases a key. This is sent after the
     * {@link #onKey(int, int[])} is called.
     *
     * For keys that repeat, this is only called once.
     *
     * @param primaryCode the unicode code of the key that was released.
     */
    @Override
    public void onRelease(final int primaryCode) {
        // Empty block.
    }

    /**
     * Sends a sequence of characters to the listener.
     *
     * @param text the sequence of characters to be displayed.
     */
    @Override
    public void onText(final CharSequence text) {
        // Empty block.
    }

    /**
     * Called when the user quickly moves the finger from up to down.
     */
    @Override
    public void swipeDown() {
        // Empty block.
    }

    /**
     * Called when the user quickly moves the finger from right to left.
     */
    @Override
    public void swipeLeft() {
        // Empty block.
    }

    /**
     * Called when the user quickly moves the finger from left to right.
     */
    @Override
    public void swipeRight() {
        // Empty block.
    }

    /**
     * Called when the user quickly moves the finger from down to up.
     */
    @Override
    public void swipeUp() {
        // Empty block.
    }

    /**
     * Close (hides) the keyboard and the view that renders the key.
     */
    private void _handleClose() {
        // Close this input method's soft input area, removing it from the
        // display. The input method will continue running, but the user can no
        // longer use it to generate input by touching the screen.
        this.requestHideSelf(0);
        // Close the view that renders the keyboard.
        this._oKeyboardView.closing();
    }

    // End: Implementation of the abstracts methods of class
    // android.inputmethodservice.KeyboardView.OnKeyboardActionListener.

    // Start: Generic helper methods that simplify usage.

    /**
     * Send the given key event code (as defined by <tt>{@link KeyEvent}</tt>)
     * to the current input connection as a key down event.
     *
     * The sent event has <tt>{@link KeyEvent#FLAG_SOFT_KEYBOARD}</tt> set, so
     * that the recipient can identify it as coming from a software input
     * method, and <tt>{@link KeyEvent#FLAG_KEEP_TOUCH_MODE}</tt>, so that it
     * doesn't impact the current touch mode of the UI.
     *
     * @param keyEventCode the raw key code to send, as defined by <tt>{@link
     *                     KeyEvent}</tt>.
     */
    public final void sendDownKeyEvent(final int keyEventCode) {
        InputConnection ic = this.getCurrentInputConnection();
        if (ic != null) {
            long eventTime = SystemClock.uptimeMillis();
            ic.sendKeyEvent(
                new KeyEvent(
                    eventTime, eventTime,
                    KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0,
                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
                )
            );
        }
    }

    /**
     * Send the given key event code (as defined by <tt>{@link KeyEvent}</tt>)
     * to the current input connection as a key up event.
     *
     * The sent event has <tt>{@link KeyEvent#FLAG_SOFT_KEYBOARD}</tt> set, so
     * that the recipient can identify it as coming from a software input
     * method, and <tt>{@link KeyEvent#FLAG_KEEP_TOUCH_MODE}</tt>, so that it
     * doesn't impact the current touch mode of the UI.
     *
     * @param keyEventCode the raw key code to send, as defined by <tt>{@link
     *                     KeyEvent}</tt>.
     */
    public final void sendUpKeyEvent(final int keyEventCode) {
        InputConnection ic = this.getCurrentInputConnection();
        if (ic != null) {
            long eventTime = SystemClock.uptimeMillis();
            ic.sendKeyEvent(
                new KeyEvent(
                    eventTime, eventTime,
                    KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0,
                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
                )
            );
        }
    }

    // End: Generic helper methods that simplify usage.

}




Java Source Code List

de.hs_bremen.vkb.ASCIICharacters.java
de.hs_bremen.vkb.ASCIICodeToKeyEventConstantTranslator.java
de.hs_bremen.vkb.LatinKeyboardView.java
de.hs_bremen.vkb.LatinKeyboard.java
de.hs_bremen.vkb.VirtualKeyBoard.java
de.hs_bremen.vkb.package-info.java