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

前面我们介绍了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)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
作者保留版权,未经作者同意,不得用于任何商业用途


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值