mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
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:
parent
831243af7c
commit
32aad0838e
4 changed files with 26 additions and 11 deletions
|
@ -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,
|
||||||
|
|
|
@ -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!"),
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue