初时代新潮流WebOS 【22】WebKit,鼠标引发的故事

转载:http://blog.sina.com.cn/s/blog_46d0a3930100dgvi.html

【22】WebKit,鼠标引发的故事

图片 1

Figure 1. JavaScript onclick event
Courtesy
http://farm4.static.flickr.com/3302/3640149734_3268bf297f_o.jpg
先押一样段落简单的HTML文件。在浏览器里打开这文件,将看到个别摆设相片。把鼠标移动至第一摆像,点击鼠标左键,将机关弹有一个窗口,上题“World”。
但是当鼠标移动至第二布置像,或者其他任何区域,点击鼠标,却尚无影响。关闭“World”窗口,自动弹有第二独窗口,上题“Hello”。

<html>
<script type=”text/javascript”>
function myfunction(v)
{
alert(v)
}
</script>
<body onclick=”myfunction(‘Hello’)”>
<p>
<img onclick=”myfunction(‘World’)” height=”250″ width=”290″
src=”http://www.dirjournal.com/info/wp-content/uploads/2009/02/antarctica\_mountain\_mirrored.jpg"&gt;
<p>
<img height=”206″ width=”275″
src=”http://media-cdn.tripadvisor.com/media/photo-s/01/26/f4/eb/hua-shan-hua-mountain.jpg"&gt;
</body>
</html>

马上段HTML文件并未啊特别之处,所有略知一点HTML的食指,估计还见面刻画。但是耳熟能详,未必等于深入摸底。不妨反问自己几乎只问题,

  1. 浏览器如何了解,是否鼠标的位置,在率先个影的限外?
    2.
    如修改一下HTML文件,把第一摆设相片替换成另外一样摆相片,前后两张像的尺码不同。在浏览器里打开修改后的文件,我们见面发现,能够触发弹出窗口事件之区域面积,随着像的转如果机关改变。浏览器中,是透过怎样的体制,自动识别事件触发区域之?
  2. Onclick 是HTML的素属性(Element
    attribute),还是JavaScript的事件侦听器(EventListener)?换而言之,当用户点击鼠标以后,负责处理onclick事
    件的,是Webkit 还是JavaScript Engine?
  3. Alert()
    是HTML定义之法,还是JavaScript提供的函数?谁背转那片个弹出的窗口,是Webkit还是JavaScript
    Engine?
    5.
    在意到起少数独onclick=”myfunction(…)”,当用户以第一布置照片里点拍鼠标的时节,为什么是次弹出,而无是以弹出?
    6.
    除了PC上之浏览器以外,手机是否为可以好同样的波及其响应?假如手机及并未鼠标,但是来触摸屏,如何把onclick定义成用手指点击屏幕?
  4. 为何要深刻了解这些问题? 除了满足好奇心以外,还发出没发出其他目的?

图片 2

Figure 2. Event callback stacks
Courtesy
http://farm4.static.flickr.com/3611/3640149728_bc64397f60_o.gif
当用户点击鼠标,在OS语汇里,这让起了一如既往次于暂停(interrupt)。系统基本(kernel)
如何侦听以及处理interrupt,不妨参考“Programming Embedded Systems”
一开,Chapter 8. Interrupts。这里不进行介绍,有些许只由,1.
这些内容很糊涂,而且跟本文主题不极端相关。2.
起Webkit角度看,它不用关心interrupt 以及interrupt handling
的切实可行实现,因为Webkit建筑在GUI Toolkit之上,而GUI
Toolkit已经将脚的interrupt
handling,严密地包裹起来。Webkit只待调用GUI Toolkit
的连带APIs,就可收获鼠标的点击和走,键盘的输入等等诸多事件。所以,本文着重讨论Figure
2 中,位于顶部之Webkit和JavaScript两重合。

今非昔比之操作系统,有照应的GUI Toolkit。GUI
Toolkit提供平等雨后春笋APIs,方便应用程序去管理各色窗口及控件,以及鼠标和键盘等等UI事件的收缴和应。

  1. 微软的Windows操作系统之上的GUI Toolkit,是MFC(Microsoft Fundation
    Classes)。
  2. Linux操作系统GNOME环境的GUI Toolkit,是GTK+.
  3. Linux KDE环境的,是QT。
  4. Java的GUI Toolkit有三三两两单,一个凡Sun Microsystem的Java
    Swing,另一个凡IBM Eclipse的SWT。
    Swing对native的靠较小,它依靠Java 2D来绘制窗口以及控件,而Java
    2D对于native的乘基本上只有限于用native library画点画线着色。
    SWT对native的指较充分,很多总人口拿SWT理解也Java通过JNI,对MFC,GTK+和QT进行的包裹。这种理解则未是普准儿,但是大
    体上啊未尝错。

出了GUI
Toolkit,应用程序处理鼠标和键盘等等UI事件的法门,就简化了好多,只待开片码业务。

 

  1. 把事件源于(event source),与事件处理逻辑(event listener) 绑定。

  2. 浅析并施行事件处理逻辑。

Figure 3 显示的凡Webkit如何绑定event source和event listener。Figure 4
显示的是Webkit如何调用JavaScript Engine,解析并推行事件处理逻辑。

 

先是看望event source,注意到在HTML文件里来如此一句子,
<img onclick=”myfunction(‘World’)” height=”250″ width=”290″
src=”…/antarctica_mountain_mirrored.jpg”>
立马句话里“<img>”标识告诉Webkit,需要以浏览器页面里摆放一摆放照片,“src”属性明确了照的自,“height,
width”明确了影的尺码。“onclick”属性提醒Webkit,当用户将鼠标移动至照片显得的区域,并点击鼠标时(onclick),需要所有应。响应的方法定义在“onclick”属性之价内,也即是“myfunction(‘World’)”。

当Webkit解析这个HTML文件时,它根据是HTML文件生成一棵DOM
Tree,和一棵Render Tree。对承诺给这等同句<img>语句,在DOM
Tree里有一个HTMLElement节点,相应地,在Render
Tree里出一个RenderImage节点。在layout()
过程结束晚,根据<img>语句被规定的height和width,确定了RenderImage的尺寸与岗位。由于
Render Tree的RenderImage节点,与DOM
Tree的HTMLElement节点一一对应,所以HTMLElement节点所处的岗位和分寸为呼应规定。

坐onclick事件和
这个HTMLElement节点相关联,所以是HTMLElement节点的职务及分寸确定了随后,点击事件之触发区域也就是自动确定。假如修改了HTML文件,替换了照,经过layout()
过程之后,新照对应之HTMLElement节点,它的职务和分寸为自动相应变更,所以,点击事件之接触区域为就算相应地自动生成。

当onclick属性的价里,定义了哪些处理是波之逻辑。有少种植处理事件的计,1.
一直调用HTML DOM method,2.
间接调用外设的Script。onclick=”alert(‘Hello’)”,是首先种植方法。alert()是W3C制订的规范的
HTML DOM
methods之一。除之之外,也闹小复杂一点的methods,譬如可以把当下无异句改成为,<img
onclick=”document.write(‘Hello’)”>。本文的事例,onclick=”myfunction(‘world’)”,是次种方式,间接调用外设的Script。
外设的script有多,最常见的是JavaScript,另外,微软的VBScript和Adobe的ActionScript,在有的浏览器里啊克就此。即便是JavaScript,也出强版本,各个版本之间,语法上设有有差距。为了免除这些出入,降低JavaScript使用者,以及
JavaScript
Engine开发者的承担,ECMA(欧洲计算机产联)试图制订一仿照标准的JavaScript规范,称为ECMAScript。

逐浏览器采用的JavaScript Engine不同。

  1. 微软的IE浏览器,使用的JavaScript Engine是JScript
    Engine,渲染机是Trident。
  2. Firefox浏览器,使用的JavaScript
    Engine是TraceMonkey,TraceMonkey的前身是SpiderMonkey,渲染机是Gecko。TraceMonkey
    JavaScript
    Engine借用了Adobe的Tamarin的部分代码,尤其是Just-In-Time即经常编译机的代码。而Tamarin也深受用在Adobe
    Flash的Action Engine中。
  3. Opera浏览器,使用的JavaScript
    Engine是Futhark,它的前身是Linear_b,渲染机是Presto。
  4. Apple的Safari浏览器,使用的JavaScript
    Engine是SquirrelFish,渲染机是Webkit。
  5. Google的Chrome浏览器,使用的JavaScript
    Engine是V8,渲染机也是Webkit。
    6.
    Linux的KDE和GNOME环境遭受可用Konqueror浏览器,这个浏览器采用的JavaScript
    Engine是JavaScriptCore,前身是KJS,渲染机也是Webkit。
    一如既往是Webkit渲染机,可以调用不同之JavaScript
    Engine。之所以能够完成及时一点,是为Webkit的架构设计,在装置JavaScript
    Engine的时刻,利用代理器,采取了松懈之调用方式。

 

图片 3

Figure 3. The listener binding of Webkit
Courtesy
http://farm4.static.flickr.com/3659/3640149732_e55446f6b3_b.jpg
Figure 3 详细写了Webkit 设置JavaScript Engine 的皆经过。在Webkit
解析HTML文件,生成DOM Tree 和Render Tree 的长河被,当解析到 <img
onclick=”…” src=”…”> 这无异于句之时节,生成DOM Tree中的 HTMLElement
节点,以及Render Tree 中 RenderImage 节点。如前方文所述。在生成HTMLElement
节点的长河遭到,因为在意到闹onclick属性,Webkit决定用被 HTMLElement
节点绑定一个 EventListener,参见Figure 3 中第7步。

Webkit 把有EventListener 的开创工作,交给Document 统一处理,类似于
Design Patterns中,Singleton 的用法。也就是说,DOM Tree的根本节点
Document,掌握在这个网页涉及的兼具EventListeners。 有趣的是,当Document
接获请求后,不管对的是呀一样像样事件,一律吃代理器 (kjsProxy)
生成一个JSLazyEventListener。之所以说这实现方式有趣,是因生几乎独问题待特别留意,

1.
一个HTMLElement节点,如果来差不多只类似于onclick的波性质,那么尽管待多个照应的EventListener
object instances与之绑定。

  1. 每个节点的每个事件性质,都对应一个独的EventListener object
    instance。不同节点不一起享同一个 EventListener object
    instance。即便与一个节点受到,不同之风波性质,对应的吧是差的EventListener
    object instances。

及时是一个值得说道之地方。不同节点不同事件对应彼此独立的EventListener
object
instances,这种做法让不同节点内的消息传递,造成了杀十分障碍。反过来设想一下,如果能发生同一种体制,让与一个object
instance,穿梭给多只HTMLElement
Nodes之间,那么浏览器的呈现能力将会晤大大加强,届时,将见面并发大量底划时代的匪夷所思之采用。

  1. DOM
    Tree的到底节点,Document,统一确定了于是什么工具,去分析事件性质之价值,以及实践之属于性值所定义的事件处理逻辑。如前方文所述,事件性质之价值,分成HTML
    DOM methods 和JavaScript
    两看似。但是无论是有HTMLElement节点的某事件性质的值属于哪一样近似,Document一律为
    kjsProxy代理器,生成一个 EventListener。
    瞧是代理器的名字就是懂得,kjsProxy生成的
    EventListener,一定是依托JavaScriptCore Engine,也就是先的KJS
    JavaScript
    Engine,来实施事件处理逻辑的。核实一下源代码,这个猜想果然对。
  1. 万一想拿JavaScriptCore 替换成其他JavaScript
    Engine,例如Google的V8,不可知大概地转移configuration
    file,而得改一统分源代码。所幸的是,Webkit的架构设计相当清楚,所以需要改变部分不多,关键部位是将Document.{h,cpp}
    以及其他少数源代码中,涉及kjsProxy 的片,改化任何Proxy即可。
  1. kjsProxy
    生成的EventListener,是JSLazyEventListener。解释一下JSLazyEventListener
    命名的含意,JS容易理解,意思是拿事件处理逻辑,交给JavaScript engine
    负责。所谓 lazy
    指的是,除非用户以照片显得区域点击了鼠标,否则,JavaScript Engine
    不主动处理事件属性之值所规定之事件处理逻辑。

暨 lazy做法相呼应的凡JIT即经常编译,譬如有一些JavaScript
Engine,在用户还没点任何事件以前,预先编译了具有与该网页相关的JavaScript,这样,当用户触发了一个特定事件,需要调用某些
JavaScript
functions时,运行速度就会加快。当然,预先编译会有代价,可能会见有有JavaScript
functions,虽然编译过了,但是从来没为真正实施了。

 

图片 4

Figure 4. The event handling of Webkit
Courtesy
http://farm4.static.flickr.com/3390/3640149730_0c98f0218d_b.jpg
当解析了HTML文件,生成了总体的DOM Tree 和Render Tree
以后,Webkit就准备好去响应与处理用户触发的波了。响应和处理事件的方方面面工艺流程,如Figure
4所描述。整个流程分为两单等级,

 

1. 寻找 EventTargetNode。

当用户触发某个事件,例如点击鼠标,根据鼠标所在位置,从Render
Tree的到底节点开始,一路找寻到鼠标所在位置对应的纸牌节点。Render
Tree根节点对应之是不折不扣浏览器页面,而叶子节点对应的区域面积最小。

打Render Tree根节点,到叶子节点,沿途每个Render Tree Node,都对应一个DOM
Tree Node。这同一错DOM Tree
Nodes中,有些节点响应用户触发的轩然大波,另一对勿响应。例如在本文的例证中,<body>
tag 对应的DOM Tree Node,和率先摆放相片的<img> tag 对应的DOM Tree
Node,都针对onclick事件闹应。

先是路了时,Webkit得到一个EventTargetNode,这个节点是一个DOM Tree
Node,而且是对准事件闹响应的DOM Tree Node。如果有多个DOM Tree
Nodes对事件有响应,EventTargetNode是十分最接近叶子的中节点。

 

2. 实行事件处理逻辑。

若是对跟一个事件,有差不多单响应节点,那么JavaScript Engine
依次拍卖及时同样失误节点受到,每一个节点定义的事件处理逻辑。事件处理逻辑,以字符串的款型定义在事变性质的价备受。在本文的例证中,HTML文件包
含<img onclick=”myfunction(‘World’)”>,和<body
onclick=”myfunction(‘Hello’)”>,这代表,有些许单DOM Tree Nodes
对onclick事件闹应,它们的事件处理逻辑分别是myfunction(‘World’)
和myfunction(‘Hello’),这有限个字符串。

当JavaScript Engine
获得事件处理逻辑的字符串后,它将这个字符串,根据JavaScript的语法规则,解析为同株树状结构,称作Parse
Tree。有矣马上棵Parse Tree,JavaScript
Engine就可知道这字符串中,哪些是函数称为,哪些是变量,哪些是变量值。理解掌握以后,JavaScript
Engine 就得履事件处理逻辑了。

 

正文例子的事件处理过程,如Figure 4中第16步,到第35步所展示。
正文的例证中,“myfunction(‘World’)”
这个字符串本身并没有概念事件处理逻辑,而就是供了一个JavaScript函数的函数曰,以及函数的参数的价值。当JavaScript
Engine
得到这字符串以后,解析,执行。执行之结果是得到函数实体的代码。函数实体的代码中,最重大之是alert(v)
这同一词。JavaScript Engine 把立即等同句解析成Parse Tree,然后实施。

注意到本文例子中,对于与一个风波onclick,有少独例外之DOM Tree Nodes
有应。处理当下点儿单节点的先后顺序要么出于capture path,要么是因为bubbling
path决定,如Figure 5所著。(Figure
5中对应的HTML文件,不是本文所引起的例子)。在HTML文件被,可以确定event.bubbles属性。如果无确定,那即便比如bubbling的
顺序进行,所以本文的例子,是先实施<img>,弹出“World”
的窗口,关掉“World”窗口后,接着执行<body>,弹出“Hello” 的窗口。

图片 5

Figure 5. The capture and bubbling of event by the DOM tree.
Courtesy http://www.w3.org/TR/DOM-Level-3-Eventsventflow.png
眼看同样节约于平淡,因为涉嫌了无与伦比多之源代码细节。之所以这样不厌其烦地证明细节,是为化解什么重新有效率地处理事件,以及供再增长的手段去处理事件。待续。