mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
This is implement Hover Event. If over element, currently full reflow. after PR, will make partial reflow.
This commit is contained in:
parent
d2f8b593a9
commit
c8d503898a
14 changed files with 171 additions and 20 deletions
|
@ -11,9 +11,9 @@ use platform::{Application, Window};
|
||||||
use windowing::{WindowEvent, WindowMethods,
|
use windowing::{WindowEvent, WindowMethods,
|
||||||
WindowNavigateMsg,
|
WindowNavigateMsg,
|
||||||
IdleWindowEvent, RefreshWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent,
|
IdleWindowEvent, RefreshWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent,
|
||||||
MouseWindowEventClass,ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent,
|
MouseWindowEventClass, MouseWindowMoveEventClass,ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent,
|
||||||
FinishedWindowEvent, QuitWindowEvent,
|
FinishedWindowEvent, QuitWindowEvent,
|
||||||
MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent, MouseMoveEventClass};
|
MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
||||||
|
|
||||||
|
|
||||||
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
||||||
|
@ -515,7 +515,7 @@ impl IOCompositor {
|
||||||
self.on_mouse_window_event_class(mouse_window_event);
|
self.on_mouse_window_event_class(mouse_window_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseMoveEventClass(cursor) => {
|
MouseWindowMoveEventClass(cursor) => {
|
||||||
self.on_mouse_window_move_event_class(cursor);
|
self.on_mouse_window_move_event_class(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use layers::platform::surface::{NativeCompositingGraphicsContext, NativeSurfaceM
|
||||||
use layers::texturegl::{Texture, TextureTarget};
|
use layers::texturegl::{Texture, TextureTarget};
|
||||||
#[cfg(target_os="macos")] use layers::texturegl::TextureTargetRectangle;
|
#[cfg(target_os="macos")] use layers::texturegl::TextureTargetRectangle;
|
||||||
use pipeline::CompositionPipeline;
|
use pipeline::CompositionPipeline;
|
||||||
use script::dom::event::{ClickEvent, MouseDownEvent, MouseUpEvent, MouseMoveEvent};
|
use script::dom::event::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
|
||||||
use script::script_task::SendEventMsg;
|
use script::script_task::SendEventMsg;
|
||||||
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
|
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
|
||||||
use servo_msg::constellation_msg::PipelineId;
|
use servo_msg::constellation_msg::PipelineId;
|
||||||
|
@ -248,7 +248,6 @@ impl CompositorLayer {
|
||||||
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor),
|
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor),
|
||||||
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor),
|
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.pipeline.script_chan.send(SendEventMsg(self.pipeline.id.clone(), message));
|
self.pipeline.script_chan.send(SendEventMsg(self.pipeline.id.clone(), message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,9 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
let mut layout_data_ref = self.mutate_layout_data();
|
let mut layout_data_ref = self.mutate_layout_data();
|
||||||
match *layout_data_ref.get() {
|
match *layout_data_ref.get() {
|
||||||
Some(ref mut layout_data) => {
|
Some(ref mut layout_data) => {
|
||||||
|
//FIXME To implement a clear() on SmallVec and use it(init_applicable_declarations).
|
||||||
|
layout_data.data.init_applicable_declarations();
|
||||||
|
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(self,
|
||||||
style_attribute,
|
style_attribute,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -35,9 +35,9 @@ use script::dom::node::{ElementNodeTypeId, LayoutDataRef};
|
||||||
use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId};
|
use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId};
|
||||||
use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery};
|
use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery};
|
||||||
use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitNowMsg, LayoutQuery};
|
use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitNowMsg, LayoutQuery};
|
||||||
use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse};
|
use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse, MouseOverQuery, MouseOverResponse};
|
||||||
use script::layout_interface::{ContentChangedDocumentDamage, LayoutChan, Msg, PrepareToExitMsg};
|
use script::layout_interface::{ContentChangedDocumentDamage, LayoutChan, Msg, PrepareToExitMsg};
|
||||||
use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, ReflowDocumentDamage};
|
use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, ReflowDocumentDamage, UntrustedNodeAddress};
|
||||||
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
|
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
|
||||||
use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg};
|
use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
|
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
|
||||||
|
@ -753,7 +753,6 @@ impl LayoutTask {
|
||||||
.to_untrusted_node_address()))
|
.to_untrusted_node_address()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret: Option<HitTestResponse> = None;
|
let ret: Option<HitTestResponse> = None;
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -769,6 +768,46 @@ impl LayoutTask {
|
||||||
reply_chan.send(Err(()));
|
reply_chan.send(Err(()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
MouseOverQuery(_, point, reply_chan) => {
|
||||||
|
fn mouse_over_test(x: Au, y: Au, list: &[DisplayItem<OpaqueNode>], result: &mut ~[UntrustedNodeAddress]) {
|
||||||
|
for item in list.rev_iter() {
|
||||||
|
match *item {
|
||||||
|
ClipDisplayItemClass(ref cc) => {
|
||||||
|
mouse_over_test(x, y, cc.child_list, result);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in list.rev_iter() {
|
||||||
|
let bounds = item.bounds();
|
||||||
|
|
||||||
|
// TODO(tikue): This check should really be performed by a method of
|
||||||
|
// DisplayItem.
|
||||||
|
if x < bounds.origin.x + bounds.size.width &&
|
||||||
|
bounds.origin.x <= x &&
|
||||||
|
y < bounds.origin.y + bounds.size.height &&
|
||||||
|
bounds.origin.y <= y {
|
||||||
|
result.push(item.base()
|
||||||
|
.extra
|
||||||
|
.to_untrusted_node_address());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mouse_over_list:~[UntrustedNodeAddress] = ~[];
|
||||||
|
for display_list in self.display_list_collection.as_ref().unwrap().get().lists.rev_iter() {
|
||||||
|
let (x, y) = (Au::from_frac_px(point.x as f64),
|
||||||
|
Au::from_frac_px(point.y as f64));
|
||||||
|
mouse_over_test(x,y,display_list.list, &mut mouse_over_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if mouse_over_list.is_empty() {
|
||||||
|
reply_chan.send(Err(()));
|
||||||
|
} else {
|
||||||
|
reply_chan.send(Ok(MouseOverResponse(mouse_over_list)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,14 @@ impl PrivateLayoutData {
|
||||||
parallel: DomParallelInfo::new(),
|
parallel: DomParallelInfo::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initialize the function for applicable_declarations.
|
||||||
|
pub fn init_applicable_declarations(&mut self) {
|
||||||
|
//FIXME To implement a clear() on SmallVec and use it(init_applicable_declarations).
|
||||||
|
self.applicable_declarations = SmallVec16::new();
|
||||||
|
self.before_applicable_declarations = SmallVec0::new();
|
||||||
|
self.after_applicable_declarations = SmallVec0::new();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LayoutDataWrapper {
|
pub struct LayoutDataWrapper {
|
||||||
|
|
|
@ -349,6 +349,10 @@ impl<'le> TElement for LayoutElement<'le> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_hover_state(&self) -> bool {
|
||||||
|
self.element.node.get_hover_state()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
|
/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
//! A windowing implementation using GLFW.
|
//! A windowing implementation using GLFW.
|
||||||
|
|
||||||
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
||||||
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
|
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass, MouseWindowMoveEventClass};
|
||||||
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
||||||
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent, MouseMoveEventClass};
|
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
||||||
use windowing::RefreshWindowEvent;
|
use windowing::RefreshWindowEvent;
|
||||||
use windowing::{Forward, Back};
|
use windowing::{Forward, Back};
|
||||||
|
|
||||||
|
@ -157,8 +157,8 @@ impl WindowMethods<Application> for Window {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
window.glfw_window.set_cursor_pos_callback(
|
window.glfw_window.set_cursor_pos_callback(
|
||||||
glfw_callback!(glfw::CursorPosCallback(win: &glfw::Window, xpos: f64, ypos: f64) {
|
glfw_callback!(glfw::CursorPosCallback(_win: &glfw::Window, xpos: f64, ypos: f64) {
|
||||||
local_window().event_queue.push(MouseMoveEventClass(Point2D(xpos as f32, ypos as f32)));
|
local_window().event_queue.push(MouseWindowMoveEventClass(Point2D(xpos as f32, ypos as f32)));
|
||||||
}));
|
}));
|
||||||
window.glfw_window.set_scroll_callback(
|
window.glfw_window.set_scroll_callback(
|
||||||
glfw_callback!(glfw::ScrollCallback(win: &glfw::Window, xpos: f64, ypos: f64) {
|
glfw_callback!(glfw::ScrollCallback(win: &glfw::Window, xpos: f64, ypos: f64) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub enum WindowEvent {
|
||||||
/// Sent when a mouse hit test is to be performed.
|
/// Sent when a mouse hit test is to be performed.
|
||||||
MouseWindowEventClass(MouseWindowEvent),
|
MouseWindowEventClass(MouseWindowEvent),
|
||||||
/// Sent when a mouse move.
|
/// Sent when a mouse move.
|
||||||
MouseMoveEventClass(Point2D<f32>),
|
MouseWindowMoveEventClass(Point2D<f32>),
|
||||||
/// Sent when the user scrolls. Includes the current cursor position.
|
/// Sent when the user scrolls. Includes the current cursor position.
|
||||||
ScrollWindowEvent(Point2D<f32>, Point2D<i32>),
|
ScrollWindowEvent(Point2D<f32>, Point2D<i32>),
|
||||||
/// Sent when the user zooms.
|
/// Sent when the user zooms.
|
||||||
|
|
|
@ -101,6 +101,8 @@ impl NodeFlags {
|
||||||
|
|
||||||
/// Specifies whether this node is in a document.
|
/// Specifies whether this node is in a document.
|
||||||
bitfield!(NodeFlags, is_in_doc, set_is_in_doc, 0x01)
|
bitfield!(NodeFlags, is_in_doc, set_is_in_doc, 0x01)
|
||||||
|
/// Specifies whether this node is hover state for this node
|
||||||
|
bitfield!(NodeFlags, get_in_hover_state, set_is_in_hover_state, 0x02)
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl Drop for Node {
|
impl Drop for Node {
|
||||||
|
@ -546,6 +548,14 @@ impl<'a> AbstractNode {
|
||||||
pub fn is_in_doc(&self) -> bool {
|
pub fn is_in_doc(&self) -> bool {
|
||||||
self.node().flags.is_in_doc()
|
self.node().flags.is_in_doc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_hover_state(&self) -> bool {
|
||||||
|
self.node().flags.get_in_hover_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_hover_state(&self, state: bool) {
|
||||||
|
self.mut_node().flags.set_is_in_hover_state(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode {
|
impl AbstractNode {
|
||||||
|
@ -1607,6 +1617,14 @@ impl Node {
|
||||||
doc.document().wait_until_safe_to_modify_dom();
|
doc.document().wait_until_safe_to_modify_dom();
|
||||||
self.next_sibling = new_next_sibling
|
self.next_sibling = new_next_sibling
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_hover_state(&self) -> bool {
|
||||||
|
self.flags.get_in_hover_state()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_hover_state(&mut self, state: bool) {
|
||||||
|
self.flags.set_is_in_hover_state(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Reflectable for Node {
|
impl Reflectable for Node {
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub enum LayoutQuery {
|
||||||
ContentBoxesQuery(AbstractNode, Chan<ContentBoxesResponse>),
|
ContentBoxesQuery(AbstractNode, Chan<ContentBoxesResponse>),
|
||||||
/// Requests the node containing the point of interest
|
/// Requests the node containing the point of interest
|
||||||
HitTestQuery(AbstractNode, Point2D<f32>, Chan<Result<HitTestResponse, ()>>),
|
HitTestQuery(AbstractNode, Point2D<f32>, Chan<Result<HitTestResponse, ()>>),
|
||||||
|
MouseOverQuery(AbstractNode, Point2D<f32>, Chan<Result<MouseOverResponse, ()>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The address of a node. Layout sends these back. They must be validated via
|
/// The address of a node. Layout sends these back. They must be validated via
|
||||||
|
@ -66,6 +67,7 @@ pub type UntrustedNodeAddress = *c_void;
|
||||||
pub struct ContentBoxResponse(Rect<Au>);
|
pub struct ContentBoxResponse(Rect<Au>);
|
||||||
pub struct ContentBoxesResponse(~[Rect<Au>]);
|
pub struct ContentBoxesResponse(~[Rect<Au>]);
|
||||||
pub struct HitTestResponse(UntrustedNodeAddress);
|
pub struct HitTestResponse(UntrustedNodeAddress);
|
||||||
|
pub struct MouseOverResponse(~[UntrustedNodeAddress]);
|
||||||
|
|
||||||
/// Determines which part of the
|
/// Determines which part of the
|
||||||
#[deriving(Eq, Ord)]
|
#[deriving(Eq, Ord)]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::codegen::RegisterBindings;
|
||||||
use dom::bindings::utils::{Reflectable, GlobalStaticData};
|
use dom::bindings::utils::{Reflectable, GlobalStaticData};
|
||||||
use dom::document::AbstractDocument;
|
use dom::document::AbstractDocument;
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseUpEvent, MouseMoveEvent};
|
use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use dom::eventtarget::AbstractEventTarget;
|
use dom::eventtarget::AbstractEventTarget;
|
||||||
use dom::htmldocument::HTMLDocument;
|
use dom::htmldocument::HTMLDocument;
|
||||||
|
@ -20,7 +20,7 @@ use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDi
|
||||||
use html::hubbub_html_parser;
|
use html::hubbub_html_parser;
|
||||||
use layout_interface::{AddStylesheetMsg, DocumentDamage};
|
use layout_interface::{AddStylesheetMsg, DocumentDamage};
|
||||||
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
|
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
|
||||||
use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery};
|
use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery, MouseOverQuery, MouseOverResponse};
|
||||||
use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg};
|
use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg};
|
||||||
use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg};
|
use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg};
|
||||||
use layout_interface::ContentChangedDocumentDamage;
|
use layout_interface::ContentChangedDocumentDamage;
|
||||||
|
@ -405,6 +405,8 @@ pub struct ScriptTask {
|
||||||
|
|
||||||
/// The JavaScript runtime.
|
/// The JavaScript runtime.
|
||||||
js_runtime: js::rust::rt,
|
js_runtime: js::rust::rt,
|
||||||
|
|
||||||
|
mouse_over_targets:Option<~[AbstractNode]>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the relevant page from the associated JS Context.
|
/// Returns the relevant page from the associated JS Context.
|
||||||
|
@ -440,6 +442,7 @@ impl ScriptTask {
|
||||||
compositor: compositor,
|
compositor: compositor,
|
||||||
|
|
||||||
js_runtime: js_runtime,
|
js_runtime: js_runtime,
|
||||||
|
mouse_over_targets:None
|
||||||
};
|
};
|
||||||
|
|
||||||
script_task
|
script_task
|
||||||
|
@ -882,7 +885,75 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
MouseDownEvent(..) => {}
|
MouseDownEvent(..) => {}
|
||||||
MouseUpEvent(..) => {}
|
MouseUpEvent(..) => {}
|
||||||
MouseMoveEvent(point) => {}
|
MouseMoveEvent(point) => {
|
||||||
|
let document = page.frame.expect("root frame is None").document;
|
||||||
|
let root = document.document().GetDocumentElement();
|
||||||
|
if root.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (port, chan) = Chan::new();
|
||||||
|
match page.query_layout(MouseOverQuery(root.unwrap(), point, chan), port) {
|
||||||
|
Ok(MouseOverResponse(node_address)) => {
|
||||||
|
|
||||||
|
let mut target_list:~[AbstractNode] = ~[];
|
||||||
|
let mut target_compare = false;
|
||||||
|
|
||||||
|
match self.mouse_over_targets {
|
||||||
|
Some(ref mut mouse_over_targets) => {
|
||||||
|
for node in mouse_over_targets.iter() {
|
||||||
|
node.set_hover_state(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for node_address in node_address.iter() {
|
||||||
|
let mut node = AbstractNode::from_untrusted_node_address(self.js_runtime
|
||||||
|
.ptr,
|
||||||
|
*node_address);
|
||||||
|
// Traverse node generations until a node that is an element is
|
||||||
|
// found.
|
||||||
|
while !node.is_element() {
|
||||||
|
match node.parent_node() {
|
||||||
|
Some(parent) => node = parent,
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.is_element() {
|
||||||
|
node.set_hover_state(true);
|
||||||
|
|
||||||
|
match self.mouse_over_targets {
|
||||||
|
Some(ref mouse_over_targets) => {
|
||||||
|
if !target_compare {
|
||||||
|
target_compare = !mouse_over_targets.contains(&node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
target_list.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match self.mouse_over_targets {
|
||||||
|
Some(ref mouse_over_targets) => {
|
||||||
|
if mouse_over_targets.len() != target_list.len() {
|
||||||
|
target_compare = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => { target_compare = true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if target_compare {
|
||||||
|
if self.mouse_over_targets.is_some() {
|
||||||
|
page.damage(MatchSelectorsDocumentDamage);
|
||||||
|
page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor);
|
||||||
|
}
|
||||||
|
self.mouse_over_targets = Some(target_list);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(()) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ pub trait TNode<E:TElement> : Clone {
|
||||||
fn parent_node(&self) -> Option<Self>;
|
fn parent_node(&self) -> Option<Self>;
|
||||||
fn prev_sibling(&self) -> Option<Self>;
|
fn prev_sibling(&self) -> Option<Self>;
|
||||||
fn next_sibling(&self) -> Option<Self>;
|
fn next_sibling(&self) -> Option<Self>;
|
||||||
|
|
||||||
fn is_document(&self) -> bool;
|
fn is_document(&self) -> bool;
|
||||||
fn is_element(&self) -> bool;
|
fn is_element(&self) -> bool;
|
||||||
|
|
||||||
|
@ -28,5 +27,6 @@ pub trait TElement {
|
||||||
fn get_link(&self) -> Option<&'static str>;
|
fn get_link(&self) -> Option<&'static str>;
|
||||||
fn get_local_name<'a>(&'a self) -> &'a str;
|
fn get_local_name<'a>(&'a self) -> &'a str;
|
||||||
fn get_namespace<'a>(&'a self) -> &'a Namespace;
|
fn get_namespace<'a>(&'a self) -> &'a Namespace;
|
||||||
|
fn get_hover_state(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -615,6 +615,11 @@ fn matches_simple_selector<E:TElement,N:TNode<E>>(selector: &SimpleSelector, ele
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hover => {
|
||||||
|
element.with_element(|element: &E| {
|
||||||
|
element.get_hover_state()
|
||||||
|
})
|
||||||
|
},
|
||||||
FirstChild => matches_first_child(element),
|
FirstChild => matches_first_child(element),
|
||||||
LastChild => matches_last_child(element),
|
LastChild => matches_last_child(element),
|
||||||
OnlyChild => matches_first_child(element) &&
|
OnlyChild => matches_first_child(element) &&
|
||||||
|
|
|
@ -74,6 +74,7 @@ pub enum SimpleSelector {
|
||||||
AnyLink,
|
AnyLink,
|
||||||
Link,
|
Link,
|
||||||
Visited,
|
Visited,
|
||||||
|
Hover,
|
||||||
FirstChild, LastChild, OnlyChild,
|
FirstChild, LastChild, OnlyChild,
|
||||||
// Empty,
|
// Empty,
|
||||||
Root,
|
Root,
|
||||||
|
@ -210,7 +211,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
||||||
&ClassSelector(..)
|
&ClassSelector(..)
|
||||||
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
||||||
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
||||||
| &AnyLink | &Link | &Visited
|
| &AnyLink | &Link | &Visited | &Hover
|
||||||
| &FirstChild | &LastChild | &OnlyChild | &Root
|
| &FirstChild | &LastChild | &OnlyChild | &Root
|
||||||
// | &Empty | &Lang(*)
|
// | &Empty | &Lang(*)
|
||||||
| &NthChild(..) | &NthLastChild(..)
|
| &NthChild(..) | &NthLastChild(..)
|
||||||
|
@ -468,6 +469,7 @@ fn parse_simple_pseudo_class(name: &str) -> Option<SimpleSelector> {
|
||||||
"any-link" => Some(AnyLink),
|
"any-link" => Some(AnyLink),
|
||||||
"link" => Some(Link),
|
"link" => Some(Link),
|
||||||
"visited" => Some(Visited),
|
"visited" => Some(Visited),
|
||||||
|
"hover" => Some(Hover),
|
||||||
"first-child" => Some(FirstChild),
|
"first-child" => Some(FirstChild),
|
||||||
"last-child" => Some(LastChild),
|
"last-child" => Some(LastChild),
|
||||||
"only-child" => Some(OnlyChild),
|
"only-child" => Some(OnlyChild),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue