diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/Cargo.toml | 2 | ||||
-rw-r--r-- | components/script/dom/bindings/str.rs | 11 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 2 | ||||
-rw-r--r-- | components/script/dom/document.rs | 9 | ||||
-rw-r--r-- | components/script/dom/element.rs | 53 | ||||
-rw-r--r-- | components/script/dom/htmlimageelement.rs | 104 | ||||
-rw-r--r-- | components/script/dom/keyboardevent.rs | 42 | ||||
-rw-r--r-- | components/script/dom/webidls/CSSStyleDeclaration.webidl | 3 | ||||
-rw-r--r-- | components/script/layout_wrapper.rs | 90 | ||||
-rw-r--r-- | components/script/script_thread.rs | 4 | ||||
-rw-r--r-- | components/script/task_source/dom_manipulation.rs | 6 | ||||
-rw-r--r-- | components/script/textinput.rs | 68 |
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, } } |