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)
......


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章