Chinaunix首页 | 论坛 | 博客
  • 博客访问: 139491
  • 博文数量: 124
  • 博客积分: 70
  • 博客等级: 民兵
  • 技术积分: 1745
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-24 13:49
文章分类

全部博文(124)

文章存档

2011年(55)

2010年(14)

2009年(30)

2008年(25)

我的朋友

分类: WINDOWS

2011-05-27 15:24:51

我自己用qtwebkit也尝试了一下,采用html

先看个简单的,仅仅在body中处理的事件

total





通过阅读代码
1. webcore 定义了一组全局标签宏,应该是编译时候自动生成的

DEFINE_GLOBAL(AtomicString, xhtmlNamespaceURI, "")
// Tags
DEFINE_GLOBAL(QualifiedName, aTag, nullAtom, "a", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, abbrTag, nullAtom, "abbr", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, acronymTag, nullAtom, "acronym", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, addressTag, nullAtom, "address", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, appletTag, nullAtom, "applet", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, areaTag, nullAtom, "area", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, articleTag, nullAtom, "article", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, asideTag, nullAtom, "aside", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, audioTag, nullAtom, "audio", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, bTag, nullAtom, "b", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, baseTag, nullAtom, "base", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, basefontTag, nullAtom, "basefont", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, bdoTag, nullAtom, "bdo", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, bigTag, nullAtom, "big", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, blockquoteTag, nullAtom, "blockquote", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, bodyTag, nullAtom, "body", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, brTag, nullAtom, "br", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, buttonTag, nullAtom, "button", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, canvasTag, nullAtom, "canvas", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, captionTag, nullAtom, "caption", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, centerTag, nullAtom, "center", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, citeTag, nullAtom, "cite", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, codeTag, nullAtom, "code", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, colTag, nullAtom, "col", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, colgroupTag, nullAtom, "colgroup", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, datagridTag, nullAtom, "datagrid", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, datalistTag, nullAtom, "datalist", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, dcellTag, nullAtom, "dcell", xhtmlNamespaceURI);
DEFINE_GLOBAL(QualifiedName, dcolTag, nullAtom, "dcol", xhtmlNamespaceURI);
。。。。。。。。

2. 在parsetag时候

 PassRefPtr HTMLParser::getNode(Token* t)
{
    // Init our error handling table.
    DEFINE_STATIC_LOCAL(FunctionMap, gFunctionMap, ());
    if (gFunctionMap.isEmpty()) {
        gFunctionMap.set(aTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck);
        gFunctionMap.set(addressTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
        gFunctionMap.set(articleTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
        gFunctionMap.set(asideTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
        gFunctionMap.set(bTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck);
        gFunctionMap.set(bigTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck);
        gFunctionMap.set(blockquoteTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
        gFunctionMap.set(bodyTag.localName().impl(), &HTMLParser::bodyCreateErrorCheck);
        gFunctionMap.set(buttonTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck);
        gFunctionMap.set(centerTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
        gFunctionMap.set(commentAtom.impl(), &HTMLParser::commentCreateErrorCheck);
        gFunctionMap.set(ddTag.localName().impl(), &HTMLParser::ddCreateErrorCheck);
        gFunctionMap.set(dirTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
        gFunctionMap.set(divTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck);
.....

将tag和创建它们的方法关联。


3. static void createFunctionMap()
{
    ASSERT(!gFunctionMap);

    // Create the table.
    gFunctionMap = new FunctionMap;
    
    // Populate it with constructor functions.
    addTag(aTag, anchorConstructor);
    addTag(appletTag, appletConstructor);
    addTag(areaTag, areaConstructor);
#if ENABLE(VIDEO)
    addTag(audioTag, audioConstructor);
#endif

    addTag(baseTag, baseConstructor);
    addTag(basefontTag, basefontConstructor);
    addTag(blockquoteTag, blockquoteConstructor);
    addTag(bodyTag, bodyConstructor);
    addTag(brTag, brConstructor);
    addTag(buttonTag, buttonConstructor);
    addTag(canvasTag, canvasConstructor);
    addTag(captionTag, tablecaptionConstructor);
    addTag(colTag, tablecolConstructor);
    addTag(colgroupTag, tablecolConstructor);
#if ENABLE(DATAGRID)
    addTag(datagridTag, datagridConstructor);
#endif

#if ENABLE(DATALIST)
    addTag(datalistTag, datalistConstructor);
#endif

#if ENABLE(DATAGRID)
    addTag(dcellTag, datagridcellConstructor);
#endif

#if ENABLE(DATAGRID)
    addTag(dcolTag, datagridcolConstructor);
#endif

    addTag(delTag, modConstructor);
    addTag(dirTag, directoryConstructor);
    addTag(divTag, divConstructor);
    addTag(dlTag, dlistConstructor);
#if ENABLE(DATAGRID)
    addTag(drowTag, datagridrowConstructor);
#endif

    addTag(embedTag, embedConstructor);
    addTag(fieldsetTag, fieldsetConstructor);
    addTag(fontTag, fontConstructor);
    addTag(formTag, formConstructor);
    addTag(frameTag, frameConstructor);
    addTag(framesetTag, framesetConstructor);
    addTag(h1Tag, headingConstructor);
    addTag(h2Tag, headingConstructor);
    addTag(h3Tag, headingConstructor);
    addTag(h4Tag, headingConstructor);
    addTag(h5Tag, headingConstructor);
    addTag(h6Tag, headingConstructor);
    addTag(headTag, headConstructor);
    addTag(hrTag, hrConstructor);
    addTag(htmlTag, htmlConstructor);
    addTag(iframeTag, iframeConstructor);
    addTag(imageTag, imgToimageConstructor);
    addTag(imgTag, imageConstructor);
    addTag(inputTag, inputConstructor);
    addTag(insTag, modConstructor);
    addTag(isindexTag, isindexConstructor);
    addTag(keygenTag, keygenConstructor);
    addTag(labelTag, labelConstructor);
    addTag(legendTag, legendConstructor);
    addTag(liTag, liConstructor);
    addTag(linkTag, linkConstructor);
    addTag(listingTag, preConstructor);
    addTag(mapTag, mapConstructor);
    addTag(marqueeTag, marqueeConstructor);
    addTag(menuTag, menuConstructor);
    addTag(metaTag, metaConstructor);
    addTag(objectTag, objectConstructor);
    addTag(olTag, olistConstructor);
    addTag(optgroupTag, optgroupConstructor);
    addTag(optionTag, optionConstructor);
    addTag(pTag, paragraphConstructor);
    addTag(paramTag, paramConstructor);
    addTag(preTag, preConstructor);
#if ENABLE(PROGRESS_TAG)
    addTag(progressTag, progressConstructor);
#endif

    addTag(qTag, quoteConstructor);
    addTag(scriptTag, scriptConstructor);
    addTag(selectTag, selectConstructor);
#if ENABLE(VIDEO)
    addTag(sourceTag, sourceConstructor);
#endif

    addTag(styleTag, styleConstructor);
    addTag(tableTag, tableConstructor);
    addTag(tbodyTag, tablesectionConstructor);
    addTag(tdTag, tablecellConstructor);
    addTag(textareaTag, textareaConstructor);
    addTag(tfootTag, tablesectionConstructor);
    addTag(thTag, tablecellConstructor);
    addTag(theadTag, tablesectionConstructor);
    addTag(titleTag, titleConstructor);
    addTag(trTag, tablerowConstructor);
    addTag(ulTag, ulistConstructor);
#if ENABLE(VIDEO)
    addTag(videoTag, videoConstructor);
#endif

    addTag(xmpTag, preConstructor);
}


当html页面本身被下载后, webkit开始接续html,当解析到上述符合名字的node时候会调用,注册的factory创建节点。然后创建节点后开始解析节点的属性,碰到上述map中定义的属性那么久创建属性的时间listener
(对本例而言)。




上图就是html下载后的parsehtml时候发现有个title的节点,然后常见这样一个节点类。
以此类推最后会发现一个body的节点。


当常见body节点后,parsemappedattrhi触发创建节点的属性事件接受者。



然后发现创建的eventlistener被加到domwindow 的eventtarget内部的一个map中(这个有点特殊,没有加到htmlbodyelement自己的eventtarget中,不过这个是特定的时事件处理模式,即onload,onunload等是作为document的事件进行处理的;如果将onclick加到body后那么这个listener还是在element上的)



最后onload事件触发,js函数得到调用。
这儿为什么刚才会有一个jslazyeventlistener,原因就在这儿,即onload内的js是在事件触发时候构造js函数来执行的。


下面增加一个input 和onclick,去掉body内的attr来看看真正的鼠标点击。。。

total





由于过程和body基本类似,直接上图


这儿差异在于,input代表为htmlelement,而每个htmlelement 均最终派生再 node 而每个node都派生自eventtarget,这个不太同于body内的onload事件处理器。



然后点击时候如下:


我们会看到,实际上底部的callstack显示无非就是一个鼠标点击事件被捕获了,然后


  if (m_nodeUnderMouse)
        swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount);

通过这个m_nodeUnderMouse 呼叫到了刚才我们分析的input。

那么这个m_nodeUnderMouse哪儿来的呢?

void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
{
 ....
   m_nodeUnderMouse = result;
...

存在这样一个监测鼠标移动的函数,它在不断的刷新鼠标所在点所对应的node。



我们继续观察,那么如果input没有处理这个onlickc,而body有,那么如何呢?


可以发现,处理逻辑是先自己的所在节点处理,如果交给祖先处理。

如果是窗口事件,还要交给window对象处理。



阅读(751) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~