diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-03-30 21:40:27 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-03-30 21:40:57 +0100 |
commit | 25f28a54a131c4aa188ba2c4c453c1b1648d02c6 (patch) | |
tree | 20aa3bde47473ff6c451adf5add30c20225d7ec1 | |
parent | 245c4bd7c89733d940b0b12bf4e8ebf11bbb6e64 (diff) | |
download | serenity-25f28a54a131c4aa188ba2c4c453c1b1648d02c6.zip |
Terminal+LibGUI: Make the terminal cursor blink.
Added a GTimer class to help with this. It's just a simple GObject subclass
that sets up an event loop timer and invokes a callback on timeout.
-rw-r--r-- | Applications/Terminal/Terminal.cpp | 20 | ||||
-rw-r--r-- | Applications/Terminal/Terminal.h | 5 | ||||
-rw-r--r-- | LibGUI/GTimer.cpp | 39 | ||||
-rw-r--r-- | LibGUI/GTimer.h | 32 | ||||
-rw-r--r-- | LibGUI/Makefile | 1 |
5 files changed, 96 insertions, 1 deletions
diff --git a/Applications/Terminal/Terminal.cpp b/Applications/Terminal/Terminal.cpp index 9e85460265..fe0b79a487 100644 --- a/Applications/Terminal/Terminal.cpp +++ b/Applications/Terminal/Terminal.cpp @@ -21,6 +21,12 @@ Terminal::Terminal(int ptm_fd) : m_ptm_fd(ptm_fd) , m_notifier(ptm_fd, GNotifier::Read) { + m_cursor_blink_timer.set_interval(500); + m_cursor_blink_timer.on_timeout = [this] { + m_cursor_blink_state = !m_cursor_blink_state; + update_cursor(); + }; + set_font(Font::default_fixed_width_font()); m_notifier.on_ready_to_read = [this] (GNotifier& notifier) { byte buffer[BUFSIZ]; @@ -724,6 +730,12 @@ void Terminal::event(GEvent& event) { if (event.type() == GEvent::WindowBecameActive || event.type() == GEvent::WindowBecameInactive) { m_in_active_window = event.type() == GEvent::WindowBecameActive; + if (!m_in_active_window) { + m_cursor_blink_timer.stop(); + } else { + m_cursor_blink_state = true; + m_cursor_blink_timer.start(); + } invalidate_cursor(); update(); } @@ -794,7 +806,7 @@ void Terminal::paint_event(GPaintEvent&) painter.fill_rect(row_rect(row), lookup_color(line.attributes[0].background_color).with_alpha(255 * m_opacity)); } for (word column = 0; column < m_columns; ++column) { - bool should_reverse_fill_for_cursor = m_in_active_window && row == m_cursor_row && column == m_cursor_column; + bool should_reverse_fill_for_cursor = m_cursor_blink_state && m_in_active_window && row == m_cursor_row && column == m_cursor_column; auto& attribute = line.attributes[column]; char ch = line.characters[column]; auto character_rect = glyph_rect(row, column); @@ -864,3 +876,9 @@ void Terminal::apply_size_increments_to_window(GWindow& window) window.set_size_increment({ font().glyph_width('x'), m_line_height }); window.set_base_size({ m_inset * 2, m_inset * 2}); } + +void Terminal::update_cursor() +{ + invalidate_cursor(); + flush_dirty_lines(); +} diff --git a/Applications/Terminal/Terminal.h b/Applications/Terminal/Terminal.h index 5f31d3b2e4..4f1bbd439f 100644 --- a/Applications/Terminal/Terminal.h +++ b/Applications/Terminal/Terminal.h @@ -7,6 +7,7 @@ #include <SharedGraphics/Rect.h> #include <LibGUI/GWidget.h> #include <LibGUI/GNotifier.h> +#include <LibGUI/GTimer.h> class Font; @@ -65,6 +66,7 @@ private: word rows() const { return m_rows; } Rect glyph_rect(word row, word column); Rect row_rect(word row); + void update_cursor(); struct Attribute { Attribute() { reset(); } @@ -154,6 +156,9 @@ private: float m_opacity { 1 }; bool m_needs_background_fill { true }; + bool m_cursor_blink_state { true }; int m_glyph_width { 0 }; + + GTimer m_cursor_blink_timer; }; diff --git a/LibGUI/GTimer.cpp b/LibGUI/GTimer.cpp new file mode 100644 index 0000000000..9edd58bd7a --- /dev/null +++ b/LibGUI/GTimer.cpp @@ -0,0 +1,39 @@ +#include <LibGUI/GTimer.h> + +GTimer::GTimer(GObject* parent) + : GObject(parent) +{ +} + +GTimer::~GTimer() +{ +} + +void GTimer::start() +{ + start(m_interval); +} + +void GTimer::start(int interval) +{ + if (m_active) + return; + start_timer(interval); + m_active = true; +} + +void GTimer::stop() +{ + if (!m_active) + return; + stop_timer(); + m_active = false; +} + +void GTimer::timer_event(GTimerEvent&) +{ + if (m_single_shot) + stop(); + if (on_timeout) + on_timeout(); +} diff --git a/LibGUI/GTimer.h b/LibGUI/GTimer.h new file mode 100644 index 0000000000..604c5042df --- /dev/null +++ b/LibGUI/GTimer.h @@ -0,0 +1,32 @@ +#pragma once + +#include <LibGUI/GObject.h> +#include <AK/Function.h> + +class GTimer final : public GObject { +public: + explicit GTimer(GObject* parent = nullptr); + virtual ~GTimer() override; + + void start(); + void start(int interval); + void stop(); + + bool is_active() const { return m_active; } + int interval() const { return m_interval; } + void set_interval(int interval) { m_interval = interval; } + + bool is_single_shot() const { return m_single_shot; } + void set_single_shot(bool single_shot) { m_single_shot = single_shot; } + + Function<void()> on_timeout; + + virtual const char* class_name() const override { return "GTimer"; } + +private: + virtual void timer_event(GTimerEvent&) override; + + bool m_active { false }; + bool m_single_shot { false }; + int m_interval { 0 }; +}; diff --git a/LibGUI/Makefile b/LibGUI/Makefile index 218b344b39..9660229968 100644 --- a/LibGUI/Makefile +++ b/LibGUI/Makefile @@ -57,6 +57,7 @@ LIBGUI_OBJS = \ GTreeView.o \ GFileSystemModel.o \ GSplitter.o \ + GTimer.o \ GWindow.o OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS) |