summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthankyouverycool <66646555+thankyouverycool@users.noreply.github.com>2022-12-15 12:26:05 -0500
committerAndreas Kling <kling@serenityos.org>2022-12-20 10:22:27 +0100
commitc4ac73d0738243fd3cd0246d5038b2319f0f07a4 (patch)
treebf824cb07323d53fc2135f65f4f4d614a0b3f294
parent12cd30f1acd6bccfba07d3054d71feb0467a3d78 (diff)
downloadserenity-c4ac73d0738243fd3cd0246d5038b2319f0f07a4.zip
LibGUI: Check bounds when moving GlyphMapWidget selections
Fixes crashing on invalid code points when creating selections with the keyboard and applying actions to them. Also adds Home/End key support for selections. Ctrl+Shift+{Home,End} now extends the selection to the beginning or end of the active range, respectively. Shift+{Home,End} extends the selection to the start or end of the row. Alt+{Home,End} resets the selection and moves the active glyph to the beginning or end of the active range.
-rw-r--r--Userland/Libraries/LibGUI/GlyphMapWidget.cpp129
1 files changed, 79 insertions, 50 deletions
diff --git a/Userland/Libraries/LibGUI/GlyphMapWidget.cpp b/Userland/Libraries/LibGUI/GlyphMapWidget.cpp
index 9157ebda58..6ddc8319d2 100644
--- a/Userland/Libraries/LibGUI/GlyphMapWidget.cpp
+++ b/Userland/Libraries/LibGUI/GlyphMapWidget.cpp
@@ -264,78 +264,107 @@ void GlyphMapWidget::keydown_event(KeyEvent& event)
return;
}
- int range_offset = m_active_range.first;
-
if (!event.ctrl() && !event.shift() && event.key() != KeyCode::Key_Delete) {
m_selection.set_size(1);
m_selection.set_start(m_active_glyph);
}
+ int first_glyph = m_active_range.first;
+ int last_glyph = m_active_range.last;
+ auto selection = m_selection.normalized();
+
if (event.key() == KeyCode::Key_Up) {
- if (m_selection.start() - range_offset >= m_columns) {
- if (event.shift())
- m_selection.resize_by(-m_columns);
- else
- m_selection.set_start(m_selection.start() - m_columns);
- set_active_glyph(m_active_glyph - m_columns, ShouldResetSelection::No);
- scroll_to_glyph(m_active_glyph);
+ if (m_active_glyph - m_columns < first_glyph)
return;
- }
+ if (event.ctrl() && selection.start() - m_columns < first_glyph)
+ return;
+ if (event.shift())
+ m_selection.extend_to(m_active_glyph - m_columns);
+ else
+ m_selection.set_start(m_selection.start() - m_columns);
+ set_active_glyph(m_active_glyph - m_columns, ShouldResetSelection::No);
+ scroll_to_glyph(m_active_glyph);
+ return;
}
+
if (event.key() == KeyCode::Key_Down) {
- if (m_selection.start() < m_glyph_count + range_offset - m_columns) {
- if (event.shift())
- m_selection.resize_by(m_columns);
- else
- m_selection.set_start(m_selection.start() + m_columns);
- set_active_glyph(m_active_glyph + m_columns, ShouldResetSelection::No);
- scroll_to_glyph(m_active_glyph);
+ if (m_active_glyph + m_columns > last_glyph)
return;
- }
+ if (event.ctrl() && selection.start() + selection.size() - 1 + m_columns > last_glyph)
+ return;
+ if (event.shift())
+ m_selection.extend_to(m_active_glyph + m_columns);
+ else
+ m_selection.set_start(m_selection.start() + m_columns);
+ set_active_glyph(m_active_glyph + m_columns, ShouldResetSelection::No);
+ scroll_to_glyph(m_active_glyph);
+ return;
}
+
if (event.key() == KeyCode::Key_Left) {
- if (m_selection.start() > range_offset) {
- if (event.shift())
- m_selection.resize_by(-1);
- else
- m_selection.set_start(m_selection.start() - 1);
- set_active_glyph(m_active_glyph - 1, ShouldResetSelection::No);
- scroll_to_glyph(m_active_glyph);
+ if (m_active_glyph - 1 < first_glyph)
return;
- }
- }
- if (event.key() == KeyCode::Key_Right) {
- if (m_selection.start() < m_glyph_count + range_offset - 1) {
- if (event.shift())
- m_selection.resize_by(1);
- else
- m_selection.set_start(m_selection.start() + 1);
- set_active_glyph(m_active_glyph + 1, ShouldResetSelection::No);
- scroll_to_glyph(m_active_glyph);
+ if (event.ctrl() && selection.start() - 1 < first_glyph)
return;
- }
- }
-
- // FIXME: Support selection for these.
- if (event.ctrl() && event.key() == KeyCode::Key_Home) {
- set_active_glyph(m_active_range.first);
+ if (event.shift())
+ m_selection.resize_by(-1);
+ else
+ m_selection.set_start(m_selection.start() - 1);
+ set_active_glyph(m_active_glyph - 1, ShouldResetSelection::No);
scroll_to_glyph(m_active_glyph);
return;
}
- if (event.ctrl() && event.key() == KeyCode::Key_End) {
- set_active_glyph(m_active_range.last);
+
+ if (event.key() == KeyCode::Key_Right) {
+ if (m_active_glyph + 1 > last_glyph)
+ return;
+ if (event.ctrl() && selection.start() + selection.size() > last_glyph)
+ return;
+ if (event.shift())
+ m_selection.resize_by(1);
+ else
+ m_selection.set_start(m_selection.start() + 1);
+ set_active_glyph(m_active_glyph + 1, ShouldResetSelection::No);
scroll_to_glyph(m_active_glyph);
return;
}
- if (!event.ctrl() && event.key() == KeyCode::Key_Home) {
- auto start_of_row = (m_active_glyph - range_offset) / m_columns * m_columns;
- set_active_glyph(start_of_row + range_offset);
+
+ if (event.key() == KeyCode::Key_Home) {
+ if (event.alt()) {
+ set_active_glyph(first_glyph);
+ scroll_to_glyph(m_active_glyph);
+ return;
+ }
+ if (event.ctrl() && event.shift()) {
+ m_selection.extend_to(first_glyph);
+ set_active_glyph(first_glyph, ShouldResetSelection::No);
+ scroll_to_glyph(m_active_glyph);
+ return;
+ }
+ auto start_of_row = (m_active_glyph - first_glyph) / m_columns * m_columns;
+ if (event.shift())
+ m_selection.extend_to(start_of_row + first_glyph);
+ set_active_glyph(start_of_row + first_glyph, event.shift() ? ShouldResetSelection::No : ShouldResetSelection::Yes);
return;
}
- if (!event.ctrl() && event.key() == KeyCode::Key_End) {
- auto end_of_row = (m_active_glyph - range_offset) / m_columns * m_columns + (m_columns - 1);
- end_of_row = clamp(end_of_row + range_offset, m_active_range.first, m_active_range.last);
- set_active_glyph(end_of_row);
+
+ if (event.key() == KeyCode::Key_End) {
+ if (event.alt()) {
+ set_active_glyph(last_glyph);
+ scroll_to_glyph(m_active_glyph);
+ return;
+ }
+ if (event.ctrl() && event.shift()) {
+ m_selection.extend_to(last_glyph);
+ set_active_glyph(last_glyph, ShouldResetSelection::No);
+ scroll_to_glyph(m_active_glyph);
+ return;
+ }
+ auto end_of_row = (m_active_glyph - first_glyph) / m_columns * m_columns + (m_columns - 1);
+ end_of_row = clamp(end_of_row + first_glyph, first_glyph, last_glyph);
+ if (event.shift())
+ m_selection.extend_to(end_of_row);
+ set_active_glyph(end_of_row, event.shift() ? ShouldResetSelection::No : ShouldResetSelection::Yes);
return;
}