Draw insertion point even for empty input fields

This allows text layout to generate an empty text fragment if the fragment
contains the insertion point for a text input box.
This commit is contained in:
Matt Brubeck 2016-04-01 20:18:28 -07:00
parent 831243af7c
commit 32aad0838e
4 changed files with 26 additions and 11 deletions

View file

@ -1014,13 +1014,9 @@ impl FragmentDisplayListBuilding for Fragment {
// display list items. // display list items.
let mut clip = (*clip).clone(); let mut clip = (*clip).clone();
self.adjust_clip_for_style(&mut clip, &stacking_relative_border_box); self.adjust_clip_for_style(&mut clip, &stacking_relative_border_box);
if !clip.might_intersect_rect(&stacking_relative_border_box) { let empty_rect = !clip.might_intersect_rect(&stacking_relative_border_box);
return;
}
debug!("Fragment::build_display_list: intersected. Adding display item..."); if self.is_primary_fragment() && !empty_rect {
if self.is_primary_fragment() {
// Add shadows, background, borders, and outlines, if applicable. // Add shadows, background, borders, and outlines, if applicable.
if let Some(ref inline_context) = self.inline_context { if let Some(ref inline_context) = self.inline_context {
for node in inline_context.nodes.iter().rev() { for node in inline_context.nodes.iter().rev() {
@ -1080,14 +1076,23 @@ impl FragmentDisplayListBuilding for Fragment {
&stacking_relative_border_box, &stacking_relative_border_box,
&clip); &clip);
} }
}
// Paint the selection point if necessary. if self.is_primary_fragment() {
// Paint the selection point if necessary. Even an empty text fragment may have an
// insertion point, so we do this even if `empty_rect` is true.
self.build_display_items_for_selection_if_necessary(state, self.build_display_items_for_selection_if_necessary(state,
&stacking_relative_border_box, &stacking_relative_border_box,
display_list_section, display_list_section,
&clip); &clip);
} }
if empty_rect {
return;
}
debug!("Fragment::build_display_list: intersected. Adding display item...");
// Create special per-fragment-type display items. // Create special per-fragment-type display items.
self.build_fragment_type_specific_display_items(state, self.build_fragment_type_specific_display_items(state,
&stacking_relative_border_box, &stacking_relative_border_box,

View file

@ -1709,6 +1709,9 @@ impl Fragment {
if other_info.requires_line_break_afterward_if_wrapping_on_newlines() { if other_info.requires_line_break_afterward_if_wrapping_on_newlines() {
this_info.flags.insert(REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES); this_info.flags.insert(REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES);
} }
if other_info.insertion_point.is_some() {
this_info.insertion_point = other_info.insertion_point;
}
self.border_padding.inline_end = next_fragment.border_padding.inline_end; self.border_padding.inline_end = next_fragment.border_padding.inline_end;
} }
_ => panic!("Can only merge two scanned-text fragments!"), _ => panic!("Can only merge two scanned-text fragments!"),

View file

@ -239,6 +239,7 @@ impl TextRunScanner {
mapping.flush(&mut mappings, mapping.flush(&mut mappings,
&mut run_info, &mut run_info,
&**text, &**text,
insertion_point,
compression, compression,
text_transform, text_transform,
&mut last_whitespace, &mut last_whitespace,
@ -268,6 +269,7 @@ impl TextRunScanner {
mapping.flush(&mut mappings, mapping.flush(&mut mappings,
&mut run_info, &mut run_info,
&**text, &**text,
insertion_point,
compression, compression,
text_transform, text_transform,
&mut last_whitespace, &mut last_whitespace,
@ -336,6 +338,7 @@ impl TextRunScanner {
let scanned_run = runs[mapping.text_run_index].clone(); let scanned_run = runs[mapping.text_run_index].clone();
let requires_line_break_afterward_if_wrapping_on_newlines = let requires_line_break_afterward_if_wrapping_on_newlines =
!mapping.byte_range.is_empty() &&
scanned_run.run.text.char_at_reverse(mapping.byte_range.end()) == '\n'; scanned_run.run.text.char_at_reverse(mapping.byte_range.end()) == '\n';
if requires_line_break_afterward_if_wrapping_on_newlines { if requires_line_break_afterward_if_wrapping_on_newlines {
mapping.char_range.extend_by(CharIndex(-1)); mapping.char_range.extend_by(CharIndex(-1));
@ -575,12 +578,13 @@ impl RunMapping {
mappings: &mut Vec<RunMapping>, mappings: &mut Vec<RunMapping>,
run_info: &mut RunInfo, run_info: &mut RunInfo,
text: &str, text: &str,
insertion_point: Option<CharIndex>,
compression: CompressionMode, compression: CompressionMode,
text_transform: text_transform::T, text_transform: text_transform::T,
last_whitespace: &mut bool, last_whitespace: &mut bool,
start_position: &mut usize, start_position: &mut usize,
end_position: usize) { end_position: usize) {
if *start_position == end_position { if *start_position == end_position && insertion_point.is_none() {
return; return;
} }
let old_byte_length = run_info.text.len(); let old_byte_length = run_info.text.len();
@ -601,9 +605,9 @@ impl RunMapping {
run_info.character_length = run_info.character_length + character_count; run_info.character_length = run_info.character_length + character_count;
*start_position = end_position; *start_position = end_position;
// Don't flush empty mappings. // Don't flush mappings that contain no characters and no insertion_point.
if character_count == 0 { if character_count == 0 && !self.contains_insertion_point(insertion_point) {
return return;
} }
let new_byte_length = run_info.text.len(); let new_byte_length = run_info.text.len();

View file

@ -11,5 +11,8 @@
<body> <body>
<input id="a"> <input id="a">
<input id="b"> <input id="b">
<script>
document.getElementById("a").focus();
</script>
</body> </body>
</html> </html>