aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml2
-rw-r--r--components/script/dom/bindings/str.rs11
-rw-r--r--components/script/dom/bindings/trace.rs2
-rw-r--r--components/script/dom/document.rs9
-rw-r--r--components/script/dom/element.rs53
-rw-r--r--components/script/dom/htmlimageelement.rs104
-rw-r--r--components/script/dom/keyboardevent.rs42
-rw-r--r--components/script/dom/webidls/CSSStyleDeclaration.webidl3
-rw-r--r--components/script/layout_wrapper.rs90
-rw-r--r--components/script/script_thread.rs4
-rw-r--r--components/script/task_source/dom_manipulation.rs6
-rw-r--r--components/script/textinput.rs68
12 files changed, 226 insertions, 168 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index d9bdeac843b..fa2d75c633d 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -57,7 +57,7 @@ regex = "0.1.43"
rustc-serialize = "0.3"
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
-selectors = {version = "0.6", features = ["heap_size"]}
+selectors = {version = "0.7", features = ["heap_size"]}
serde = "0.7.11"
smallvec = "0.1"
string_cache = {version = "0.2.20", features = ["heap_size", "unstable"]}
diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs
index 69565520899..310285a8bcd 100644
--- a/components/script/dom/bindings/str.rs
+++ b/components/script/dom/bindings/str.rs
@@ -5,7 +5,7 @@
//! The `ByteString` struct.
use std::ascii::AsciiExt;
-use std::borrow::ToOwned;
+use std::borrow::{ToOwned, Cow};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops;
@@ -204,6 +204,15 @@ impl<'a> From<&'a str> for DOMString {
}
}
+impl<'a> From<Cow<'a, str>> for DOMString {
+ fn from(contents: Cow<'a, str>) -> DOMString {
+ match contents {
+ Cow::Owned(s) => DOMString::from(s),
+ Cow::Borrowed(s) => DOMString::from(s),
+ }
+ }
+}
+
impl From<DOMString> for Atom {
fn from(contents: DOMString) -> Atom {
Atom::from(contents.0)
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 7404e96b95d..e2c6e540a3d 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -276,7 +276,7 @@ impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, B, C) {
}
}
-no_jsmanaged_fields!(bool, f32, f64, String, Url, AtomicBool, AtomicUsize, UrlOrigin, Uuid);
+no_jsmanaged_fields!(bool, f32, f64, String, Url, AtomicBool, AtomicUsize, UrlOrigin, Uuid, char);
no_jsmanaged_fields!(usize, u8, u16, u32, u64);
no_jsmanaged_fields!(isize, i8, i16, i32, i64);
no_jsmanaged_fields!(Sender<T>);
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 2160a3a4556..43a4473689e 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -1044,6 +1044,7 @@ impl Document {
/// The entry point for all key processing for web content
pub fn dispatch_key_event(&self,
+ ch: Option<char>,
key: Key,
state: KeyState,
modifiers: KeyModifiers,
@@ -1070,7 +1071,7 @@ impl Document {
}
.to_owned());
- let props = KeyboardEvent::key_properties(key, modifiers);
+ let props = KeyboardEvent::key_properties(ch, key, modifiers);
let keyevent = KeyboardEvent::new(&self.window,
ev_type,
@@ -1078,8 +1079,9 @@ impl Document {
true,
Some(&self.window),
0,
+ ch,
Some(key),
- DOMString::from(props.key_string),
+ DOMString::from(props.key_string.clone()),
DOMString::from(props.code),
props.location,
is_repeating,
@@ -1103,6 +1105,7 @@ impl Document {
true,
Some(&self.window),
0,
+ ch,
Some(key),
DOMString::from(props.key_string),
DOMString::from(props.code),
@@ -1122,7 +1125,7 @@ impl Document {
}
if !prevented {
- constellation.send(ConstellationMsg::SendKeyEvent(key, state, modifiers)).unwrap();
+ constellation.send(ConstellationMsg::SendKeyEvent(ch, key, state, modifiers)).unwrap();
}
// This behavior is unspecced
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index d9535663d46..e53f7dbb77b 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -2217,6 +2217,34 @@ impl VirtualMethods for Element {
}
}
+impl<'a> ::selectors::MatchAttrGeneric for Root<Element> {
+ fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
+ where F: Fn(&str) -> bool
+ {
+ use ::selectors::Element;
+ let local_name = {
+ if self.is_html_element_in_html_document() {
+ &attr.lower_name
+ } else {
+ &attr.name
+ }
+ };
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attribute(ns, local_name)
+ .map_or(false, |attr| {
+ test(&attr.value())
+ })
+ },
+ NamespaceConstraint::Any => {
+ self.attrs.borrow().iter().any(|attr| {
+ attr.local_name() == local_name && test(&attr.value())
+ })
+ }
+ }
+ }
+}
+
impl<'a> ::selectors::Element for Root<Element> {
type Impl = ServoSelectorImpl;
@@ -2317,31 +2345,6 @@ impl<'a> ::selectors::Element for Root<Element> {
}
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
- where F: Fn(&str) -> bool
- {
- let local_name = {
- if self.is_html_element_in_html_document() {
- &attr.lower_name
- } else {
- &attr.name
- }
- };
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attribute(ns, local_name)
- .map_or(false, |attr| {
- test(&attr.value())
- })
- },
- NamespaceConstraint::Any => {
- self.attrs.borrow().iter().any(|attr| {
- attr.local_name() == local_name && test(&attr.value())
- })
- }
- }
- }
-
fn is_html_element_in_html_document(&self) -> bool {
self.html_element_in_html_document()
}
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 06a5bf93abf..2b61a800a1a 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -31,6 +31,8 @@ use script_thread::Runnable;
use std::sync::Arc;
use string_cache::Atom;
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
+use task_source::TaskSource;
+use task_source::dom_manipulation::DOMManipulationTask;
use url::Url;
#[derive(JSTraceable, HeapSizeOf)]
@@ -44,7 +46,8 @@ enum State {
#[derive(JSTraceable, HeapSizeOf)]
struct ImageRequest {
state: State,
- url: Option<Url>,
+ parsed_url: Option<Url>,
+ source_url: Option<DOMString>,
image: Option<Arc<Image>>,
metadata: Option<ImageMetadata>,
}
@@ -56,8 +59,8 @@ pub struct HTMLImageElement {
}
impl HTMLImageElement {
- pub fn get_url(&self) -> Option<Url>{
- self.current_request.borrow().url.clone()
+ pub fn get_url(&self) -> Option<Url> {
+ self.current_request.borrow().parsed_url.clone()
}
}
@@ -118,33 +121,70 @@ impl HTMLImageElement {
let image_cache = window.image_cache_thread();
match value {
None => {
- self.current_request.borrow_mut().url = None;
+ self.current_request.borrow_mut().parsed_url = None;
+ self.current_request.borrow_mut().source_url = None;
self.current_request.borrow_mut().image = None;
}
Some((src, base_url)) => {
let img_url = base_url.join(&src);
- // FIXME: handle URL parse errors more gracefully.
- let img_url = img_url.unwrap();
- self.current_request.borrow_mut().url = Some(img_url.clone());
-
- let trusted_node = Trusted::new(self);
- let (responder_sender, responder_receiver) = ipc::channel().unwrap();
- let script_chan = window.networking_task_source();
- let wrapper = window.get_runnable_wrapper();
- ROUTER.add_route(responder_receiver.to_opaque(), box move |message| {
- // Return the image via a message to the script thread, which marks the element
- // as dirty and triggers a reflow.
- let image_response = message.to().unwrap();
- let runnable = ImageResponseHandlerRunnable::new(
- trusted_node.clone(), image_response);
- let runnable = wrapper.wrap_runnable(runnable);
- let _ = script_chan.send(CommonScriptMsg::RunnableMsg(
- UpdateReplacedElement, runnable));
- });
-
- image_cache.request_image_and_metadata(img_url,
- window.image_cache_chan(),
- Some(ImageResponder::new(responder_sender)));
+ if let Ok(img_url) = img_url {
+ self.current_request.borrow_mut().parsed_url = Some(img_url.clone());
+ self.current_request.borrow_mut().source_url = Some(src);
+
+ let trusted_node = Trusted::new(self);
+ let (responder_sender, responder_receiver) = ipc::channel().unwrap();
+ let script_chan = window.networking_task_source();
+ let wrapper = window.get_runnable_wrapper();
+ ROUTER.add_route(responder_receiver.to_opaque(), box move |message| {
+ // Return the image via a message to the script thread, which marks the element
+ // as dirty and triggers a reflow.
+ let image_response = message.to().unwrap();
+ let runnable = ImageResponseHandlerRunnable::new(
+ trusted_node.clone(), image_response);
+ let runnable = wrapper.wrap_runnable(runnable);
+ let _ = script_chan.send(CommonScriptMsg::RunnableMsg(
+ UpdateReplacedElement, runnable));
+ });
+
+ image_cache.request_image_and_metadata(img_url,
+ window.image_cache_chan(),
+ Some(ImageResponder::new(responder_sender)));
+ } else {
+ // https://html.spec.whatwg.org/multipage/#update-the-image-data
+ // Step 11 (error substeps)
+ debug!("Failed to parse URL {} with base {}", src, base_url);
+ let mut req = self.current_request.borrow_mut();
+
+ // Substeps 1,2
+ req.image = None;
+ req.parsed_url = None;
+ req.state = State::Broken;
+ // todo: set pending request to null
+ // (pending requests aren't being used yet)
+
+
+ struct ImgParseErrorRunnable {
+ img: Trusted<HTMLImageElement>,
+ src: String,
+ }
+ impl Runnable for ImgParseErrorRunnable {
+ fn handler(self: Box<Self>) {
+ // https://html.spec.whatwg.org/multipage/#update-the-image-data
+ // Step 11, substep 5
+ let img = self.img.root();
+ img.current_request.borrow_mut().source_url = Some(self.src.into());
+ img.upcast::<EventTarget>().fire_simple_event("error");
+ img.upcast::<EventTarget>().fire_simple_event("loadend");
+ }
+ }
+
+ let runnable = Box::new(ImgParseErrorRunnable {
+ img: Trusted::new(self),
+ src: src.into(),
+ });
+ let task = window.dom_manipulation_task_source();
+ let _ = task.queue(DOMManipulationTask::Miscellaneous(runnable));
+ }
}
}
}
@@ -153,13 +193,15 @@ impl HTMLImageElement {
htmlelement: HTMLElement::new_inherited(localName, prefix, document),
current_request: DOMRefCell::new(ImageRequest {
state: State::Unavailable,
- url: None,
+ parsed_url: None,
+ source_url: None,
image: None,
metadata: None
}),
pending_request: DOMRefCell::new(ImageRequest {
state: State::Unavailable,
- url: None,
+ parsed_url: None,
+ source_url: None,
image: None,
metadata: None
}),
@@ -209,7 +251,7 @@ impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
#[allow(unsafe_code)]
unsafe fn image_url(&self) -> Option<Url> {
- (*self.unsafe_get()).current_request.borrow_for_layout().url.clone()
+ (*self.unsafe_get()).current_request.borrow_for_layout().parsed_url.clone()
}
#[allow(unsafe_code)]
@@ -313,9 +355,9 @@ impl HTMLImageElementMethods for HTMLImageElement {
// https://html.spec.whatwg.org/multipage/#dom-img-currentsrc
fn CurrentSrc(&self) -> DOMString {
- let ref url = self.current_request.borrow().url;
+ let ref url = self.current_request.borrow().source_url;
match *url {
- Some(ref url) => DOMString::from(url.as_str()),
+ Some(ref url) => url.clone(),
None => DOMString::from(""),
}
}
diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs
index 4cfa1a61011..71b00767a8e 100644
--- a/components/script/dom/keyboardevent.rs
+++ b/components/script/dom/keyboardevent.rs
@@ -17,6 +17,7 @@ use dom::uievent::UIEvent;
use dom::window::Window;
use msg::constellation_msg;
use msg::constellation_msg::{Key, KeyModifiers};
+use std::borrow::Cow;
use std::cell::Cell;
no_jsmanaged_fields!(Key);
@@ -36,6 +37,7 @@ pub struct KeyboardEvent {
is_composing: Cell<bool>,
char_code: Cell<Option<u32>>,
key_code: Cell<u32>,
+ printable: Cell<Option<char>>,
}
impl KeyboardEvent {
@@ -54,6 +56,7 @@ impl KeyboardEvent {
is_composing: Cell::new(false),
char_code: Cell::new(None),
key_code: Cell::new(0),
+ printable: Cell::new(None),
}
}
@@ -69,6 +72,7 @@ impl KeyboardEvent {
cancelable: bool,
view: Option<&Window>,
_detail: i32,
+ ch: Option<char>,
key: Option<Key>,
key_string: DOMString,
code: DOMString,
@@ -91,6 +95,7 @@ impl KeyboardEvent {
ev.shift.set(shiftKey);
ev.meta.set(metaKey);
ev.char_code.set(char_code);
+ ev.printable.set(ch);
ev.key_code.set(key_code);
ev.is_composing.set(isComposing);
ev
@@ -103,7 +108,9 @@ impl KeyboardEvent {
init.parent.parent.parent.bubbles,
init.parent.parent.parent.cancelable,
init.parent.parent.view.r(),
- init.parent.parent.detail, key_from_string(&init.key, init.location),
+ init.parent.parent.detail,
+ None,
+ key_from_string(&init.key, init.location),
init.key.clone(), init.code.clone(), init.location,
init.repeat, init.isComposing, init.parent.ctrlKey,
init.parent.altKey, init.parent.shiftKey, init.parent.metaKey,
@@ -111,13 +118,13 @@ impl KeyboardEvent {
Ok(event)
}
- pub fn key_properties(key: Key, mods: KeyModifiers)
+ pub fn key_properties(ch: Option<char>, key: Key, mods: KeyModifiers)
-> KeyEventProperties {
KeyEventProperties {
- key_string: key_value(key, mods),
+ key_string: key_value(ch, key, mods),
code: code_value(key),
location: key_location(key),
- char_code: key_charcode(key, mods),
+ char_code: ch.map(|ch| ch as u32),
key_code: key_keycode(key),
}
}
@@ -125,6 +132,10 @@ impl KeyboardEvent {
impl KeyboardEvent {
+ pub fn printable(&self) -> Option<char> {
+ self.printable.get()
+ }
+
pub fn get_key(&self) -> Option<Key> {
self.key.get().clone()
}
@@ -147,11 +158,14 @@ impl KeyboardEvent {
}
}
-
// https://w3c.github.io/uievents-key/#key-value-tables
-pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str {
+pub fn key_value(ch: Option<char>, key: Key, mods: KeyModifiers) -> Cow<'static, str> {
+ if let Some(ch) = ch {
+ return Cow::from(format!("{}", ch));
+ }
+
let shift = mods.contains(constellation_msg::SHIFT);
- match key {
+ Cow::from(match key {
Key::Space => " ",
Key::Apostrophe if shift => "\"",
Key::Apostrophe => "'",
@@ -321,7 +335,7 @@ pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str {
Key::Menu => "ContextMenu",
Key::NavigateForward => "BrowserForward",
Key::NavigateBackward => "BrowserBack",
- }
+ })
}
fn key_from_string(key_string: &str, location: u32) -> Option<Key> {
@@ -647,16 +661,6 @@ fn key_location(key: Key) -> u32 {
}
}
-// https://w3c.github.io/uievents/#dom-keyboardevent-charcode
-fn key_charcode(key: Key, mods: KeyModifiers) -> Option<u32> {
- let key_string = key_value(key, mods);
- if key_string.len() == 1 {
- Some(key_string.chars().next().unwrap() as u32)
- } else {
- None
- }
-}
-
// https://w3c.github.io/uievents/#legacy-key-models
fn key_keycode(key: Key) -> u32 {
match key {
@@ -739,7 +743,7 @@ fn key_keycode(key: Key) -> u32 {
#[derive(HeapSizeOf)]
pub struct KeyEventProperties {
- pub key_string: &'static str,
+ pub key_string: Cow<'static, str>,
pub code: &'static str,
pub location: u32,
pub char_code: Option<u32>,
diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl
index 8d587b9760a..02864d39a77 100644
--- a/components/script/dom/webidls/CSSStyleDeclaration.webidl
+++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl
@@ -308,6 +308,9 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transitionDelay;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transition-delay;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString flex;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString flexFlow;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString flex-flow;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString flexDirection;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString flex-direction;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString flexWrap;
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index 7085fcae002..ebc2da9c529 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -387,17 +387,13 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
#[inline]
- fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str> {
- unsafe {
- (*self.element.unsafe_get()).get_attr_val_for_layout(namespace, name)
- }
+ fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool {
+ self.get_attr(namespace, attr).is_some()
}
#[inline]
- fn get_attrs(&self, name: &Atom) -> Vec<&str> {
- unsafe {
- (*self.element.unsafe_get()).get_attr_vals_for_layout(name)
- }
+ fn attr_equals(&self, namespace: &Namespace, attr: &Atom, val: &Atom) -> bool {
+ self.get_attr(namespace, attr).map_or(false, |x| x == val)
}
}
@@ -409,12 +405,41 @@ impl<'le> ServoLayoutElement<'le> {
chain: PhantomData,
}
}
+
+ #[inline]
+ fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str> {
+ unsafe {
+ (*self.element.unsafe_get()).get_attr_val_for_layout(namespace, name)
+ }
+ }
}
fn as_element<'le>(node: LayoutJS<Node>) -> Option<ServoLayoutElement<'le>> {
node.downcast().map(ServoLayoutElement::from_layout_js)
}
+impl<'le> ::selectors::MatchAttrGeneric for ServoLayoutElement<'le> {
+ fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
+ use ::selectors::Element;
+ let name = if self.is_html_element_in_html_document() {
+ &attr.lower_name
+ } else {
+ &attr.name
+ };
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attr(ns, name).map_or(false, |attr| test(attr))
+ },
+ NamespaceConstraint::Any => {
+ let attrs = unsafe {
+ (*self.element.unsafe_get()).get_attr_vals_for_layout(name)
+ };
+ attrs.iter().any(|attr| test(*attr))
+ }
+ }
+ }
+}
+
impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
type Impl = ServoSelectorImpl;
@@ -550,22 +575,6 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
}
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
- let name = if self.is_html_element_in_html_document() {
- &attr.lower_name
- } else {
- &attr.name
- };
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attr(ns, name).map_or(false, |attr| test(attr))
- },
- NamespaceConstraint::Any => {
- self.get_attrs(name).iter().any(|attr| test(*attr))
- }
- }
- }
-
fn is_html_element_in_html_document(&self) -> bool {
unsafe {
self.element.html_element_in_html_document_for_layout()
@@ -900,7 +909,23 @@ impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> {
///
/// Note that the element implementation is needed only for selector matching,
/// not for inheritance (styles are inherited appropiately).
-impl <'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
+impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> {
+ fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
+ where F: Fn(&str) -> bool {
+ match attr.namespace {
+ NamespaceConstraint::Specific(ref ns) => {
+ self.get_attr(ns, &attr.name).map_or(false, |attr| test(attr))
+ },
+ NamespaceConstraint::Any => {
+ unsafe {
+ self.element.get_attr_vals_for_layout(&attr.name).iter()
+ .any(|attr| test(*attr))
+ }
+ }
+ }
+ }
+}
+impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
type Impl = ServoSelectorImpl;
fn parent_element(&self) -> Option<Self> {
@@ -962,21 +987,6 @@ impl <'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
false
}
- fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
- where F: Fn(&str) -> bool {
- match attr.namespace {
- NamespaceConstraint::Specific(ref ns) => {
- self.get_attr(ns, &attr.name).map_or(false, |attr| test(attr))
- },
- NamespaceConstraint::Any => {
- unsafe {
- self.element.get_attr_vals_for_layout(&attr.name).iter()
- .any(|attr| test(*attr))
- }
- }
- }
- }
-
fn is_empty(&self) -> bool {
warn!("ServoThreadSafeLayoutElement::is_empty called");
false
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 2367ecc0fd9..05689baac39 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -1937,12 +1937,12 @@ impl ScriptThread {
document.r().handle_touchpad_pressure_event(self.js_runtime.rt(), point, pressure, phase);
}
- KeyEvent(key, state, modifiers) => {
+ KeyEvent(ch, key, state, modifiers) => {
let document = match self.root_browsing_context().find(pipeline_id) {
Some(browsing_context) => browsing_context.active_document(),
None => return warn!("Message sent to closed pipeline {}.", pipeline_id),
};
- document.dispatch_key_event(key, state, modifiers, &self.constellation_chan);
+ document.dispatch_key_event(ch, key, state, modifiers, &self.constellation_chan);
}
}
}
diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs
index daf212d8c52..fbe864a9005 100644
--- a/components/script/task_source/dom_manipulation.rs
+++ b/components/script/task_source/dom_manipulation.rs
@@ -52,7 +52,8 @@ pub enum DOMManipulationTask {
// https://html.spec.whatwg.org/multipage/#planned-navigation
PlannedNavigation(Box<Runnable + Send>),
// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
- SendStorageNotification(Box<MainThreadRunnable + Send>)
+ SendStorageNotification(Box<MainThreadRunnable + Send>),
+ Miscellaneous(Box<Runnable + Send>),
}
impl DOMManipulationTask {
@@ -72,7 +73,8 @@ impl DOMManipulationTask {
FireToggleEvent(runnable) => runnable.handler(),
MediaTask(runnable) => runnable.handler(),
PlannedNavigation(runnable) => runnable.handler(),
- SendStorageNotification(runnable) => runnable.handler(script_thread)
+ SendStorageNotification(runnable) => runnable.handler(script_thread),
+ Miscellaneous(runnable) => runnable.handler(),
}
}
}
diff --git a/components/script/textinput.rs b/components/script/textinput.rs
index a56bd983f34..871af9637c0 100644
--- a/components/script/textinput.rs
+++ b/components/script/textinput.rs
@@ -6,7 +6,7 @@
use clipboard_provider::ClipboardProvider;
use dom::bindings::str::DOMString;
-use dom::keyboardevent::{KeyboardEvent, key_value};
+use dom::keyboardevent::KeyboardEvent;
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
use msg::constellation_msg::{Key, KeyModifiers};
use std::borrow::ToOwned;
@@ -120,24 +120,6 @@ fn is_control_key(mods: KeyModifiers) -> bool {
mods.contains(CONTROL) && !mods.contains(SUPER | ALT)
}
-fn is_printable_key(key: Key) -> bool {
- match key {
- Key::Space | Key::Apostrophe | Key::Comma | Key::Minus |
- Key::Period | Key::Slash | Key::GraveAccent | Key::Num0 |
- Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 |
- Key::Num6 | Key::Num7 | Key::Num8 | Key::Num9 | Key::Semicolon |
- Key::Equal | Key::A | Key::B | Key::C | Key::D | Key::E | Key::F |
- Key::G | Key::H | Key::I | Key::J | Key::K | Key::L | Key::M | Key::N |
- Key::O | Key::P | Key::Q | Key::R | Key::S | Key::T | Key::U | Key::V |
- Key::W | Key::X | Key::Y | Key::Z | Key::LeftBracket | Key::Backslash |
- Key::RightBracket | Key::Kp0 | Key::Kp1 | Key::Kp2 | Key::Kp3 |
- Key::Kp4 | Key::Kp5 | Key::Kp6 | Key::Kp7 | Key::Kp8 | Key::Kp9 |
- Key::KpDecimal | Key::KpDivide | Key::KpMultiply | Key::KpSubtract |
- Key::KpAdd | Key::KpEqual => true,
- _ => false,
- }
-}
-
/// The length in bytes of the first n characters in a UTF-8 string.
///
/// If the string has fewer than n characters, returns the length of the whole string.
@@ -486,80 +468,80 @@ impl<T: ClipboardProvider> TextInput<T> {
/// Process a given `KeyboardEvent` and return an action for the caller to execute.
pub fn handle_keydown(&mut self, event: &KeyboardEvent) -> KeyReaction {
if let Some(key) = event.get_key() {
- self.handle_keydown_aux(key, event.get_key_modifiers())
+ self.handle_keydown_aux(event.printable(), key, event.get_key_modifiers())
} else {
KeyReaction::Nothing
}
}
- pub fn handle_keydown_aux(&mut self, key: Key, mods: KeyModifiers) -> KeyReaction {
+
+ pub fn handle_keydown_aux(&mut self,
+ printable: Option<char>,
+ key: Key,
+ mods: KeyModifiers) -> KeyReaction {
let maybe_select = if mods.contains(SHIFT) { Selection::Selected } else { Selection::NotSelected };
- match key {
- Key::A if is_control_key(mods) => {
+ match (printable, key) {
+ (Some('a'), _) if is_control_key(mods) => {
self.select_all();
KeyReaction::RedrawSelection
},
- Key::C if is_control_key(mods) => {
+ (Some('c'), _) if is_control_key(mods) => {
if let Some(text) = self.get_selection_text() {
self.clipboard_provider.set_clipboard_contents(text);
}
KeyReaction::DispatchInput
},
- Key::V if is_control_key(mods) => {
+ (Some('v'), _) if is_control_key(mods) => {
let contents = self.clipboard_provider.clipboard_contents();
self.insert_string(contents);
KeyReaction::DispatchInput
},
- _ if is_printable_key(key) => {
- self.insert_string(key_value(key, mods));
- KeyReaction::DispatchInput
- }
- Key::Space => {
- self.insert_char(' ');
+ (Some(c), _) => {
+ self.insert_char(c);
KeyReaction::DispatchInput
}
- Key::Delete => {
+ (None, Key::Delete) => {
self.delete_char(Direction::Forward);
KeyReaction::DispatchInput
}
- Key::Backspace => {
+ (None, Key::Backspace) => {
self.delete_char(Direction::Backward);
KeyReaction::DispatchInput
}
- Key::Left => {
+ (None, Key::Left) => {
self.adjust_horizontal_by_one(Direction::Backward, maybe_select);
KeyReaction::RedrawSelection
}
- Key::Right => {
+ (None, Key::Right) => {
self.adjust_horizontal_by_one(Direction::Forward, maybe_select);
KeyReaction::RedrawSelection
}
- Key::Up => {
+ (None, Key::Up) => {
self.adjust_vertical(-1, maybe_select);
KeyReaction::RedrawSelection
}
- Key::Down => {
+ (None, Key::Down) => {
self.adjust_vertical(1, maybe_select);
KeyReaction::RedrawSelection
}
- Key::Enter | Key::KpEnter => self.handle_return(),
- Key::Home => {
+ (None, Key::Enter) | (None, Key::KpEnter) => self.handle_return(),
+ (None, Key::Home) => {
self.edit_point.index = 0;
KeyReaction::RedrawSelection
}
- Key::End => {
+ (None, Key::End) => {
self.edit_point.index = self.current_line_length();
self.assert_ok_selection();
KeyReaction::RedrawSelection
}
- Key::PageUp => {
+ (None, Key::PageUp) => {
self.adjust_vertical(-28, maybe_select);
KeyReaction::RedrawSelection
}
- Key::PageDown => {
+ (None, Key::PageDown) => {
self.adjust_vertical(28, maybe_select);
KeyReaction::RedrawSelection
}
- Key::Tab => KeyReaction::TriggerDefaultAction,
+ (None, Key::Tab) => KeyReaction::TriggerDefaultAction,
_ => KeyReaction::Nothing,
}
}