Qt API | Qtopia API | Qtopia Documentation |

## Input Methods

There are two kinds of input method. The first is a widget that generates keystrokes, such as a virtual keyboard or a handwriting recogniser. This is the sort of input method supported by Qtopia 1.5.

Qtopia 1.6 adds support for a second type of input method: a composing input method. Composing input methods takes keyboard input from a keyboard (real or virtual) and compose several keystrokes into one character. Composing input methods can be used to input Chinese, Japanese and Korean text.

Input methods built using the Qtopia 1.6 interface can be either composing or virtual keyboard, but they cannot be installed on Qtopia 1.5-based devices.

### Qtopia 1.5 methods

These input methods must supply a QWidget that will be shown above the task bar and emit a signal when a key is pressed:

    #include <qwidget.h>

    class SimpleInputMethod : public QWidget
    {
        Q_OBJECT
    public:
        SimpleInputMethod( QWidget *parent, const char *name, WFlags f );

    signals:
        void keyPress( ushort unicode, ushort keycode, ushort modifiers, bool press, bool repeat )
    };

The parameters of the keyPress signal are:

Parameter | Notes
--- | ---
unicode | The unicode value of the character, or 0xFFFF if it is a non-printing key.
keycode | The key code as specified in qnamespace.h
modifiers | A combination of zero or more of the following OR'ed together: Qt::ShiftButton, Qt::ControlButton and Qt::AltButton
press | TRUE for a key press, FALSE for a key release.
repeat | TRUE if this is a repeating keypress.

Input methods may be added to Qtopia via plugins. In order to write an input method plugin you must create an interface to your input method by deriving from the InputMethodInterface class and implementing the pure virtual functions.

To make an input method plugin the following implementation is required:

    #include <qpe/inputmethodinterface.h>

    class SimpleInputMethodImpl : public InputMethodInterface
    {
    public:
        SimpleInputMethodImpl();
        virtual ~SimpleInputMethodImpl();

    #ifndef QT_NO_COMPONENT
        QRESULT queryInterface( const QUuid&, QUnknownInterface** );
        Q_REFCOUNT
    #endif

        virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f );
        virtual void resetState();
        virtual QPixmap *icon();
        virtual QString name();
        virtual void onKeyPress( QObject *receiver, const char *slot );

    private:
        SimpleInputMethod *input;
        QPixmap *icn;
        ulong ref;
    };

The constructor and destructor are very simple:

    SimpleInputMethodImpl::SimpleInputMethodImpl()
        : input(0), icn(0), ref(0)
    {
    }

    SimpleInputMethodImpl::~SimpleInputMethodImpl()
    {
        delete input;
        delete icn;
    }

The queryInterface() function can be implemented using the following boilerplate code:

    QRESULT SimpleInputMethodImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
    {
        *iface = 0;
        if ( uuid == IID_QUnknown )
            *iface = this;
        else if ( uuid == IID_InputMethod )
            *iface = this;
        else
            return QS_FALSE;

        (*iface)->addRef();
        return QS_OK;
    }

The inputMethod() function returns the input method widget. This widget will be display just above the task bar when the user needs to input text. You should always return the same widget if this function is called multiple times.

    QWidget *SimpleInputMethodImpl::inputMethod( QWidget *parent, Qt::WFlags f )
    {
        if ( !input )
            input = new SimpleInputMethod( parent, "SimpleInput", f );
        return input;
    }

The resetState() function should return the input method to its default state.

The name() function returns the name of the input method. This will be displayed in the popup list of available input methods.

    QString SimpleInputMethodImpl::name()
    {
        return qApp->translate( "InputMethods", "SimpleInput" );
    }

The name() function returns the icon for the input method. This will be displayed in the taskbar when the input method is selected.

    QPixmap *SimpleInputMethodImpl::icon()
    {
        if ( !icn )
            icn = new QPixmap( your pixmap );
        return icn;
    }

The onKeyPress() function must connect the supplied slot to the signal that is emitted when a key press is generated.

The following code will connect the signal to the supplied slot:

    void SimpleInputMethodImpl::onKeyPress( QObject *receiver, const char *slot )
    {
        if ( input )
            QObject::connect( input, SIGNAL(keyPress(ushort,ushort,ushort,bool,bool)), receiver, slot );
    }

You must also create an instance of the input method plugin using the following boilerplate code:

    Q_EXPORT_INTERFACE()
    {
        Q_CREATE_INSTANCE( SimpleInputMethodImpl )
    }

The plugin must be compiled as a shared library and placed in the `$QPEDIR/plugins/imputmethods` directory. The following `tmake` project file will create a suitable Makefile:

    TEMPLATE     = lib
    CONFIG      += qt warn_on release
    HEADERS      = simpleinputmethod.h \
                   simpleinputmethodimpl.h
    SOURCES      = simpleinputmethod.cpp \
                   simpleinputmethodimpl.cpp
    TARGET       = simpleinputmethod
    DESTDIR      = $(QPEDIR)/plugins/inputmethods
    INCLUDEPATH += $(QPEDIR)/include
    LIBS        += -lqpe
    VERSION      = 1.0.0

Examples of Qtopia input methods can be found in the `inputmethods/` directory of the Qtopia source code.

### Composing input methods

Qtopia 1.6 input methods are created by inheriting from ExtInputMethodInterface, in the same manner as InputMethodInterface.

The main new feature of ExtInputMethodInterface is support for composing input methods. The input method itself is implemented as a class that inherits from QWSInputMethod. It filters all keyboard events before they are sent to the application that has keyboard focus.

There is a complete example of a composing input method in the `examples/inputmethod` directory of Qtopia.

The main class of a composing input method inherits from QWSInputMethod. It filters all keyboard events before they are sent to the application that has keyboard focus. A minimal input method could look like this:

    class ComposeIM : public QWSInputMethod
    {
    public:
        ComposeIM();

        void reset();
        bool filter(int unicode, int keycode, int modifiers,
                                bool isPress, bool autoRepeat);

        enum State { Off, On };

    private:
        State state;
        QString composed;
    };

The QWSInputMethod::filter() function is the central part of the input method. It implements the composition logic and maintains state. It uses QWSInputMethod::sendIMEvent() to send input method events.

The function QWSInputMethod::reset() is called from the system when the input method needs to reset state, eg. when the focus widget changes.

Other functions include QWSInputMethod::setMicroFocus() which is called when the cursor position changes inside the focus widget, and QWSInputMethod::mouseHandler() which is called when the user clicks inside the composed text.

A plugin for the ExtInputMethodInterface requires the following implementation:

    class ComposeImpl : public ExtInputMethodInterface
    {

    public:
        ComposeImpl();
        virtual ~ComposeImpl();

    #ifndef QT_NO_COMPONENT
        QRESULT queryInterface( const QUuid&, QUnknownInterface** );
        Q_REFCOUNT
    #endif
        virtual QString name();
        virtual QPixmap *icon();

        virtual void resetState();

        virtual QStringList compatible();

        virtual QWSInputMethod *inputMethod( );

        virtual QWidget *statusWidget( QWidget *parent, Qt::WFlags f);
        virtual QWidget *keyboardWidget( QWidget *parent, Qt::WFlags f);

        virtual void qcopReceive( const QCString &msg, const QByteArray &data );

    private:
        ComposeIM *input;
        QPixmap *icn;
        QWidget *statWid;
        ulong ref;
    };

The queryInterface() function for this interface can be implemented as follows:

    QRESULT ComposeImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
    {
        *iface = 0;
        if ( uuid == IID_QUnknown )
            *iface = this;
        else if ( uuid == IID_ExtInputMethod )
            *iface = this;
        else
            return QS_FALSE;

        (*iface)->addRef();
        return QS_OK;
    }

For a composing input method, the keyboardWidget() function returns 0:

    QWidget *ComposeImpl::keyboardWidget( QWidget *, Qt::WFlags )
    {
        return 0;
    }

The function inputMethod() returns the input method:

    QWSInputMethod *ComposeImpl::inputMethod( )
    {
        if ( !input )
            input = new ComposeIM( );
        return input;
    }

resetState() resets the state of the input method:

    void ComposeImpl::resetState()
    {
        if ( input )
            input->reset();
    }

icon() returns the icon.

    QPixmap *ComposeImpl::icon()
    {
        if (!icn)
            icn = new QPixmap( \e pixmap );
        return icn;
    }

name() returns the name:

    QString ComposeImpl::name()
    {
        return qApp->translate( "InputMethods", "Latest" );
    }

For a composing input method, the widget returned by statusWidget() will be placed in the taskbar when the input method is selected. This widget is typically used to display status, and can also be used to let the user interact with the input method.

    QWidget *ComposeImpl::statusWidget( QWidget *parent, Qt::WFlags )
    {
        if (!statWid) {
            (void) inputMethod(); //create input before we use it
            statWid  = new IMStatus( input, parent);
        }
        return statWid;
    }

The compatible() function can be used to say that this input method is only compatible with certain other input methods. In this case, there are no restrictions:

    QStringList ComposeImpl::compatible( )
    {
        return QStringList();
    }

In qcopReceive(), we get notified when there is an event on the inputmethod channel:

    void ComposeImpl::qcopReceive( const QCString &msg, const QByteArray &data )
    {
        //process QCop event
    }