WebKit焦点切换的流程

    WebKit Focus Shift与Tab Key Event关联,点击TAB Key后,WebKit内核会将焦点切换到下一个焦点. 焦点变换一般通过TAB Key触发,所以首先需要了解TAB Event的牏流程。

一. Tab事件的处理

    Tab Event准确说是TAB Key Event,  是在keydown阶段处理,内核处理的入口是:

 EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent);

    这个接口实现两个功能:

    1. 找到Tab Event的Target节点 : 

RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document());

    2. 在keydown阶段对dispatch事件到Target节点:

node->dispatchEvent(keydown, ec);

    以下是WebKit在收到TAB Key Event后,进行焦点切换的堆栈:    

    nextNodeWithGreaterTabIndex
    WebCore::FocusController::nextFocusableNode
    WebCore::FocusController::findFocusableNode
    WebCore::FocusController::findFocusableNodeRecursively
    WebCore::FocusController::findFocusableNodeAcrossFocusScope
    WebCore::FocusController::advanceFocusInDocumentOrder
    WebCore::FocusController::advanceFocus
    WebCore::EventHandler::defaultTabEventHandler
    WebCore::EventHandler::defaultKeyboardEventHandler
    WebCore::Node::defaultEventHandler
    WebCore::HTMLTextFormControlElement::defaultEventHandler
    WebCore::HTMLInputElement::defaultEventHandler  
    WebCore::EventDispatcher::dispatchEventPostProcess
    WebCore::EventDispatcher::dispatchEvent
    WebCore::EventDispatchMediator::dispatchEvent  
    WebCore::EventDispatcher::dispatchEvent
    WebCore::Node::dispatchEvent
    WebCore::EventTarget::dispatchEvent
    WebCore::EventHandler::keyEvent

     首先可以看到TAB Key Event事件的EventListener是HTMLInputElement, 在HTMLInputElement::defaultEventHandler中,会调用父类的::defautlEventHandler() ,最终传递到Node::defautlEventHandler(),该函数将找到Node所在的Frame上的EventHandler对象,调用EventHandler::defaultKeyboardEventHandler()方法处理键盘相关的事件; 

     EventHandler::defaultKeyboardEventHnadler(KeyboardEvent* event)方法中,根据Event的m_keyIdentifier类型来选择处理流程,如果m_keyIdentifier == "U+0009", 将调用EventHandler::defaultTabEventHandler(KeyboardEvent* event)处理Tab Key Event.

     EventHandler::defaultTabEventHandler(KeyboardEvent* event)函数通过FocusController找到下一个可聚焦(Focusable)的Node, 并将焦点切换至该Node。     

二.  焦点的查找

    从以上过程可以看出,下一个Focusable Node的查找是整个处理流程的关键步骤,在以下函数中实现:

FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start, KeyboardEvent* event)

    其中,

    start:当前的focus node; 

    start是否为空, 可分两种:

  •    start为空:

    1. 以FocusNavigationScope::rootNode()为起始点,以tree order查找tabIndex > 0的点作为winnerNode;

    2. 如果winnerNode为空,从FocusNavigationScope的根节点开始,返回第一个tabIndex为0的点;    

  •    start非空

    1.  检查start是否在Tabbing Cycle中(所谓Tabbing Cycle是由指定了tabindex属性的节点组成的集合);  如果不在,则按照DOM树的结构找到下一个Focusable Node; 如果Focusable Node不存在,进入下一步; 

    2. 在Tabbing Cycle中,查找tabIndex  == start->tabIndex()的Focusable Node,如果成功,则返回; 失败,进入下一步;

    3. 继续查找tabIndex  > start->tabIndex()的Focusable Node,成功则返回;失败则进入下一步;

    4. 从FocusNavigationScope的根节点开始,返回第一个tabIndex为0的点; 


    上面的流程可以简单理解为

    1. 如果参考点不在Tabbling Cycle上,以DOM树的顺序查找; 

    2. 优先查找tabindex相等的点; 

    3. 优先查找tabindex大于0的点; 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值