diff --git a/Applications/PaintBrush/SprayTool.cpp b/Applications/PaintBrush/SprayTool.cpp index 0125897cce..1ebb3456b7 100644 --- a/Applications/PaintBrush/SprayTool.cpp +++ b/Applications/PaintBrush/SprayTool.cpp @@ -11,10 +11,11 @@ SprayTool::SprayTool() { - m_timer.on_timeout = [=]() { + m_timer = CTimer::create(); + m_timer->on_timeout = [&]() { paint_it(); }; - m_timer.set_interval(200); + m_timer->set_interval(200); } SprayTool::~SprayTool() @@ -54,22 +55,22 @@ void SprayTool::on_mousedown(GMouseEvent& event) m_color = m_widget->color_for(event); m_last_pos = event.position(); - m_timer.start(); + m_timer->start(); paint_it(); } void SprayTool::on_mousemove(GMouseEvent& event) { m_last_pos = event.position(); - if (m_timer.is_active()) { + if (m_timer->is_active()) { paint_it(); - m_timer.restart(m_timer.interval()); + m_timer->restart(m_timer->interval()); } } void SprayTool::on_mouseup(GMouseEvent&) { - m_timer.stop(); + m_timer->stop(); } void SprayTool::on_contextmenu(GContextMenuEvent& event) diff --git a/Applications/PaintBrush/SprayTool.h b/Applications/PaintBrush/SprayTool.h index 2260990555..679009a1da 100644 --- a/Applications/PaintBrush/SprayTool.h +++ b/Applications/PaintBrush/SprayTool.h @@ -19,7 +19,7 @@ public: private: virtual const char* class_name() const override { return "SprayTool"; } void paint_it(); - CTimer m_timer; + ObjectPtr m_timer; Point m_last_pos; Color m_color; OwnPtr m_context_menu; diff --git a/Applications/SoundPlayer/main.cpp b/Applications/SoundPlayer/main.cpp index 4fe842dfe8..3df9522139 100644 --- a/Applications/SoundPlayer/main.cpp +++ b/Applications/SoundPlayer/main.cpp @@ -52,7 +52,7 @@ int main(int argc, char** argv) auto next_sample_buffer = loader.get_more_samples(); - new CTimer(100, [&] { + auto timer = CTimer::create(100, [&] { if (!next_sample_buffer) { sample_widget->set_buffer(nullptr); return; diff --git a/Applications/SystemMonitor/NetworkStatisticsWidget.cpp b/Applications/SystemMonitor/NetworkStatisticsWidget.cpp index 4820755d5e..e728e2cd3e 100644 --- a/Applications/SystemMonitor/NetworkStatisticsWidget.cpp +++ b/Applications/SystemMonitor/NetworkStatisticsWidget.cpp @@ -55,7 +55,7 @@ NetworkStatisticsWidget::NetworkStatisticsWidget(GWidget* parent) net_tcp_fields.empend("bytes_out", "Bytes Out", TextAlignment::CenterRight); m_socket_table_view->set_model(GJsonArrayModel::create("/proc/net/tcp", move(net_tcp_fields))); - m_update_timer = new CTimer( + m_update_timer = CTimer::create( 1000, [this] { update_models(); }, diff --git a/Applications/SystemMonitor/NetworkStatisticsWidget.h b/Applications/SystemMonitor/NetworkStatisticsWidget.h index 502474bee1..a76e344ebf 100644 --- a/Applications/SystemMonitor/NetworkStatisticsWidget.h +++ b/Applications/SystemMonitor/NetworkStatisticsWidget.h @@ -16,5 +16,5 @@ private: GTableView* m_adapter_table_view { nullptr }; GTableView* m_socket_table_view { nullptr }; - CTimer* m_update_timer { nullptr }; + ObjectPtr m_update_timer; }; diff --git a/Applications/SystemMonitor/ProcessStacksWidget.cpp b/Applications/SystemMonitor/ProcessStacksWidget.cpp index d7e4a822da..6c52dfd8b1 100644 --- a/Applications/SystemMonitor/ProcessStacksWidget.cpp +++ b/Applications/SystemMonitor/ProcessStacksWidget.cpp @@ -11,7 +11,7 @@ ProcessStacksWidget::ProcessStacksWidget(GWidget* parent) m_stacks_editor = new GTextEditor(GTextEditor::Type::MultiLine, this); m_stacks_editor->set_readonly(true); - m_timer = new CTimer(1000, [this] { refresh(); }, this); + m_timer = CTimer::create(1000, [this] { refresh(); }, this); } ProcessStacksWidget::~ProcessStacksWidget() diff --git a/Applications/SystemMonitor/ProcessStacksWidget.h b/Applications/SystemMonitor/ProcessStacksWidget.h index 9b0c6ac8f0..fb7cac94dd 100644 --- a/Applications/SystemMonitor/ProcessStacksWidget.h +++ b/Applications/SystemMonitor/ProcessStacksWidget.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -17,5 +18,5 @@ public: private: pid_t m_pid { -1 }; GTextEditor* m_stacks_editor { nullptr }; - CTimer* m_timer { nullptr }; + ObjectPtr m_timer; }; diff --git a/Applications/SystemMonitor/main.cpp b/Applications/SystemMonitor/main.cpp index dea87c1f67..9c8f1abf5c 100644 --- a/Applications/SystemMonitor/main.cpp +++ b/Applications/SystemMonitor/main.cpp @@ -111,7 +111,7 @@ int main(int argc, char** argv) auto* process_table_view = new ProcessTableView(*cpu_graph, process_table_container); auto* memory_stats_widget = new MemoryStatsWidget(*memory_graph, graphs_container); - auto* refresh_timer = new CTimer(1000, [&] { + auto refresh_timer = CTimer::create(1000, [&] { process_table_view->refresh(); memory_stats_widget->refresh(); }); @@ -167,19 +167,19 @@ int main(int argc, char** argv) }; auto frequency_menu = make("Frequency"); - frequency_menu->add_action(GAction::create("0.25 sec", [refresh_timer](auto&) { + frequency_menu->add_action(GAction::create("0.25 sec", [&](auto&) { refresh_timer->restart(250); })); - frequency_menu->add_action(GAction::create("0.5 sec", [refresh_timer](auto&) { + frequency_menu->add_action(GAction::create("0.5 sec", [&](auto&) { refresh_timer->restart(500); })); - frequency_menu->add_action(GAction::create("1 sec", [refresh_timer](auto&) { + frequency_menu->add_action(GAction::create("1 sec", [&](auto&) { refresh_timer->restart(1000); })); - frequency_menu->add_action(GAction::create("3 sec", [refresh_timer](auto&) { + frequency_menu->add_action(GAction::create("3 sec", [&](auto&) { refresh_timer->restart(3000); })); - frequency_menu->add_action(GAction::create("5 sec", [refresh_timer](auto&) { + frequency_menu->add_action(GAction::create("5 sec", [&](auto&) { refresh_timer->restart(5000); })); menubar->add_menu(move(frequency_menu)); diff --git a/Applications/Terminal/TerminalWidget.cpp b/Applications/Terminal/TerminalWidget.cpp index 1ab140e603..83d2a44b4a 100644 --- a/Applications/Terminal/TerminalWidget.cpp +++ b/Applications/Terminal/TerminalWidget.cpp @@ -25,6 +25,9 @@ TerminalWidget::TerminalWidget(int ptm_fd, RefPtr config) , m_notifier(ptm_fd, CNotifier::Read) , m_config(move(config)) { + m_cursor_blink_timer = CTimer::create(); + m_visual_beep_timer = CTimer::create(); + set_frame_shape(FrameShape::Container); set_frame_shadow(FrameShadow::Sunken); set_frame_thickness(2); @@ -36,10 +39,10 @@ TerminalWidget::TerminalWidget(int ptm_fd, RefPtr config) }; dbgprintf("Terminal: Load config file from %s\n", m_config->file_name().characters()); - m_cursor_blink_timer.set_interval(m_config->read_num_entry("Text", + m_cursor_blink_timer->set_interval(m_config->read_num_entry("Text", "CursorBlinkInterval", 500)); - m_cursor_blink_timer.on_timeout = [this] { + m_cursor_blink_timer->on_timeout = [this] { m_cursor_blink_state = !m_cursor_blink_state; update_cursor(); }; @@ -103,10 +106,10 @@ void TerminalWidget::event(CEvent& 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(); + m_cursor_blink_timer->stop(); } else { m_cursor_blink_state = true; - m_cursor_blink_timer.start(); + m_cursor_blink_timer->start(); } invalidate_cursor(); update(); @@ -117,9 +120,9 @@ void TerminalWidget::event(CEvent& event) void TerminalWidget::keydown_event(GKeyEvent& event) { // Reset timer so cursor doesn't blink while typing. - m_cursor_blink_timer.stop(); + m_cursor_blink_timer->stop(); m_cursor_blink_state = true; - m_cursor_blink_timer.start(); + m_cursor_blink_timer->start(); switch (event.key()) { case KeyCode::Key_Up: @@ -196,7 +199,7 @@ void TerminalWidget::paint_event(GPaintEvent& event) painter.add_clip_rect(event.rect()); - if (m_visual_beep_timer.is_active()) + if (m_visual_beep_timer->is_active()) painter.fill_rect(frame_inner_rect(), Color::Red); else painter.fill_rect(frame_inner_rect(), Color(Color::Black).with_alpha(m_opacity)); @@ -223,7 +226,7 @@ void TerminalWidget::paint_event(GPaintEvent& event) continue; auto& line = line_for_visual_row(row); bool has_only_one_background_color = line.has_only_one_background_color(); - if (m_visual_beep_timer.is_active()) + if (m_visual_beep_timer->is_active()) painter.fill_rect(row_rect, Color::Red); else if (has_only_one_background_color) painter.fill_rect(row_rect, lookup_color(line.attributes[0].background_color).with_alpha(m_opacity)); @@ -563,9 +566,9 @@ void TerminalWidget::beep() sysbeep(); return; } - m_visual_beep_timer.restart(200); - m_visual_beep_timer.set_single_shot(true); - m_visual_beep_timer.on_timeout = [this] { + m_visual_beep_timer->restart(200); + m_visual_beep_timer->set_single_shot(true); + m_visual_beep_timer->on_timeout = [this] { force_repaint(); }; force_repaint(); diff --git a/Applications/Terminal/TerminalWidget.h b/Applications/Terminal/TerminalWidget.h index f9bb0cd421..b5caa841ef 100644 --- a/Applications/Terminal/TerminalWidget.h +++ b/Applications/Terminal/TerminalWidget.h @@ -96,8 +96,8 @@ private: int m_glyph_width { 0 }; - CTimer m_cursor_blink_timer; - CTimer m_visual_beep_timer; + ObjectPtr m_cursor_blink_timer; + ObjectPtr m_visual_beep_timer; RefPtr m_config; GScrollBar* m_scrollbar { nullptr }; diff --git a/Demos/WidgetGallery/main.cpp b/Demos/WidgetGallery/main.cpp index 99b22303b0..060a0d3f7c 100755 --- a/Demos/WidgetGallery/main.cpp +++ b/Demos/WidgetGallery/main.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) button2->set_enabled(false); auto* progress1 = new GProgressBar(main_widget); - new CTimer(100, [progress1] { + auto timer = CTimer::create(100, [progress1] { progress1->set_value(progress1->value() + 1); if (progress1->value() == progress1->max()) progress1->set_value(progress1->min()); diff --git a/Games/Minesweeper/Field.cpp b/Games/Minesweeper/Field.cpp index 8278867d19..21870f55ef 100644 --- a/Games/Minesweeper/Field.cpp +++ b/Games/Minesweeper/Field.cpp @@ -101,11 +101,12 @@ Field::Field(GLabel& flag_label, GLabel& time_label, GButton& face_button, GWidg , m_on_size_changed(move(on_size_changed)) { srand(time(nullptr)); - m_timer.on_timeout = [this] { + m_timer = CTimer::create(); + m_timer->on_timeout = [this] { ++m_time_elapsed; m_time_label.set_text(String::format("%u.%u", m_time_elapsed / 10, m_time_elapsed % 10)); }; - m_timer.set_interval(100); + m_timer->set_interval(100); set_frame_thickness(2); set_frame_shape(FrameShape::Container); set_frame_shadow(FrameShadow::Sunken); @@ -187,7 +188,7 @@ void Field::reset() m_time_label.set_text("0"); m_flags_left = m_mine_count; m_flag_label.set_text(String::number(m_flags_left)); - m_timer.stop(); + m_timer->stop(); set_greedy_for_hits(false); set_face(Face::Default); @@ -325,8 +326,8 @@ void Field::on_square_clicked_impl(Square& square, bool should_flood_fill) return; if (square.is_considering) return; - if (!m_timer.is_active()) - m_timer.start(); + if (!m_timer->is_active()) + m_timer->start(); update(); square.is_swept = true; square.button->set_visible(false); @@ -417,7 +418,7 @@ void Field::on_square_middle_clicked(Square& square) void Field::win() { - m_timer.stop(); + m_timer->stop(); set_greedy_for_hits(true); set_face(Face::Good); for_each_square([&](auto& square) { @@ -429,7 +430,7 @@ void Field::win() void Field::game_over() { - m_timer.stop(); + m_timer->stop(); set_greedy_for_hits(true); set_face(Face::Bad); reveal_mines(); diff --git a/Games/Minesweeper/Field.h b/Games/Minesweeper/Field.h index 0c01a02572..e976d26189 100644 --- a/Games/Minesweeper/Field.h +++ b/Games/Minesweeper/Field.h @@ -95,7 +95,7 @@ private: GButton& m_face_button; GLabel& m_flag_label; GLabel& m_time_label; - CTimer m_timer; + ObjectPtr m_timer; int m_time_elapsed { 0 }; int m_flags_left { 0 }; Face m_face { Face::Default }; diff --git a/Libraries/LibCore/CTimer.h b/Libraries/LibCore/CTimer.h index 3abb54d6f6..611dd37788 100644 --- a/Libraries/LibCore/CTimer.h +++ b/Libraries/LibCore/CTimer.h @@ -2,12 +2,21 @@ #include #include +#include class CTimer final : public CObject { C_OBJECT(CTimer) public: - explicit CTimer(CObject* parent = nullptr); - CTimer(int interval, Function&& timeout_handler, CObject* parent = nullptr); + static ObjectPtr create(CObject* parent = nullptr) + { + return new CTimer(parent); + } + + static ObjectPtr create(int interval, Function&& timeout_handler, CObject* parent = nullptr) + { + return new CTimer(interval, move(timeout_handler), parent); + } + virtual ~CTimer() override; void start(); @@ -31,6 +40,9 @@ public: Function on_timeout; private: + explicit CTimer(CObject* parent = nullptr); + CTimer(int interval, Function&& timeout_handler, CObject* parent = nullptr); + virtual void timer_event(CTimerEvent&) override; bool m_active { false }; diff --git a/Libraries/LibGUI/GAbstractButton.cpp b/Libraries/LibGUI/GAbstractButton.cpp index 002d7311ae..150d9b75e9 100644 --- a/Libraries/LibGUI/GAbstractButton.cpp +++ b/Libraries/LibGUI/GAbstractButton.cpp @@ -9,9 +9,9 @@ GAbstractButton::GAbstractButton(GWidget* parent) GAbstractButton::GAbstractButton(const StringView& text, GWidget* parent) : GWidget(parent) , m_text(text) - , m_auto_repeat_timer(this) { - m_auto_repeat_timer.on_timeout = [this] { + m_auto_repeat_timer = CTimer::create(this); + m_auto_repeat_timer->on_timeout = [this] { click(); }; } @@ -71,9 +71,9 @@ void GAbstractButton::mousemove_event(GMouseEvent& event) m_being_pressed = being_pressed; if (m_auto_repeat_interval) { if (!m_being_pressed) - m_auto_repeat_timer.stop(); + m_auto_repeat_timer->stop(); else - m_auto_repeat_timer.start(m_auto_repeat_interval); + m_auto_repeat_timer->start(m_auto_repeat_interval); } update(); } @@ -94,7 +94,7 @@ void GAbstractButton::mousedown_event(GMouseEvent& event) if (m_auto_repeat_interval) { click(); - m_auto_repeat_timer.start(m_auto_repeat_interval); + m_auto_repeat_timer->start(m_auto_repeat_interval); } } } @@ -107,8 +107,8 @@ void GAbstractButton::mouseup_event(GMouseEvent& event) dbgprintf("GAbstractButton::mouse_up_event: x=%d, y=%d, button=%u\n", event.x(), event.y(), (unsigned)event.button()); #endif if (event.button() == GMouseButton::Left) { - bool was_auto_repeating = m_auto_repeat_timer.is_active(); - m_auto_repeat_timer.stop(); + bool was_auto_repeating = m_auto_repeat_timer->is_active(); + m_auto_repeat_timer->stop(); if (is_enabled()) { bool was_being_pressed = m_being_pressed; m_being_pressed = false; diff --git a/Libraries/LibGUI/GAbstractButton.h b/Libraries/LibGUI/GAbstractButton.h index b9ccfd044b..266cff6b4b 100644 --- a/Libraries/LibGUI/GAbstractButton.h +++ b/Libraries/LibGUI/GAbstractButton.h @@ -61,7 +61,7 @@ private: bool m_exclusive { false }; int m_auto_repeat_interval { 0 }; - CTimer m_auto_repeat_timer; + ObjectPtr m_auto_repeat_timer; }; template<> diff --git a/Libraries/LibGUI/GScrollBar.cpp b/Libraries/LibGUI/GScrollBar.cpp index 432383f7c3..dd57396306 100644 --- a/Libraries/LibGUI/GScrollBar.cpp +++ b/Libraries/LibGUI/GScrollBar.cpp @@ -60,8 +60,8 @@ static CharacterBitmap* s_right_arrow_bitmap; GScrollBar::GScrollBar(Orientation orientation, GWidget* parent) : GWidget(parent) , m_orientation(orientation) - , m_automatic_scrolling_timer(this) { + m_automatic_scrolling_timer = CTimer::create(this); if (!s_up_arrow_bitmap) s_up_arrow_bitmap = &CharacterBitmap::create_from_ascii(s_up_arrow_bitmap_data, 9, 9).leak_ref(); if (!s_down_arrow_bitmap) @@ -77,8 +77,8 @@ GScrollBar::GScrollBar(Orientation orientation, GWidget* parent) set_preferred_size(0, 15); } - m_automatic_scrolling_timer.set_interval(100); - m_automatic_scrolling_timer.on_timeout = [this] { + m_automatic_scrolling_timer->set_interval(100); + m_automatic_scrolling_timer->on_timeout = [this] { on_automatic_scrolling_timer_fired(); }; } @@ -293,9 +293,9 @@ void GScrollBar::set_automatic_scrolling_active(bool active) { if (active) { on_automatic_scrolling_timer_fired(); - m_automatic_scrolling_timer.start(); + m_automatic_scrolling_timer->start(); } else { - m_automatic_scrolling_timer.stop(); + m_automatic_scrolling_timer->stop(); } } diff --git a/Libraries/LibGUI/GScrollBar.h b/Libraries/LibGUI/GScrollBar.h index e17014ebb8..ad81d2a8b8 100644 --- a/Libraries/LibGUI/GScrollBar.h +++ b/Libraries/LibGUI/GScrollBar.h @@ -82,5 +82,5 @@ private: }; AutomaticScrollingDirection m_automatic_scrolling_direction { AutomaticScrollingDirection::None }; - CTimer m_automatic_scrolling_timer; + ObjectPtr m_automatic_scrolling_timer; }; diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 5eafc330e2..3e78f80e0d 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -31,29 +31,30 @@ WallpaperMode mode_to_enum(const String& name) } WSCompositor::WSCompositor() - : m_compose_timer(this) - , m_immediate_compose_timer(this) { + m_compose_timer = CTimer::create(this); + m_immediate_compose_timer = CTimer::create(this); + m_screen_can_set_buffer = WSScreen::the().can_set_buffer(); init_bitmaps(); - m_compose_timer.on_timeout = [=]() { + m_compose_timer->on_timeout = [&]() { #if defined(COMPOSITOR_DEBUG) dbgprintf("WSCompositor: delayed frame callback: %d rects\n", m_dirty_rects.size()); #endif compose(); }; - m_compose_timer.set_single_shot(true); - m_compose_timer.set_interval(1000 / 60); - m_immediate_compose_timer.on_timeout = [=]() { + m_compose_timer->set_single_shot(true); + m_compose_timer->set_interval(1000 / 60); + m_immediate_compose_timer->on_timeout = [=]() { #if defined(COMPOSITOR_DEBUG) dbgprintf("WSCompositor: immediate frame callback: %d rects\n", m_dirty_rects.size()); #endif compose(); }; - m_immediate_compose_timer.set_single_shot(true); - m_immediate_compose_timer.set_interval(0); + m_immediate_compose_timer->set_single_shot(true); + m_immediate_compose_timer->set_interval(0); } void WSCompositor::init_bitmaps() @@ -248,12 +249,12 @@ void WSCompositor::invalidate(const Rect& a_rect) // We delay composition by a timer interval, but to not affect latency too // much, if a pending compose is not already scheduled, we also schedule an // immediate compose the next spin of the event loop. - if (!m_compose_timer.is_active()) { + if (!m_compose_timer->is_active()) { #if defined(COMPOSITOR_DEBUG) dbgprintf("Invalidated (starting immediate frame): %dx%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); #endif - m_compose_timer.start(); - m_immediate_compose_timer.start(); + m_compose_timer->start(); + m_immediate_compose_timer->start(); } else { #if defined(COMPOSITOR_DEBUG) dbgprintf("Invalidated (frame callback pending): %dx%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); diff --git a/Servers/WindowServer/WSCompositor.h b/Servers/WindowServer/WSCompositor.h index cfbcf09270..7e82bd5a7b 100644 --- a/Servers/WindowServer/WSCompositor.h +++ b/Servers/WindowServer/WSCompositor.h @@ -46,8 +46,8 @@ private: unsigned m_compose_count { 0 }; unsigned m_flush_count { 0 }; - CTimer m_compose_timer; - CTimer m_immediate_compose_timer; + ObjectPtr m_compose_timer; + ObjectPtr m_immediate_compose_timer; bool m_flash_flush { false }; bool m_buffers_are_flipped { false }; bool m_screen_can_set_buffer { false }; diff --git a/Servers/WindowServer/WSMenuManager.cpp b/Servers/WindowServer/WSMenuManager.cpp index 8fb805cba1..cbdf2e84fc 100644 --- a/Servers/WindowServer/WSMenuManager.cpp +++ b/Servers/WindowServer/WSMenuManager.cpp @@ -10,7 +10,7 @@ WSMenuManager::WSMenuManager() { m_username = getlogin(); - new CTimer(300, [this] { + m_timer = CTimer::create(300, [this] { static time_t last_update_time; time_t now = time(nullptr); if (now != last_update_time || m_cpu_monitor.is_dirty()) { diff --git a/Servers/WindowServer/WSMenuManager.h b/Servers/WindowServer/WSMenuManager.h index dab4717720..32e3e40f79 100644 --- a/Servers/WindowServer/WSMenuManager.h +++ b/Servers/WindowServer/WSMenuManager.h @@ -2,6 +2,7 @@ #include "WSMenu.h" #include +#include #include #include @@ -32,6 +33,7 @@ private: OwnPtr m_window; WSCPUMonitor m_cpu_monitor; String m_username; + ObjectPtr m_timer; Vector> m_open_menu_stack; };