1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:47:44 +00:00

LibGUI: Keep scrolling while drag-selecting outside a TextEditor

If you start selecting text and move the cursor outside the TextEditor
widget area without letting go of the mouse button, we will now keep
scrolling a little bit every 100ms.
This commit is contained in:
Andreas Kling 2020-04-20 21:31:49 +02:00
parent f78a92c5a9
commit 5c15c24976
2 changed files with 29 additions and 0 deletions

View file

@ -27,6 +27,7 @@
#include <AK/QuickSort.h> #include <AK/QuickSort.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <Kernel/KeyCode.h> #include <Kernel/KeyCode.h>
#include <LibCore/Timer.h>
#include <LibGUI/Action.h> #include <LibGUI/Action.h>
#include <LibGUI/Clipboard.h> #include <LibGUI/Clipboard.h>
#include <LibGUI/FontDatabase.h> #include <LibGUI/FontDatabase.h>
@ -60,6 +61,10 @@ TextEditor::TextEditor(Type type)
// FIXME: Recompute vertical scrollbar step size on font change. // FIXME: Recompute vertical scrollbar step size on font change.
vertical_scrollbar().set_step(line_height()); vertical_scrollbar().set_step(line_height());
m_cursor = { 0, 0 }; m_cursor = { 0, 0 };
m_automatic_selection_scroll_timer = add<Core::Timer>(100, [this] {
automatic_selection_scroll_timer_fired();
});
m_automatic_selection_scroll_timer->stop();
create_actions(); create_actions();
} }
@ -261,6 +266,7 @@ void TextEditor::mousedown_event(MouseEvent& event)
} }
m_in_drag_select = true; m_in_drag_select = true;
m_automatic_selection_scroll_timer->start();
set_cursor(text_position_at(event.position())); set_cursor(text_position_at(event.position()));
@ -289,6 +295,7 @@ void TextEditor::mouseup_event(MouseEvent& event)
void TextEditor::mousemove_event(MouseEvent& event) void TextEditor::mousemove_event(MouseEvent& event)
{ {
m_last_mousemove_position = event.position();
if (m_in_drag_select) { if (m_in_drag_select) {
set_cursor(text_position_at(event.position())); set_cursor(text_position_at(event.position()));
m_selection.set_end(m_cursor); m_selection.set_end(m_cursor);
@ -298,6 +305,18 @@ void TextEditor::mousemove_event(MouseEvent& event)
} }
} }
void TextEditor::automatic_selection_scroll_timer_fired()
{
if (!m_in_drag_select) {
m_automatic_selection_scroll_timer->stop();
return;
}
set_cursor(text_position_at(m_last_mousemove_position));
m_selection.set_end(m_cursor);
did_update_selection();
update();
}
int TextEditor::ruler_width() const int TextEditor::ruler_width() const
{ {
if (!m_ruler_visible) if (!m_ruler_visible)
@ -1189,12 +1208,17 @@ void TextEditor::enter_event(Core::Event&)
{ {
ASSERT(window()); ASSERT(window());
window()->set_override_cursor(StandardCursor::IBeam); window()->set_override_cursor(StandardCursor::IBeam);
m_automatic_selection_scroll_timer->stop();
} }
void TextEditor::leave_event(Core::Event&) void TextEditor::leave_event(Core::Event&)
{ {
ASSERT(window()); ASSERT(window());
window()->set_override_cursor(StandardCursor::None); window()->set_override_cursor(StandardCursor::None);
if (m_in_drag_select)
m_automatic_selection_scroll_timer->start();
} }
void TextEditor::did_change() void TextEditor::did_change()

View file

@ -200,6 +200,8 @@ private:
size_t visual_line_containing(size_t line_index, size_t column) const; size_t visual_line_containing(size_t line_index, size_t column) const;
void recompute_visual_lines(size_t line_index); void recompute_visual_lines(size_t line_index);
void automatic_selection_scroll_timer_fired();
template<class T, class... Args> template<class T, class... Args>
inline void execute(Args&&... args) inline void execute(Args&&... args)
{ {
@ -247,6 +249,9 @@ private:
NonnullOwnPtrVector<LineVisualData> m_line_visual_data; NonnullOwnPtrVector<LineVisualData> m_line_visual_data;
OwnPtr<SyntaxHighlighter> m_highlighter; OwnPtr<SyntaxHighlighter> m_highlighter;
RefPtr<Core::Timer> m_automatic_selection_scroll_timer;
Gfx::Point m_last_mousemove_position;
}; };
} }