nsIIdleService 的实现与应用

来源:互联网 发布:java定义字符串 编辑:程序博客网 时间:2024/06/03 17:14

在 Mozilla 中有一个服务可以实现对系统消息的侦听,就是 nsIIdleService 接口。

该接口主要实现的功能是:设置一个时间段,当你在这个时间段内没有对计算机进行操作(键盘触发和鼠标操作)时,它会侦听到一个 idle 的消息,而你可以对这个消息做处理,做你想要实现的效果。

其实,就是在 QQ 中实现的“离开”的自动设置的功能。

分析源码,涉及到 nsITimer 及其相关内容,对这部分还不是很懂,继续研究中。

经过一番分析,终于找到它是如何侦听系统消息的了。图一中所示代码是在windows下实现的接口中的 idleTime 的获取过程。其中,通过GetLastInputInfo获取最后的 input event 的时间。

正是在这个函数中,实现在对 windows 系统消息的捕获,nsIIdleService 在实现接口的时候利用该属性与设定的侦听的延迟时间做比较,从而进行触发,如此想来,就很是简单了。图二中所示代码是 nsIIdleService 中实现的 checkAwayState 方法。

图一:在 windows 中实现的 GetIdleTime 方法

NS_IMETHODIMP
nsIdleServiceWin::GetIdleTime(PRUint32 *aTimeDiff)
{
    LASTINPUTINFO inputInfo;
    inputInfo.cbSize = sizeof(inputInfo);
    if (!::GetLastInputInfo(&inputInfo))
        return NS_ERROR_FAILURE;

    *aTimeDiff = GetTickCount() - inputInfo.dwTime;
    return NS_OK;
}


关于windows 对消息事件的处理,可参阅 Keyboard Input 。

图二: 在 nsIdleService.cpp 中实现的修改 away state 的方法

void
nsIdleService::CheckAwayState()
{
    // Get the idle time.

    PRUint32 idleTime;
    if (NS_FAILED(GetIdleTime(&idleTime)))
        return;

    nsAutoString timeStr;
    timeStr.AppendInt(idleTime);

    // Change state first, and save observers that need notification, so

    // removing things will always work without upsetting notifications.

    nsCOMArray<nsIObserver> idleListeners;
    nsCOMArray<nsIObserver> hereListeners;
    for (PRUint32 i = 0; i < mArrayListeners.Length(); i++)
    {
        IdleListener& curListener = mArrayListeners.ElementAt(i);
        if ((curListener.reqIdleTime * 1000 <= idleTime) &&
            !curListener.isIdle)
        {
            curListener.isIdle = PR_TRUE;
            idleListeners.AppendObject(curListener.observer);
        }
        else if ((curListener.reqIdleTime * 1000 > idleTime) &&
                 curListener.isIdle)
        {
            curListener.isIdle = PR_FALSE;
            hereListeners.AppendObject(curListener.observer);
        }
    }

    // Notify listeners gone idle:

    for (PRInt32 i = 0; i < idleListeners.Count(); i++)
    {
        idleListeners[i]->Observe(this, OBSERVER_TOPIC_IDLE, timeStr.get());
    }

    // Notify listeners that came back:

    for (PRInt32 i = 0; i < hereListeners.Count(); i++)
    {
        hereListeners[i]->Observe(this, OBSERVER_TOPIC_BACK, timeStr.get());
    }
}


在这段源代码的分析中,可以看到 mozilla 在实现一个接口的思想。它的跨平台的实现,也显现了出来。而对服务的实现,也是利用 observer 机制很简单就实现了。真是佩服。

我要好好消化下。

在应用方面,mozilla 官网上的实例很不错。如图三所示:

var idleService = Components.classes["@mozilla.org/widget/idleservice;1"]
                            .getService(Components.interfaces.nsIIdleService)
var idleObserver = {
  observe: function(subject, topic, data) {
    alert("topic: " + topic + "/ndata: " + data);
  }
};
idleService.addIdleObserver(idleObserver, 60); // one minute

// ...

// Don't forget to remove the observer using removeIdleObserver!

idleService.removeIdleObserver(idleObserver, 60);


第一次这样研究 mozilla 里的 xpcom ,我想这仅仅是一个开始,我将坚持下去,深入的理解这个庞大强悍的 Gecko 内核。

加油!

原创粉丝点击