
Now that the "unix" pledge is no longer required for socket I/O, we can drop it after making the connections we need in a program. In most GUI program cases, once we've connected to the WindowServer by instantiating a GApplication, we no longer need "unix" :^)
95 lines
2.5 KiB
C++
95 lines
2.5 KiB
C++
#include <AK/CircularQueue.h>
|
|
#include <LibCore/CProcessStatisticsReader.h>
|
|
#include <LibDraw/Palette.h>
|
|
#include <LibGUI/GApplication.h>
|
|
#include <LibGUI/GPainter.h>
|
|
#include <LibGUI/GWidget.h>
|
|
#include <LibGUI/GWindow.h>
|
|
#include <stdio.h>
|
|
|
|
class GraphWidget final : public GWidget {
|
|
C_OBJECT(GraphWidget)
|
|
public:
|
|
GraphWidget()
|
|
: GWidget(nullptr)
|
|
{
|
|
start_timer(1000);
|
|
}
|
|
|
|
virtual ~GraphWidget() override {}
|
|
|
|
private:
|
|
virtual void timer_event(CTimerEvent&) override
|
|
{
|
|
unsigned busy;
|
|
unsigned idle;
|
|
get_cpu_usage(busy, idle);
|
|
unsigned busy_diff = busy - m_last_busy;
|
|
unsigned idle_diff = idle - m_last_idle;
|
|
m_last_busy = busy;
|
|
m_last_idle = idle;
|
|
float cpu = (float)busy_diff / (float)(busy_diff + idle_diff);
|
|
m_cpu_history.enqueue(cpu);
|
|
update();
|
|
}
|
|
|
|
virtual void paint_event(GPaintEvent& event) override
|
|
{
|
|
GPainter painter(*this);
|
|
painter.add_clip_rect(event.rect());
|
|
painter.fill_rect(event.rect(), Color::Black);
|
|
int i = m_cpu_history.capacity() - m_cpu_history.size();
|
|
for (auto cpu_usage : m_cpu_history) {
|
|
painter.draw_line(
|
|
{ i, rect().bottom() },
|
|
{ i, (int)(height() - (cpu_usage * (float)height())) },
|
|
palette().menu_selection());
|
|
++i;
|
|
}
|
|
}
|
|
|
|
static void get_cpu_usage(unsigned& busy, unsigned& idle)
|
|
{
|
|
busy = 0;
|
|
idle = 0;
|
|
|
|
auto all_processes = CProcessStatisticsReader::get_all();
|
|
|
|
for (auto& it : all_processes) {
|
|
for (auto& jt : it.value.threads) {
|
|
if (it.value.pid == 0)
|
|
idle += jt.times_scheduled;
|
|
else
|
|
busy += jt.times_scheduled;
|
|
}
|
|
}
|
|
}
|
|
|
|
CircularQueue<float, 30> m_cpu_history;
|
|
unsigned m_last_busy { 0 };
|
|
unsigned m_last_idle { 0 };
|
|
};
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
if (pledge("stdio shared_buffer rpath unix cpath fattr", nullptr) < 0) {
|
|
perror("pledge");
|
|
return 1;
|
|
}
|
|
|
|
GApplication app(argc, argv);
|
|
|
|
if (pledge("stdio shared_buffer rpath", nullptr) < 0) {
|
|
perror("pledge");
|
|
return 1;
|
|
}
|
|
|
|
auto window = GWindow::construct();
|
|
window->set_window_type(GWindowType::MenuApplet);
|
|
window->resize(30, 16);
|
|
|
|
auto widget = GraphWidget::construct();
|
|
window->set_main_widget(widget);
|
|
window->show();
|
|
return app.exec();
|
|
}
|