diff options
author | bors-servo <metajack+bors@gmail.com> | 2015-10-21 15:23:52 -0600 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2015-10-21 15:23:52 -0600 |
commit | af6a64e176ec66a9c066e9e7bf40b6ce3ac77b2e (patch) | |
tree | 16b07286847fc8370efc9bb9bab441c9e913b896 /components | |
parent | f9e17d33bb3cd5cfe103bb1631f390123bcddc04 (diff) | |
parent | 80e8a674e219a6b65e070675d1775f0bd0e2ad93 (diff) | |
download | servo-af6a64e176ec66a9c066e9e7bf40b6ce3ac77b2e.tar.gz servo-af6a64e176ec66a9c066e9e7bf40b6ce3ac77b2e.zip |
Auto merge of #7761 - fiji-flo:input_caret, r=pcwalton
display input caret for textarea. fixes #7758
This adds the input caret for textareas. Although, it does not handle multiline textareas correctly. The caret gets displayed for each line.
I'll look into that but that will take more time. Some feedback on this small patch would be appreciated though.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7761)
<!-- Reviewable:end -->
Diffstat (limited to 'components')
-rw-r--r-- | components/layout/text.rs | 12 | ||||
-rw-r--r-- | components/layout/wrapper.rs | 29 | ||||
-rw-r--r-- | components/script/dom/htmltextareaelement.rs | 8 | ||||
-rw-r--r-- | components/script/textinput.rs | 10 | ||||
-rw-r--r-- | components/util/str.rs | 15 |
5 files changed, 54 insertions, 20 deletions
diff --git a/components/layout/text.rs b/components/layout/text.rs index e007eb3d25b..feab75efa65 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -431,9 +431,19 @@ fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragm string_before = unscanned_text_fragment_info.text[..(position + 1)].to_owned(); - insertion_point_before = unscanned_text_fragment_info.insertion_point; unscanned_text_fragment_info.text = unscanned_text_fragment_info.text[(position + 1)..].to_owned().into_boxed_str(); + let offset = CharIndex(string_before.char_indices().count() as isize); + match unscanned_text_fragment_info.insertion_point { + Some(insertion_point) if insertion_point >= offset => { + insertion_point_before = None; + unscanned_text_fragment_info.insertion_point = Some(insertion_point - offset); + } + Some(_) | None => { + insertion_point_before = unscanned_text_fragment_info.insertion_point; + unscanned_text_fragment_info.insertion_point = None; + } + }; } first_fragment.transform(first_fragment.border_box.size, SpecificFragmentInfo::UnscannedText( diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 2be8382ee4c..e2c0bd89f19 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -71,7 +71,7 @@ use style::node::TElementAttributes; use style::properties::ComputedValues; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; use url::Url; -use util::str::is_whitespace; +use util::str::{is_whitespace, search_index}; /// A wrapper so that layout can access only the methods that it should have access to. Layout must /// only ever see these and must never see instances of `LayoutJS`. @@ -918,24 +918,17 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { let this = unsafe { self.get_jsmanaged() }; - let input = this.downcast(); - if let Some(input) = input { - let insertion_point = unsafe { - input.get_insertion_point_for_layout() - }; + + if let Some(area) = this.downcast::<HTMLTextAreaElement>() { + let insertion_point = unsafe { area.get_absolute_insertion_point_for_layout() }; + let text = unsafe { area.get_value_for_layout() }; + return Some(CharIndex(search_index(insertion_point, text.char_indices()))); + } + if let Some(input) = this.downcast::<HTMLInputElement>() { + let insertion_point = unsafe { input.get_insertion_point_for_layout() }; if let Some(insertion_point) = insertion_point { - let text = unsafe { - input.get_value_for_layout() - }; - - let mut character_count = 0; - for (character_index, _) in text.char_indices() { - if character_index == insertion_point.index { - return Some(CharIndex(character_count)) - } - character_count += 1 - } - return Some(CharIndex(character_count)) + let text = unsafe { input.get_value_for_layout() }; + return Some(CharIndex(search_index(insertion_point.index, text.char_indices()))); } } None diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index d802760a308..2ef5a24775d 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -46,6 +46,8 @@ pub struct HTMLTextAreaElement { pub trait LayoutHTMLTextAreaElementHelpers { #[allow(unsafe_code)] unsafe fn get_value_for_layout(self) -> String; + #[allow(unsafe_code)] + unsafe fn get_absolute_insertion_point_for_layout(self) -> usize; } pub trait RawLayoutHTMLTextAreaElementHelpers { @@ -61,6 +63,12 @@ impl LayoutHTMLTextAreaElementHelpers for LayoutJS<HTMLTextAreaElement> { unsafe fn get_value_for_layout(self) -> String { (*self.unsafe_get()).textinput.borrow_for_layout().get_content() } + + #[allow(unrooted_must_root)] + #[allow(unsafe_code)] + unsafe fn get_absolute_insertion_point_for_layout(self) -> usize { + (*self.unsafe_get()).textinput.borrow_for_layout().get_absolute_insertion_point() + } } impl<'a> RawLayoutHTMLTextAreaElementHelpers for &'a HTMLTextAreaElement { diff --git a/components/script/textinput.rs b/components/script/textinput.rs index 627ecf29a5f..c75d246d3ba 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -455,4 +455,14 @@ impl<T: ClipboardProvider> TextInput<T> { self.edit_point.line = min(self.edit_point.line, self.lines.len() - 1); self.edit_point.index = min(self.edit_point.index, self.current_line_length()); } + + pub fn get_absolute_insertion_point(&self) -> usize { + self.lines.iter().enumerate().fold(0, |acc, (i, val)| { + if i < self.edit_point.line { + acc + val.len() + 1 // +1 for the \n + } else { + acc + } + }) + self.edit_point.index + } } diff --git a/components/util/str.rs b/components/util/str.rs index 78bc8824707..91d5562f4e4 100644 --- a/components/util/str.rs +++ b/components/util/str.rs @@ -11,7 +11,7 @@ use std::borrow::ToOwned; use std::ffi::CStr; use std::iter::{Filter, Peekable}; use std::ops::Deref; -use std::str::{FromStr, Split, from_utf8}; +use std::str::{CharIndices, FromStr, Split, from_utf8}; pub type DOMString = String; pub type StaticCharVec = &'static [char]; @@ -420,3 +420,16 @@ pub fn slice_chars(s: &str, begin: usize, end: usize) -> &str { (Some(a), Some(b)) => unsafe { s.slice_unchecked(a, b) } } } + +// searches a character index in CharIndices +// returns indices.count if not found +pub fn search_index(index: usize, indices: CharIndices) -> isize { + let mut character_count = 0; + for (character_index, _) in indices { + if character_index == index { + return character_count; + } + character_count += 1 + } + character_count +} |