diff options
-rw-r--r-- | components/compositing/constellation.rs | 13 | ||||
-rw-r--r-- | components/msg/constellation_msg.rs | 5 | ||||
-rw-r--r-- | components/script/dom/document.rs | 38 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 5 |
4 files changed, 57 insertions, 4 deletions
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 22a22d459e7..34d20d42c0d 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -613,6 +613,19 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { debug!("constellation got focus message"); self.handle_focus_msg(pipeline_id); } + Request::Script(FromScriptMsg::ForwardMouseButtonEvent( + pipeline_id, event_type, button, point)) => { + if let Some(pipeline) = self.pipelines.get(&pipeline_id) { + pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline_id, + CompositorEvent::MouseButtonEvent(event_type, button, point))); + } + } + Request::Script(FromScriptMsg::ForwardMouseMoveEvent(pipeline_id, point)) => { + if let Some(pipeline) = self.pipelines.get(&pipeline_id) { + pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline_id, + CompositorEvent::MouseMoveEvent(Some(point)))); + } + } Request::Script(FromScriptMsg::GetClipboardContents(sender)) => { let result = self.clipboard_ctx.as_ref().map_or( "".to_owned(), diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 8d3652f82ed..d7ff06de6a4 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -7,6 +7,7 @@ use canvas_traits::CanvasMsg; use compositor_msg::Epoch; +use euclid::point::Point2D; use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; use hyper::header::Headers; @@ -283,6 +284,10 @@ pub enum ScriptMsg { Failure(Failure), /// Notifies the constellation that this frame has received focus. Focus(PipelineId), + /// Re-send a mouse button event that was sent to the parent window. + ForwardMouseButtonEvent(PipelineId, MouseEventType, MouseButton, Point2D<f32>), + /// Re-send a mouse move event that was sent to the parent window. + ForwardMouseMoveEvent(PipelineId, Point2D<f32>), /// Requests that the constellation retrieve the current contents of the clipboard GetClipboardContents(IpcSender<String>), /// <head> tag finished parsing diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 0887cd8b1e3..0e790188320 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -5,12 +5,15 @@ use document_loader::{DocumentLoader, LoadType}; use dom::attr::{Attr, AttrValue}; use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods; use dom::bindings::codegen::Bindings::DocumentBinding; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState}; +use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; +use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter; use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods; @@ -604,7 +607,7 @@ impl Document { pub fn handle_mouse_event(&self, js_runtime: *mut JSRuntime, - _button: MouseButton, + button: MouseButton, client_point: Point2D<f32>, mouse_event_type: MouseEventType) { let mouse_event_type_string = match mouse_event_type { @@ -635,6 +638,21 @@ impl Document { }, }; + // If the target is an iframe, forward the event to the child document. + if let Some(iframe) = el.downcast::<HTMLIFrameElement>() { + if let Some(pipeline_id) = iframe.pipeline_id() { + let rect = iframe.upcast::<Element>().GetBoundingClientRect(); + let child_origin = Point2D::new(rect.X() as f32, rect.Y() as f32); + let child_point = client_point - child_origin; + + let event = ConstellationMsg::ForwardMouseButtonEvent(pipeline_id, + mouse_event_type, + button, child_point); + self.window.constellation_chan().0.send(event).unwrap(); + } + return; + } + let node = el.upcast::<Node>(); debug!("{} on {:?}", mouse_event_type_string, node.debug_str()); // Prevent click event if form control element is disabled. @@ -767,11 +785,23 @@ impl Document { if mouse_over_addresses.len() > 0 { let top_most_node = node::from_untrusted_node_address(js_runtime, mouse_over_addresses[0]); + let client_point = client_point.unwrap(); // Must succeed because hit test succeeded. - let target = top_most_node.upcast(); - if let Some(client_point) = client_point { - self.fire_mouse_event(client_point, target, "mousemove".to_owned()); + // If the target is an iframe, forward the event to the child document. + if let Some(iframe) = top_most_node.downcast::<HTMLIFrameElement>() { + if let Some(pipeline_id) = iframe.pipeline_id() { + let rect = iframe.upcast::<Element>().GetBoundingClientRect(); + let child_origin = Point2D::new(rect.X() as f32, rect.Y() as f32); + let child_point = client_point - child_origin; + + let event = ConstellationMsg::ForwardMouseMoveEvent(pipeline_id, child_point); + self.window.constellation_chan().0.send(event).unwrap(); + } + return; } + + let target = top_most_node.upcast(); + self.fire_mouse_event(client_point, target, "mousemove".to_owned()); } // Store the current mouse over targets for next frame diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 78400b6d49a..fe07d28a198 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -186,6 +186,11 @@ impl HTMLIFrameElement { } #[inline] + pub fn pipeline_id(&self) -> Option<PipelineId> { + self.pipeline_id.get() + } + + #[inline] pub fn subpage_id(&self) -> Option<SubpageId> { self.subpage_id.get() } |