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