webkit中hover的几个小知识

1。每个元素都有一个hover状态,通过hovered和setHover来控制,该函数在WebCore::Node上:

bool hovered() const { return getFlag(IsHoveredFlag); }
....
virtual void setHovered( bool f = true ) { setFlag(f, IsHoveredFlag); }

 

2. setHover是个虚函数,WebCore::ContainerNode重载了它,并且能够更新界面

void ContainerNode::setHovered( bool over)
{
     if (over == hovered()) return ;
     Node::setHovered(over);
     // note that we need to recalc the style
     // FIXME: Move to Element
     if (renderer()) {
         if (renderer()->style()->affectedByHoverRules())
             setNeedsStyleRecalc();
         if (renderer() && renderer()->style()->hasAppearance())
             renderer()->theme()->stateChanged(renderer(), HoverState);
     }
}

3. 参照上面的代码,判断一个节点是否有Hover的CSS关联方法:renderer()->style()->affectedByHoverRules()

 

4. WebCore::Document元素保存一个当前的hover指针:

void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
{
     m_hoverNode = newHoverNode;
}

 

5. 重新设置一个hover节点完整的方法:

static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
{
     if (!obj1 || !obj2)
         return 0;
     for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
         for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
             if (currObj1 == currObj2)
                 return currObj1;
     return 0;
}
static void switchHover(Document *document, Node* oldHoveredNode, Node* newHoveredNode)
{
     RenderObject *ancestor = commonAncestor(oldHoveredNode ? oldHoveredNode->renderer(): NULL, newHoveredNode ? newHoveredNode->renderer() : NULL);
     if (oldHoveredNode){
         oldHoveredNode->setHovered( false );
         for (RenderObject* curr = oldHoveredNode->renderer(); curr && curr != ancestor; curr = curr->hoverAncestor()) {
             if (curr->node() && !curr->isText() /*&& curr->node()->inActiveChain()*/ )
                 curr->node()->setHovered( false );
         }
     }
     document->setHoverNode(newHoveredNode);
     if (newHoveredNode)
     {
         for (RenderObject* curr = newHoveredNode->renderer(); curr; curr = curr->hoverAncestor()) {
             if (curr->node() && !curr->isText() /*&& curr->node()->inActiveChain()*/ )
                 curr->node()->setHovered( true );
         }
         newHoveredNode->setHovered( true );
     }
}

 

6. EventHandler的fakeMouseMoveEvent: 产生一个假的鼠标移动事件,在窗口位置、状态变化后重新hover,但实际上用户并没有移动鼠标:

  1) 定义

class EventHandler {
....
Timer<EventHandler> m_fakeMouseMoveEventTimer;
....
};

  2) 初始化

EventHandler::EventHandler(Frame* frame)
     : m_frame(frame)
     ....
     , m_fakeMouseMoveEventTimer( this , &EventHandler::fakeMouseMoveEventTimerFired)
......


你可能感兴趣的:(webkit,hover)