ITKeyword,专注技术干货聚合推荐

注册 | 登录

Inside Qt Series (十五):Qt/e 输入法,How it works?

Max__Payne 分享于

2020腾讯云10周年活动,优惠非常大!(领取2860元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1040

2020阿里云最低价产品入口,含代金券(新老用户有优惠),
地址https://www.aliyun.com/minisite/goods

推荐:Qt开发:UDP、TCP发送文字消息、检测U盘插拔、SYSZUXpinyin软键盘输入法移植------[源码奉送]

开发环境为Linux+Qt, 功能是实现tcp 、udp发送消息,检测U盘插拔、同时在arm端移植syszuxpinyin软键盘出入法。下面是我当时的工作总结。下面是效果图: 关于tcp

前面我们介绍了Qte输入法的基本设计思路,以及一个最简单的例子,那么,Qte的输入法是如何工作的呢?本节我们就来看一下Qte的源代码,一起来解开这个谜团。

在Qte的Client/Server体系结构中,QWSServer类负责管理Qte的Server,监听系统事件,尤其是键盘和鼠标事件。当这些监听的事件发生的时候,server会做出判断,这些事件应该发送给那一个客户端。

如果当前系统安装了输入法,那么键盘和鼠标事件在派发之前,就会先送给输入法,让输入法来做一下判断,看输入法是否会处理这个键盘按键,如果输入法已经处理,就不在继续分发这个事件,否则就会按照原先的事件分发机制继续分发这个事件。也就是说,输入法会在应用程序之前接收到键盘事件。

Qte已经定义了一个输入法基类QWSInputMethod,在这个类中封装了一些基本的输入法函数。我们一起来看看QWSInputMethod类的定义:

class QWSInputMethod : public QObject
{
    Q_OBJECT
public:
    QWSInputMethod();
    virtual ~QWSInputMethod();

    enum UpdateType {Update, FocusIn, FocusOut, Reset, Destroyed};

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

    virtual bool filter(const QPoint &, int state, int wheel);

    virtual void reset();
    virtual void updateHandler(int type);
    virtual void mouseHandler(int pos, int state);
    virtual void queryResponse(int property, const QVariant&);

protected:
    uint setInputResolution(bool isHigh);
    uint inputResolutionShift() const;
    void sendMouseEvent(const QPoint &pos, int state, int wheel);

    void sendEvent(const QInputMethodEvent*);
    void sendPreeditString(const QString &preeditString, int cursorPosition, int selectionLength = 0);
    void sendCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0);
    void sendQuery(int property);

private:
    bool mIResolution;
};

这个类从QObject类继承而来,定义了 Q_OBJECT 宏,说明这个类支持Qt对象模型的操作,signal/slot,property,都没有问题,这里最关键的几个函数有,两个重载的filter函数,一个用来过滤键盘事件,另一个用来过滤鼠标事件,sendEvent函数用来发送输入法事件,在这个事件中可以打包preedit string, commit string,它还有一个list,可以添加任意多的其它数据。sendPreeditString函数用来把正在输入过程中的字符串发送到当前编辑窗口,而sendCommitString则用来把最终的用户选择的字符串发送到当前编辑窗口。

QWSServer类提供了一个函数来安装输入法,void setCurrentInputMethod ( QWSInputMethod * method),这个函数的参数就是一个QWSInputMethod类的指针。QWSServer是如何管理QWSInputMethod的呢?在Server端,定义了这么几个变量,

static QWSInputMethod *current_IM = 0;
static QWSWindow *current_IM_composing_win = 0;
static int current_IM_winId = -1;
static bool force_reject_strokeIM = false;

其中,最重要的就是current_IM了,这个指针指向当前安装的输入法对象,它就是在QWSServer::setCurrentInputMethod函数中赋值的。

这里是QWSServer::setCurrentInputMethod这个函数的源代码:

void QWSServer::setCurrentInputMethod(QWSInputMethod *im)
{
    if (current_IM)
        current_IM->reset();
    current_IM = im;
}

再看看这个键盘事件处理函数:

void QWSServer::sendKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
                             bool isPress, bool autoRepeat)
{
    //………………………..
#ifndef QT_NO_QWS_INPUTMETHODS

    if (!current_IM || !current_IM->filter(unicode, keycode, modifiers, isPress, autoRepeat))
        QWSServerPrivate::sendKeyEventUnfiltered(unicode, keycode, modifiers, isPress, autoRepeat);
#else
    QWSServerPrivate::sendKeyEventUnfiltered(unicode, keycode, modifiers, isPress, autoRepeat);
#endif
}

在QWSServer::sendKeyEvent函数中,会去检查当前是否安装了输入法,如果是,就会去调用这个输入法的filter函数来过滤键盘事件,如果这个函数返回值为true,就不在继续分发这个key事件。

再看看这个鼠标事件处理函数:

void QWSServer::sendMouseEvent(const QPoint& pos, int state, int wheel)
{
// ————————–
    const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
    int stroke_count; // number of strokes to keep shown.
    if (force_reject_strokeIM || !current_IM)
    {
        stroke_count = 0;
    } else {
        stroke_count = current_IM->filter(tpos, state, wheel);
    }
}

在 QWSServer::sendMouseEvent 函数里面,同样会去检查当前是否安装了输入法,如果是,就会去调用输入法的filter函数来过滤鼠标事件,如果这个函数返回值为true,就不在继续分发这个key事件。

看,Qt/Embedded 输入法的工作原理其实就是这么简单!

下面以一张简单的UML sequence图来说明一下:

======================================================================
声明:
《Inside Qt Series》专栏文章是(http://www.qkevin.com)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
作者保留版权,未经作者同意,不得用于任何商业用途

《Inside Qt Series》专栏文章总索引: http://www.qkevin.com/qt
本文原始地址:http://www.qkevin.com/archives/106

前面我们介绍了Qte输入法的基本设计思路,以及一个最简单的例子,那么,Qte的输入法是如何工作的呢?本节我们就来看一下Qte的源代码,一起来解开这个谜团。 在Qte的Client/Server体系结构中,QW

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。