From c30ed37c65d7713e82c321c7384e7c380f625344 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Thu, 12 May 2016 09:00:14 -0700 Subject: [PATCH] servo: Merge #10714 - Implement user interaction task source (from KiChjang:user-interaction-task); r=Ms2ger Part of #7959. Source-Repo: https://github.com/servo/servo Source-Revision: 42141870e764d0763bfbbdbed70b74399ee342de --- .../components/script/dom/bindings/global.rs | 9 ---- .../script/dom/htmldetailselement.rs | 8 +-- .../components/script/dom/htmlinputelement.rs | 47 +++++------------ .../script/dom/htmltextareaelement.rs | 19 +++++-- servo/components/script/dom/window.rs | 2 +- servo/components/script/script_thread.rs | 10 ++-- .../script/task_source/dom_manipulation.rs | 6 ++- servo/components/script/task_source/mod.rs | 1 - .../script/task_source/user_interaction.rs | 52 ++++++++++++++++--- 9 files changed, 88 insertions(+), 66 deletions(-) diff --git a/servo/components/script/dom/bindings/global.rs b/servo/components/script/dom/bindings/global.rs index 17a2688a9100..7dea10fd0a0e 100644 --- a/servo/components/script/dom/bindings/global.rs +++ b/servo/components/script/dom/bindings/global.rs @@ -173,15 +173,6 @@ impl<'a> GlobalRef<'a> { } } - /// `ScriptChan` used to send messages to the event loop of this global's - /// thread. - pub fn user_interaction_task_source(&self) -> Box { - match *self { - GlobalRef::Window(ref window) => window.user_interaction_task_source(), - GlobalRef::Worker(ref worker) => worker.script_chan(), - } - } - /// `ScriptChan` used to send messages to the event loop of this global's /// thread. pub fn networking_task_source(&self) -> Box { diff --git a/servo/components/script/dom/htmldetailselement.rs b/servo/components/script/dom/htmldetailselement.rs index 3f00e53220ca..724c9cff6143 100644 --- a/servo/components/script/dom/htmldetailselement.rs +++ b/servo/components/script/dom/htmldetailselement.rs @@ -74,7 +74,7 @@ impl VirtualMethods for HTMLDetailsElement { let window = window.r(); let task_source = window.dom_manipulation_task_source(); let details = Trusted::new(self); - let runnable = box ToggleEventRunnable { + let runnable = box DetailsNotificationRunnable { element: details, toggle_number: counter }; @@ -83,13 +83,13 @@ impl VirtualMethods for HTMLDetailsElement { } } -pub struct ToggleEventRunnable { +pub struct DetailsNotificationRunnable { element: Trusted, toggle_number: u32 } -impl Runnable for ToggleEventRunnable { - fn handler(self: Box) { +impl Runnable for DetailsNotificationRunnable { + fn handler(self: Box) { let target = self.element.root(); if target.check_toggle_count(self.toggle_number) { target.upcast::().fire_simple_event("toggle"); diff --git a/servo/components/script/dom/htmlinputelement.rs b/servo/components/script/dom/htmlinputelement.rs index 0e675b35b27d..a226a2e224cc 100644 --- a/servo/components/script/dom/htmlinputelement.rs +++ b/servo/components/script/dom/htmlinputelement.rs @@ -12,10 +12,8 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; use dom::bindings::error::{Error, ErrorResult}; -use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, LayoutJS, Root, RootedReference}; -use dom::bindings::refcounted::Trusted; use dom::document::Document; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers, LayoutElementHelpers}; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -31,9 +29,7 @@ use dom::nodelist::NodeList; use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; -use script_runtime::CommonScriptMsg; -use script_runtime::ScriptThreadEventCategory::InputEvent; -use script_thread::Runnable; +use script_runtime::ScriptChan; use script_traits::ScriptMsg as ConstellationMsg; use std::borrow::ToOwned; use std::cell::Cell; @@ -549,6 +545,12 @@ impl HTMLInputElementMethods for HTMLInputElement { let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); self.textinput.borrow_mut().selection_direction = direction; self.textinput.borrow_mut().set_selection_range(start, end); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); self.upcast::().dirty(NodeDamage::OtherNodeDamage); } } @@ -919,7 +921,12 @@ impl VirtualMethods for HTMLInputElement { self.value_changed.set(true); if event.IsTrusted() { - ChangeEventRunnable::send(self.upcast::()); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("input"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); } self.upcast::().dirty(NodeDamage::OtherNodeDamage); @@ -1148,31 +1155,3 @@ impl Activatable for HTMLInputElement { } } } - -pub struct ChangeEventRunnable { - element: Trusted, -} - -impl ChangeEventRunnable { - pub fn send(node: &Node) { - let handler = Trusted::new(node); - let dispatcher = ChangeEventRunnable { - element: handler, - }; - let chan = window_from_node(node).user_interaction_task_source(); - let _ = chan.send(CommonScriptMsg::RunnableMsg(InputEvent, box dispatcher)); - } -} - -impl Runnable for ChangeEventRunnable { - fn handler(self: Box) { - let target = self.element.root(); - let window = window_from_node(target.r()); - let window = window.r(); - let event = Event::new(GlobalRef::Window(window), - atom!("input"), - EventBubbles::Bubbles, - EventCancelable::NotCancelable); - target.upcast::().dispatch_event(&event); - } -} diff --git a/servo/components/script/dom/htmltextareaelement.rs b/servo/components/script/dom/htmltextareaelement.rs index 597c9a2bb60e..122d73e85536 100644 --- a/servo/components/script/dom/htmltextareaelement.rs +++ b/servo/components/script/dom/htmltextareaelement.rs @@ -14,18 +14,18 @@ use dom::bindings::reflector::{Reflectable}; use dom::document::Document; use dom::element::RawLayoutElementHelpers; use dom::element::{AttributeMutation, Element}; -use dom::event::{Event}; +use dom::event::{Event, EventBubbles, EventCancelable}; use dom::htmlelement::HTMLElement; use dom::htmlfieldsetelement::HTMLFieldSetElement; use dom::htmlformelement::{FormControl, HTMLFormElement}; -use dom::htmlinputelement::ChangeEventRunnable; use dom::keyboardevent::KeyboardEvent; use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext}; -use dom::node::{document_from_node}; +use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; +use script_runtime::ScriptChan; use script_traits::ScriptMsg as ConstellationMsg; use std::cell::Cell; use std::ops::Range; @@ -256,6 +256,12 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); self.textinput.borrow_mut().selection_direction = direction; self.textinput.borrow_mut().set_selection_range(start, end); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("select"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); self.upcast::().dirty(NodeDamage::OtherNodeDamage); } } @@ -373,7 +379,12 @@ impl VirtualMethods for HTMLTextAreaElement { self.value_changed.set(true); if event.IsTrusted() { - ChangeEventRunnable::send(self.upcast::()); + let window = window_from_node(self); + let _ = window.user_interaction_task_source().queue_event( + &self.upcast(), + atom!("input"), + EventBubbles::Bubbles, + EventCancelable::NotCancelable); } self.upcast::().dirty(NodeDamage::OtherNodeDamage); diff --git a/servo/components/script/dom/window.rs b/servo/components/script/dom/window.rs index cb8f0c596392..9f993c254615 100644 --- a/servo/components/script/dom/window.rs +++ b/servo/components/script/dom/window.rs @@ -275,7 +275,7 @@ impl Window { self.dom_manipulation_task_source.clone() } - pub fn user_interaction_task_source(&self) -> Box { + pub fn user_interaction_task_source(&self) -> UserInteractionTaskSource { self.user_interaction_task_source.clone() } diff --git a/servo/components/script/script_thread.rs b/servo/components/script/script_thread.rs index 9bd7ce26c4f7..02f8d9a83ea5 100644 --- a/servo/components/script/script_thread.rs +++ b/servo/components/script/script_thread.rs @@ -99,7 +99,7 @@ use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTa use task_source::file_reading::FileReadingTaskSource; use task_source::history_traversal::HistoryTraversalTaskSource; use task_source::networking::NetworkingTaskSource; -use task_source::user_interaction::UserInteractionTaskSource; +use task_source::user_interaction::{UserInteractionTaskSource, UserInteractionTask}; use time::Tm; use url::{Url, Position}; use util::opts; @@ -222,6 +222,8 @@ pub enum MainThreadScriptMsg { Navigate(PipelineId, LoadData), /// Tasks that originate from the DOM manipulation task source DOMManipulation(DOMManipulationTask), + /// Tasks that originate from the user interaction task source + UserInteraction(UserInteractionTask), } impl OpaqueSender for Box { @@ -928,8 +930,10 @@ impl ScriptThread { LiveDOMReferences::cleanup(addr), MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => self.collect_reports(reports_chan), - MainThreadScriptMsg::DOMManipulation(msg) => - msg.handle_msg(self), + MainThreadScriptMsg::DOMManipulation(task) => + task.handle_task(self), + MainThreadScriptMsg::UserInteraction(task) => + task.handle_task(), } } diff --git a/servo/components/script/task_source/dom_manipulation.rs b/servo/components/script/task_source/dom_manipulation.rs index 5993825a1be0..05b0722f8892 100644 --- a/servo/components/script/task_source/dom_manipulation.rs +++ b/servo/components/script/task_source/dom_manipulation.rs @@ -18,8 +18,10 @@ impl TaskSource for DOMManipulationTaskSource { fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> { self.0.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ()) } +} - fn clone(&self) -> Box + Send> { +impl DOMManipulationTaskSource { + pub fn clone(&self) -> Box + Send> { box DOMManipulationTaskSource((&self.0).clone()) } } @@ -42,7 +44,7 @@ pub enum DOMManipulationTask { } impl DOMManipulationTask { - pub fn handle_msg(self, script_thread: &ScriptThread) { + pub fn handle_task(self, script_thread: &ScriptThread) { use self::DOMManipulationTask::*; match self { diff --git a/servo/components/script/task_source/mod.rs b/servo/components/script/task_source/mod.rs index 74dd7347e9e9..fe2d159b04a2 100644 --- a/servo/components/script/task_source/mod.rs +++ b/servo/components/script/task_source/mod.rs @@ -12,5 +12,4 @@ use std::result::Result; pub trait TaskSource { fn queue(&self, msg: T) -> Result<(), ()>; - fn clone(&self) -> Box + Send>; } diff --git a/servo/components/script/task_source/user_interaction.rs b/servo/components/script/task_source/user_interaction.rs index 8f79b8ddaed3..59d7d728185b 100644 --- a/servo/components/script/task_source/user_interaction.rs +++ b/servo/components/script/task_source/user_interaction.rs @@ -2,19 +2,55 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use script_runtime::{CommonScriptMsg, ScriptChan}; +use dom::bindings::refcounted::Trusted; +use dom::event::{EventBubbles, EventCancelable}; +use dom::eventtarget::EventTarget; +use script_runtime::ScriptChan; use script_thread::MainThreadScriptMsg; +use std::result::Result; use std::sync::mpsc::Sender; +use string_cache::Atom; +use task_source::TaskSource; #[derive(JSTraceable)] pub struct UserInteractionTaskSource(pub Sender); -impl ScriptChan for UserInteractionTaskSource { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) - } - - fn clone(&self) -> Box { - box UserInteractionTaskSource((&self.0).clone()) +impl TaskSource for UserInteractionTaskSource { + fn queue(&self, msg: UserInteractionTask) -> Result<(), ()> { + self.0.send(MainThreadScriptMsg::UserInteraction(msg)).map_err(|_| ()) + } +} + +impl UserInteractionTaskSource { + pub fn queue_event(&self, + target: &EventTarget, + name: Atom, + bubbles: EventBubbles, + cancelable: EventCancelable) { + let target = Trusted::new(target); + let _ = self.0.send(MainThreadScriptMsg::UserInteraction(UserInteractionTask::FireEvent( + target, name, bubbles, cancelable))); + } + + pub fn clone(&self) -> UserInteractionTaskSource { + UserInteractionTaskSource((&self.0).clone()) + } +} + +pub enum UserInteractionTask { + // https://dom.spec.whatwg.org/#concept-event-fire + FireEvent(Trusted, Atom, EventBubbles, EventCancelable), +} + +impl UserInteractionTask { + pub fn handle_task(self) { + use self::UserInteractionTask::*; + + match self { + FireEvent(element, name, bubbles, cancelable) => { + let target = element.root(); + target.fire_event(&*name, bubbles, cancelable); + } + } } }