mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
display input caret for textarea. fixes #7758
This commit is contained in:
parent
50ec235384
commit
80e8a674e2
6 changed files with 67 additions and 21 deletions
|
@ -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(
|
||||
|
|
|
@ -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(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))
|
||||
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() };
|
||||
return Some(CharIndex(search_index(insertion_point.index, text.char_indices())));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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 util::str::{split_html_space_chars, str_join};
|
||||
use util::str::{search_index, split_html_space_chars, str_join};
|
||||
|
||||
|
||||
#[test]
|
||||
|
@ -34,3 +34,15 @@ pub fn test_str_join_many() {
|
|||
let expected = "-alpha--beta-gamma-";
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_search_index() {
|
||||
let tuples = [("", 1, 0),
|
||||
("foo", 8, 3),
|
||||
("føo", 8, 3),
|
||||
("foo", 2, 2),
|
||||
("føo", 2, 3)];
|
||||
for t in tuples.iter() {
|
||||
assert_eq!(search_index(t.1, t.0.char_indices()), t.2);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue