aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/compositing/constellation.rs13
-rw-r--r--components/msg/constellation_msg.rs5
-rw-r--r--components/script/dom/document.rs38
-rw-r--r--components/script/dom/htmliframeelement.rs5
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()
}