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