五千年(敝帚自珍)

主题:【原创】新时代新潮流WebOS 【1】 -- 邓侃

共:💬594 🌺1902
全看分页树展 · 主题 跟帖
家园 【原创】【22】WebKit,鼠标引发的故事,上

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

点看全图

外链图片需谨慎,可能会被源头改

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">

<p>

<img height="206" width="275" src="http://media-cdn.tripadvisor.com/media/photo-s/01/26/f4/eb/hua-shan-hua-mountain.jpg">

</body>

</html>

这段HTML文件没有什么特别之处,所有略知一点HTML的人,估计都会写。但是耳熟能详,未必等于深入了解。不妨反问自己几个问题,

1. 浏览器如何知道,是否鼠标的位置,在第一个照片的范围内?

2. 假如修改一下HTML文件,把第一张照片替换成另一张照片,前后两张照片的尺寸不同。在浏览器里打开修改后的文件,我们会发现,能够触发弹出窗口事件的区域面积,随着照片的改变而自动改变。浏览器内部,是通过什么样的机制,自动识别事件触发区域的?

3. Onclick 是HTML的元素属性(Element attribute),还是JavaScript的事件侦听器(EventListener)?换而言之,当用户点击鼠标以后,负责处理onclick事件的,是Webkit 还是JavaScript Engine?

4. Alert() 是HTML定义的方法,还是JavaScript提供的函数?谁负责生成那两个弹出的窗口,是Webkit还是JavaScript Engine?

5. 注意到有两个onclick="myfunction(...)",当用户在第一张照片里点击鼠标的时候,为什么是先后弹出,而不是同时弹出?

6. 除了PC上的浏览器以外,手机是否也可以完成同样的事件及其响应?假如手机上没有鼠标,但是有触摸屏,如何把onclick定义成用手指点击屏幕?

7. 为什么需要深入了解这些问题? 除了满足好奇心以外,还有没有其它目的?

点看全图

外链图片需谨慎,可能会被源头改

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的时候,利用代理器,采取了松散的调用方式。

关键词(Tags): #硅谷评论#浏览器#JavaScript
全看分页树展 · 主题 跟帖


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河