diff --git a/AK/CircularQueue.h b/AK/CircularQueue.h index acb91216b9..0dc39afdec 100644 --- a/AK/CircularQueue.h +++ b/AK/CircularQueue.h @@ -5,25 +5,25 @@ namespace AK { -template +template class CircularQueue { public: CircularQueue() { - for (size_t i = 0; i < Capacity; ++i) + for (int i = 0; i < Capacity; ++i) m_elements[i] = T(); } bool is_empty() const { return !m_size; } - size_t size() const { return m_size; } + int size() const { return m_size; } - size_t capacity() const { return Capacity; } + int capacity() const { return Capacity; } void dump() const { kprintf("CircularQueue<%zu>:\n", Capacity); kprintf(" size: %zu\n", m_size); - for (size_t i = 0; i < Capacity; ++i) { + for (int i = 0; i < Capacity; ++i) { kprintf(" [%zu] %d %c\n", i, m_elements[i], i == m_head ? '*' : ' '); } } @@ -60,9 +60,9 @@ public: const T& operator*() const { return m_queue.m_elements[m_index]; } private: friend class CircularQueue; - ConstIterator(const CircularQueue& queue, const size_t index) : m_queue(queue), m_index(index) { } + ConstIterator(const CircularQueue& queue, const int index) : m_queue(queue), m_index(index) { } const CircularQueue& m_queue; - size_t m_index { 0 }; + int m_index { 0 }; }; ConstIterator begin() const { return ConstIterator(*this, m_head); } @@ -71,8 +71,8 @@ public: private: friend class ConstIterator; T m_elements[Capacity]; - size_t m_size { 0 }; - size_t m_head { 0 }; + int m_size { 0 }; + int m_head { 0 }; }; } diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index 9895fb1f8f..cb1d88f0ec 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -232,7 +232,7 @@ WSWindowManager::WSWindowManager() static time_t last_update_time; time_t now = time(nullptr); if (now != last_update_time) { - invalidate(menubar_rect()); + tick_clock(); last_update_time = now; } }); @@ -245,6 +245,55 @@ WSWindowManager::~WSWindowManager() { } +static void get_cpu_usage(unsigned& busy, unsigned& idle) +{ + busy = 0; + idle = 0; + + FILE* fp = fopen("/proc/all", "r"); + if (!fp) { + perror("failed to open /proc/all"); + exit(1); + } + for (;;) { + char buf[BUFSIZ]; + char* ptr = fgets(buf, sizeof(buf), fp); + if (!ptr) + break; + auto parts = String(buf, Chomp).split(','); + if (parts.size() < 17) + break; + bool ok; + pid_t pid = parts[0].to_uint(ok); + ASSERT(ok); + unsigned nsched = parts[1].to_uint(ok); + ASSERT(ok); + + if (pid == 0) + idle += nsched; + else + busy += nsched; + } + int rc = fclose(fp); + ASSERT(rc == 0); +} + +void WSWindowManager::tick_clock() +{ + static unsigned last_busy; + static unsigned last_idle; + unsigned busy; + unsigned idle; + get_cpu_usage(busy, idle); + unsigned busy_diff = busy - last_busy; + unsigned idle_diff = idle - last_idle; + last_busy = busy; + last_idle = idle; + float cpu = (float)busy_diff / (float)(busy_diff + idle_diff); + m_cpu_history.enqueue(cpu); + invalidate(menubar_rect()); +} + void WSWindowManager::set_resolution(int width, int height) { if (m_screen_rect.width() == width && m_screen_rect.height() == height) @@ -866,6 +915,18 @@ void WSWindowManager::draw_menubar() tm->tm_sec); auto time_rect = menubar_rect().translated(-(menubar_menu_margin() / 2), 0); m_back_painter->draw_text(time_rect, time_text, TextAlignment::CenterRight, Color::Black); + + Rect cpu_rect { time_rect.right() - font().glyph_width() * time_text.length() - (int)m_cpu_history.capacity() - 10, time_rect.y() + 1, (int)m_cpu_history.capacity(), time_rect.height() - 2 }; + m_back_painter->fill_rect(cpu_rect, Color::Black); + int i = m_cpu_history.capacity() - m_cpu_history.size(); + for (auto cpu_usage : m_cpu_history) { + m_back_painter->draw_line( + { cpu_rect.x() + i, cpu_rect.bottom() }, + { cpu_rect.x() + i, (int)(cpu_rect.y() + (cpu_rect.height() - (cpu_usage * (float)cpu_rect.height()))) }, + Color(0, 200, 0) + ); + ++i; + } } void WSWindowManager::draw_cursor() diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index cacc113b0e..9ac5db19ae 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -11,6 +11,7 @@ #include "WSMessageReceiver.h" #include "WSMenuBar.h" #include +#include class WSAPIClientRequest; class WSScreen; @@ -79,7 +80,6 @@ private: void handle_close_button_mouse_event(WSWindow&, WSMouseEvent&); void start_window_resize(WSWindow&, WSMouseEvent&); void handle_client_request(WSAPIClientRequest&); - void set_active_window(WSWindow*); void set_hovered_window(WSWindow*); template IterationDecision for_each_visible_window_of_type_from_back_to_front(WSWindowType, Callback); @@ -88,12 +88,11 @@ private: template IterationDecision for_each_visible_window_from_back_to_front(Callback); template void for_each_active_menubar_menu(Callback); void close_current_menu(); - virtual void on_message(WSMessage&) override; - void compose(); void paint_window_frame(WSWindow&); void flip_buffers(); + void tick_clock(); WSScreen& m_screen; Rect m_screen_rect; @@ -155,4 +154,6 @@ private: Color m_menu_selection_color; WeakPtr m_current_menubar; WeakPtr m_current_menu; + + CircularQueue m_cpu_history; };