mirror of
https://github.com/servo/servo.git
synced 2025-06-21 07:38:59 +01:00
Basic hit testing functionality
This commit is contained in:
parent
ea1a406589
commit
f77eef5988
8 changed files with 148 additions and 20 deletions
|
@ -28,7 +28,7 @@ use std::arc;
|
||||||
|
|
||||||
/// A list of rendering operations to be performed.
|
/// A list of rendering operations to be performed.
|
||||||
pub struct DisplayList<E> {
|
pub struct DisplayList<E> {
|
||||||
priv list: ~[DisplayItem<E>]
|
list: ~[DisplayItem<E>]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> DisplayList<E> {
|
impl<E> DisplayList<E> {
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
use compositing::resize_rate_limiter::ResizeRateLimiter;
|
use compositing::resize_rate_limiter::ResizeRateLimiter;
|
||||||
use platform::{Application, Window};
|
use platform::{Application, Window};
|
||||||
use script::script_task::{LoadMsg, ScriptMsg};
|
use script::script_task::{LoadMsg, ScriptMsg, SendEventMsg};
|
||||||
use windowing::{ApplicationMethods, WindowMethods};
|
use windowing::{ApplicationMethods, WindowMethods};
|
||||||
|
use script::dom::event::ClickEvent;
|
||||||
|
|
||||||
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
@ -222,10 +223,22 @@ fn run_main_loop(port: Port<Msg>,
|
||||||
resize_rate_limiter.window_resized(width, height)
|
resize_rate_limiter.window_resized(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let script_chan_clone = script_chan.clone();
|
||||||
|
|
||||||
// When the user enters a new URL, load it.
|
// When the user enters a new URL, load it.
|
||||||
do window.set_load_url_callback |url_string| {
|
do window.set_load_url_callback |url_string| {
|
||||||
debug!("osmain: loading URL `%s`", url_string);
|
debug!("osmain: loading URL `%s`", url_string);
|
||||||
script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None)))
|
script_chan_clone.send(LoadMsg(url::make_url(url_string.to_str(), None)))
|
||||||
|
}
|
||||||
|
|
||||||
|
let script_chan_clone = script_chan.clone();
|
||||||
|
|
||||||
|
// When the user clicks, perform hit testing
|
||||||
|
do window.set_click_callback |layer_click_point| {
|
||||||
|
let world_click_point = layer_click_point + *world_offset;
|
||||||
|
debug!("osmain: clicked at %?", world_click_point);
|
||||||
|
|
||||||
|
script_chan_clone.send(SendEventMsg(ClickEvent(world_click_point)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the user scrolls, move the layer around.
|
// When the user scrolls, move the layer around.
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
use css::matching::MatchMethods;
|
use css::matching::MatchMethods;
|
||||||
use css::select::new_css_select_ctx;
|
use css::select::new_css_select_ctx;
|
||||||
use layout::aux::{LayoutData, LayoutAuxMethods};
|
use layout::aux::{LayoutData, LayoutAuxMethods};
|
||||||
|
use layout::box::RenderBox;
|
||||||
use layout::box_builder::LayoutTreeBuilder;
|
use layout::box_builder::LayoutTreeBuilder;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
||||||
|
@ -32,15 +33,17 @@ use newcss::types::OriginAuthor;
|
||||||
use script::dom::event::ReflowEvent;
|
use script::dom::event::ReflowEvent;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use script::layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, ContentBoxQuery};
|
use script::layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, ContentBoxQuery};
|
||||||
use script::layout_interface::{ContentBoxResponse, ContentBoxesQuery, ContentBoxesResponse};
|
use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse};
|
||||||
use script::layout_interface::{ExitMsg, LayoutQuery, LayoutResponse, LayoutTask};
|
use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitMsg, LayoutQuery};
|
||||||
use script::layout_interface::{MatchSelectorsDamage, Msg, NoDamage, QueryMsg, ReflowDamage};
|
use script::layout_interface::{LayoutResponse, LayoutTask, MatchSelectorsDamage, Msg, NoDamage};
|
||||||
|
use script::layout_interface::{QueryMsg, ReflowDamage};
|
||||||
use script::script_task::{ScriptMsg, SendEventMsg};
|
use script::script_task::{ScriptMsg, SendEventMsg};
|
||||||
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
||||||
use servo_net::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
use servo_util::time::{ProfilerChan, profile, time};
|
use servo_util::time::{ProfilerChan, profile, time};
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
|
use std::net::url::Url;
|
||||||
|
|
||||||
pub fn create_layout_task(render_task: RenderTask,
|
pub fn create_layout_task(render_task: RenderTask,
|
||||||
img_cache_task: ImageCacheTask,
|
img_cache_task: ImageCacheTask,
|
||||||
|
@ -67,6 +70,8 @@ struct Layout {
|
||||||
local_image_cache: @mut LocalImageCache,
|
local_image_cache: @mut LocalImageCache,
|
||||||
from_script: Port<Msg>,
|
from_script: Port<Msg>,
|
||||||
font_ctx: @mut FontContext,
|
font_ctx: @mut FontContext,
|
||||||
|
doc_url: Option<Url>,
|
||||||
|
screen_size: Option<Size2D<Au>>,
|
||||||
|
|
||||||
/// This is used to root reader data.
|
/// This is used to root reader data.
|
||||||
layout_refs: ~[@mut LayoutData],
|
layout_refs: ~[@mut LayoutData],
|
||||||
|
@ -90,6 +95,9 @@ impl Layout {
|
||||||
local_image_cache: @mut LocalImageCache(image_cache_task),
|
local_image_cache: @mut LocalImageCache(image_cache_task),
|
||||||
from_script: from_script,
|
from_script: from_script,
|
||||||
font_ctx: fctx,
|
font_ctx: fctx,
|
||||||
|
doc_url: None,
|
||||||
|
screen_size: None,
|
||||||
|
|
||||||
layout_refs: ~[],
|
layout_refs: ~[],
|
||||||
css_select_ctx: @mut new_css_select_ctx(),
|
css_select_ctx: @mut new_css_select_ctx(),
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
|
@ -102,6 +110,21 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a layout context for use in building display lists, hit testing, &c.
|
||||||
|
fn build_layout_context(&self) -> LayoutContext {
|
||||||
|
let image_cache = self.local_image_cache;
|
||||||
|
let font_ctx = self.font_ctx;
|
||||||
|
let screen_size = self.screen_size.unwrap();
|
||||||
|
let doc_url = self.doc_url.clone();
|
||||||
|
|
||||||
|
LayoutContext {
|
||||||
|
image_cache: image_cache,
|
||||||
|
font_ctx: font_ctx,
|
||||||
|
doc_url: doc_url.unwrap(),
|
||||||
|
screen_size: Rect(Point2D(Au(0), Au(0)), screen_size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_request(&mut self) -> bool {
|
fn handle_request(&mut self) -> bool {
|
||||||
match self.from_script.recv() {
|
match self.from_script.recv() {
|
||||||
AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
|
AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
|
||||||
|
@ -147,20 +170,16 @@ impl Layout {
|
||||||
debug!("layout: damage is %?", data.damage);
|
debug!("layout: damage is %?", data.damage);
|
||||||
debug!("layout: parsed Node tree");
|
debug!("layout: parsed Node tree");
|
||||||
debug!("%?", node.dump());
|
debug!("%?", node.dump());
|
||||||
|
|
||||||
// Reset the image cache.
|
// Reset the image cache.
|
||||||
self.local_image_cache.next_round(self.make_on_image_available_cb(script_chan));
|
self.local_image_cache.next_round(self.make_on_image_available_cb(script_chan));
|
||||||
|
|
||||||
|
self.doc_url = Some(doc_url);
|
||||||
let screen_size = Size2D(Au::from_px(data.window_size.width as int),
|
let screen_size = Size2D(Au::from_px(data.window_size.width as int),
|
||||||
Au::from_px(data.window_size.height as int));
|
Au::from_px(data.window_size.height as int));
|
||||||
|
self.screen_size = Some(screen_size);
|
||||||
|
|
||||||
// Create a layout context for use throughout the following passes.
|
// Create a layout context for use throughout the following passes.
|
||||||
let mut layout_ctx = LayoutContext {
|
let mut layout_ctx = self.build_layout_context();
|
||||||
image_cache: self.local_image_cache,
|
|
||||||
font_ctx: self.font_ctx,
|
|
||||||
doc_url: doc_url,
|
|
||||||
screen_size: Rect(Point2D(Au(0), Au(0)), screen_size)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize layout data for each node.
|
// Initialize layout data for each node.
|
||||||
//
|
//
|
||||||
|
@ -290,6 +309,55 @@ impl Layout {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reply_chan.send(response)
|
||||||
|
}
|
||||||
|
HitTestQuery(node, point) => {
|
||||||
|
// FIXME: Isolate this transmutation into a single "bridge" module.
|
||||||
|
let node: AbstractNode<LayoutView> = unsafe {
|
||||||
|
transmute(node)
|
||||||
|
};
|
||||||
|
let mut flow_node: AbstractNode<LayoutView> = node;
|
||||||
|
for node.traverse_preorder |node| {
|
||||||
|
if node.layout_data().flow.is_some() {
|
||||||
|
flow_node = node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = match flow_node.layout_data().flow {
|
||||||
|
None => {
|
||||||
|
debug!("HitTestQuery: flow is None");
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
Some(flow) => {
|
||||||
|
let layout_ctx = self.build_layout_context();
|
||||||
|
let builder = DisplayListBuilder {
|
||||||
|
ctx: &layout_ctx,
|
||||||
|
};
|
||||||
|
let display_list: @Cell<DisplayList<RenderBox>> =
|
||||||
|
@Cell(DisplayList::new());
|
||||||
|
flow.build_display_list(&builder,
|
||||||
|
&flow.position(),
|
||||||
|
display_list);
|
||||||
|
// iterate in reverse to ensure we have the most recently painted render box
|
||||||
|
let (x, y) = (Au::from_frac_px(point.x as float),
|
||||||
|
Au::from_frac_px(point.y as float));
|
||||||
|
let mut resp = Err(());
|
||||||
|
let display_list = &display_list.take().list;
|
||||||
|
for display_list.each_reverse |display_item| {
|
||||||
|
let bounds = display_item.bounds();
|
||||||
|
if x <= bounds.origin.x + bounds.size.width &&
|
||||||
|
bounds.origin.x <= x &&
|
||||||
|
y < bounds.origin.y + bounds.size.height &&
|
||||||
|
bounds.origin.y < y {
|
||||||
|
resp = Ok(HitTestResponse(display_item.base().extra.node()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
reply_chan.send(response)
|
reply_chan.send(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
/// GLUT is a very old and bare-bones toolkit. However, it has good cross-platform support, at
|
/// GLUT is a very old and bare-bones toolkit. However, it has good cross-platform support, at
|
||||||
/// least on desktops. It is designed for testing Servo without the need of a UI.
|
/// least on desktops. It is designed for testing Servo without the need of a UI.
|
||||||
|
|
||||||
use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, ResizeCallback};
|
use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, ClickCallback};
|
||||||
use windowing::{ScrollCallback, WindowMethods};
|
use windowing::{ResizeCallback, ScrollCallback, WindowMethods};
|
||||||
|
|
||||||
use alert::{Alert, AlertMethods};
|
use alert::{Alert, AlertMethods};
|
||||||
use core::libc::c_int;
|
use core::libc::c_int;
|
||||||
|
@ -35,6 +35,7 @@ pub struct Window {
|
||||||
composite_callback: Option<CompositeCallback>,
|
composite_callback: Option<CompositeCallback>,
|
||||||
resize_callback: Option<ResizeCallback>,
|
resize_callback: Option<ResizeCallback>,
|
||||||
load_url_callback: Option<LoadUrlCallback>,
|
load_url_callback: Option<LoadUrlCallback>,
|
||||||
|
click_callback: Option<ClickCallback>,
|
||||||
scroll_callback: Option<ScrollCallback>,
|
scroll_callback: Option<ScrollCallback>,
|
||||||
|
|
||||||
drag_origin: Point2D<c_int>,
|
drag_origin: Point2D<c_int>,
|
||||||
|
@ -54,6 +55,7 @@ impl WindowMethods<Application> for Window {
|
||||||
composite_callback: None,
|
composite_callback: None,
|
||||||
resize_callback: None,
|
resize_callback: None,
|
||||||
load_url_callback: None,
|
load_url_callback: None,
|
||||||
|
click_callback: None,
|
||||||
scroll_callback: None,
|
scroll_callback: None,
|
||||||
|
|
||||||
drag_origin: Point2D(0, 0),
|
drag_origin: Point2D(0, 0),
|
||||||
|
@ -77,6 +79,7 @@ impl WindowMethods<Application> for Window {
|
||||||
window.handle_key(key)
|
window.handle_key(key)
|
||||||
}
|
}
|
||||||
do glut::mouse_func |_, _, x, y| {
|
do glut::mouse_func |_, _, x, y| {
|
||||||
|
window.handle_click(x, y);
|
||||||
window.start_drag(x, y)
|
window.start_drag(x, y)
|
||||||
}
|
}
|
||||||
do glut::motion_func |x, y| {
|
do glut::motion_func |x, y| {
|
||||||
|
@ -111,6 +114,11 @@ impl WindowMethods<Application> for Window {
|
||||||
self.load_url_callback = Some(new_load_url_callback)
|
self.load_url_callback = Some(new_load_url_callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers a callback to be run when a click event occurs.
|
||||||
|
pub fn set_click_callback(&mut self, new_click_callback: ClickCallback) {
|
||||||
|
self.click_callback = Some(new_click_callback)
|
||||||
|
}
|
||||||
|
|
||||||
/// Registers a callback to be run when the user scrolls.
|
/// Registers a callback to be run when the user scrolls.
|
||||||
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback) {
|
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback) {
|
||||||
self.scroll_callback = Some(new_scroll_callback)
|
self.scroll_callback = Some(new_scroll_callback)
|
||||||
|
@ -136,6 +144,14 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function to handle a click
|
||||||
|
fn handle_click(&self, x: c_int, y: c_int) {
|
||||||
|
match self.click_callback {
|
||||||
|
None => {}
|
||||||
|
Some(callback) => callback(Point2D(x as f32, y as f32)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function to start a drag.
|
/// Helper function to start a drag.
|
||||||
fn start_drag(&mut self, x: c_int, y: c_int) {
|
fn start_drag(&mut self, x: c_int, y: c_int) {
|
||||||
self.drag_origin = Point2D(x, y)
|
self.drag_origin = Point2D(x, y)
|
||||||
|
|
|
@ -16,6 +16,10 @@ pub type ResizeCallback = @fn(uint, uint);
|
||||||
/// Type of the function that is called when a new URL is to be loaded.
|
/// Type of the function that is called when a new URL is to be loaded.
|
||||||
pub type LoadUrlCallback = @fn(&str);
|
pub type LoadUrlCallback = @fn(&str);
|
||||||
|
|
||||||
|
/// Type of the function that is called when hit testing is to be performed.
|
||||||
|
/// FIXME this currently does not discriminate between left and right clicks or any modifiers
|
||||||
|
pub type ClickCallback = @fn(Point2D<f32>);
|
||||||
|
|
||||||
/// Type of the function that is called when the user scrolls.
|
/// Type of the function that is called when the user scrolls.
|
||||||
pub type ScrollCallback = @fn(Point2D<f32>);
|
pub type ScrollCallback = @fn(Point2D<f32>);
|
||||||
|
|
||||||
|
@ -38,6 +42,8 @@ pub trait WindowMethods<A> {
|
||||||
pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback);
|
pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback);
|
||||||
/// Registers a callback to run when a new URL is to be loaded.
|
/// Registers a callback to run when a new URL is to be loaded.
|
||||||
pub fn set_load_url_callback(&mut self, new_load_url_callback: LoadUrlCallback);
|
pub fn set_load_url_callback(&mut self, new_load_url_callback: LoadUrlCallback);
|
||||||
|
/// Registers a callback to run when the user clicks.
|
||||||
|
pub fn set_click_callback(&mut self, new_click_callback: ClickCallback);
|
||||||
/// Registers a callback to run when the user scrolls.
|
/// Registers a callback to run when the user scrolls.
|
||||||
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback);
|
pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback);
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@ use dom::window::Window;
|
||||||
use dom::bindings::codegen::EventBinding;
|
use dom::bindings::codegen::EventBinding;
|
||||||
use dom::bindings::utils::{DOMString, ErrorResult, WrapperCache};
|
use dom::bindings::utils::{DOMString, ErrorResult, WrapperCache};
|
||||||
|
|
||||||
|
use geom::point::Point2D;
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
ResizeEvent(uint, uint, comm::Chan<()>),
|
ResizeEvent(uint, uint, comm::Chan<()>),
|
||||||
ReflowEvent
|
ReflowEvent,
|
||||||
|
ClickEvent(Point2D<f32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Event_ {
|
pub struct Event_ {
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
/// coupling between these two components, and enables the DOM to be placed in a separate crate
|
/// coupling between these two components, and enables the DOM to be placed in a separate crate
|
||||||
/// from layout.
|
/// from layout.
|
||||||
|
|
||||||
use dom::node::{AbstractNode, ScriptView};
|
use dom::node::{AbstractNode, ScriptView, LayoutView};
|
||||||
use script_task::ScriptMsg;
|
use script_task::ScriptMsg;
|
||||||
|
|
||||||
use core::comm::{Chan, SharedChan};
|
use core::comm::{Chan, SharedChan};
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
use geom::point::Point2D;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
@ -43,6 +44,8 @@ pub enum LayoutQuery {
|
||||||
ContentBoxQuery(AbstractNode<ScriptView>),
|
ContentBoxQuery(AbstractNode<ScriptView>),
|
||||||
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
|
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
|
||||||
ContentBoxesQuery(AbstractNode<ScriptView>),
|
ContentBoxesQuery(AbstractNode<ScriptView>),
|
||||||
|
/// Requests the node containing the point of interest
|
||||||
|
HitTestQuery(AbstractNode<ScriptView>, Point2D<f32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The reply of a synchronous message from script to layout.
|
/// The reply of a synchronous message from script to layout.
|
||||||
|
@ -54,6 +57,8 @@ pub enum LayoutResponse {
|
||||||
ContentBoxResponse(Rect<Au>),
|
ContentBoxResponse(Rect<Au>),
|
||||||
/// A response to the `ContentBoxesQuery` message.
|
/// A response to the `ContentBoxesQuery` message.
|
||||||
ContentBoxesResponse(~[Rect<Au>]),
|
ContentBoxesResponse(~[Rect<Au>]),
|
||||||
|
/// A response to the `HitTestQuery` message.
|
||||||
|
HitTestResponse(AbstractNode<LayoutView>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dirty bits for layout.
|
/// Dirty bits for layout.
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
use dom::bindings::utils::GlobalStaticData;
|
use dom::bindings::utils::GlobalStaticData;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::event::{Event, ResizeEvent, ReflowEvent};
|
use dom::event::{Event, ResizeEvent, ReflowEvent, ClickEvent};
|
||||||
use dom::node::define_bindings;
|
use dom::node::define_bindings;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, Damage, LayoutQuery};
|
use layout_interface::{AddStylesheetMsg, BuildData, BuildMsg, Damage, LayoutQuery, HitTestQuery};
|
||||||
use layout_interface::{LayoutResponse, LayoutTask, MatchSelectorsDamage, NoDamage};
|
use layout_interface::{LayoutResponse, HitTestResponse, LayoutTask, MatchSelectorsDamage, NoDamage};
|
||||||
use layout_interface::{QueryMsg, ReflowDamage};
|
use layout_interface::{QueryMsg, ReflowDamage};
|
||||||
use layout_interface;
|
use layout_interface;
|
||||||
|
|
||||||
|
@ -460,6 +460,23 @@ impl ScriptContext {
|
||||||
self.relayout()
|
self.relayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClickEvent(point) => {
|
||||||
|
debug!("ClickEvent: clicked at %?", point);
|
||||||
|
let root = match self.root_frame {
|
||||||
|
Some(ref frame) => frame.document.root,
|
||||||
|
None => fail!("root frame is None")
|
||||||
|
};
|
||||||
|
match self.query_layout(HitTestQuery(root, point)) {
|
||||||
|
Ok(node) => match node {
|
||||||
|
HitTestResponse(node) => debug!("clicked on %?", node.debug_str()),
|
||||||
|
_ => fail!(~"unexpected layout reply")
|
||||||
|
},
|
||||||
|
Err(()) => {
|
||||||
|
println(fmt!("layout query error"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue