#include "ui_cpu.h" #define RGB_VALID(x) ((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)) #define BAR_HEIGHT 15 typedef enum { COLOR_FG = 0xff2f99ff, COLOR_BG = 0xff202020, COLOR_0 = 0xff57bb8a, COLOR_5 = 0xff63b682, COLOR_10 = 0xff73b87e, COLOR_15 = 0xff84bb7b, COLOR_20 = 0xff94bd77, COLOR_25 = 0xffa4c073, COLOR_30 = 0xffb0be6e, COLOR_35 = 0xffc4c56d, COLOR_40 = 0xffd4c86a, COLOR_45 = 0xffe2c965, COLOR_50 = 0xfff5ce62, COLOR_55 = 0xfff3c563, COLOR_60 = 0xffe9b861, COLOR_65 = 0xffe6ad61, COLOR_70 = 0xffecac67, COLOR_75 = 0xffe9a268, COLOR_80 = 0xffe79a69, COLOR_85 = 0xffe5926b, COLOR_90 = 0xffe2886c, COLOR_95 = 0xffe0816d, COLOR_100 = 0xffdd776e, } Colors; static int _core_color(int percent) { if (percent >= 100) return COLOR_100; if (percent >= 95) return COLOR_95; if (percent >= 90) return COLOR_90; if (percent >= 85) return COLOR_85; if (percent >= 80) return COLOR_80; if (percent >= 75) return COLOR_75; if (percent >= 70) return COLOR_70; if (percent >= 65) return COLOR_65; if (percent >= 60) return COLOR_60; if (percent >= 55) return COLOR_55; if (percent >= 50) return COLOR_50; if (percent >= 45) return COLOR_45; if (percent >= 40) return COLOR_40; if (percent >= 35) return COLOR_35; if (percent >= 30) return COLOR_30; if (percent >= 25) return COLOR_25; if (percent >= 20) return COLOR_20; if (percent >= 15) return COLOR_15; if (percent >= 10) return COLOR_10; if (percent >= 5) return COLOR_5; return COLOR_0; } typedef struct { Ui *ui; Ecore_Animator *animator; Evas_Object *bg; Evas_Object *line; Evas_Object *obj; Evas_Object *colors; Eina_Bool redraw; int cpu_count; Eina_List *cores; Eina_Bool show_cpufreq; // Have cpu scaling Eina_Bool cpu_freq; int freq_min; int freq_max; int pos; double step; } Animate; typedef struct { int id; int freq; int percent; } Core; static int _core_alpha(int percent, int fr, int fr_max, int fr_min) { int r, g, b, a; int color; color = _core_color(percent); r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = (color & 0xff); a = 0xff; if (fr) { int rng, n; rng = fr_max - fr_min; n = fr - fr_min; double fade = (100.0 - ((n * 100) / rng)) / 100.0; r = (percent / 100.0) * 0xff; b = fade * 0xff; r = RGB_VALID(r); b = RGB_VALID(b); } color = (a << 24) + (r << 16) + (g << 8) + b; return color; } static void _core_times_cb(void *data, Ecore_Thread *thread) { Animate *ad; int ncpu; ad = data; if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max)) ad->cpu_freq = EINA_TRUE; while (!ecore_thread_check(thread)) { cpu_core_t **cores = system_cpu_usage_delayed_get(&ncpu, 100000); for (int n = 0; n < ncpu; n++) { // Copy our core state data to the animator. Core *core = eina_list_nth(ad->cores, n); if (core) { core->percent = cores[n]->percent; if (ad->cpu_freq) core->freq = system_cpu_n_frequency_get(n); } free(cores[n]); } free(cores); } } static void _win_del_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Animate *ad = data; Ui *ui = ad->ui; Core *core; ecore_animator_del(ad->animator); ecore_thread_cancel(ui->thread_cpu); ecore_thread_wait(ui->thread_cpu, 0.2); EINA_LIST_FREE(ad->cores, core) { free(core); } free(ad); evas_object_del(obj); ui->win_cpu = NULL; } static void _reset(Animate *ad) { ad->pos = ad->step = 0; } static Eina_Bool _bg_fill(Animate *ad) { uint32_t *pixels; Evas_Coord x, y, w, h; if (ecore_thread_check(ad->ui->thread_cpu)) return EINA_FALSE; evas_object_geometry_get(ad->bg, NULL, NULL, &w, &h); pixels = evas_object_image_data_get(ad->obj, EINA_TRUE); if (!pixels) return EINA_FALSE; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { *(pixels++) = COLOR_BG; } } ad->redraw = EINA_FALSE; return EINA_TRUE; } static Eina_Bool _animate(void *data) { uint32_t *pixels; Evas_Object *line, *obj, *bg; Evas_Coord x, y, w, h; Animate *ad = data; if (ecore_thread_check(ad->ui->thread_cpu)) return EINA_FALSE; bg = ad->bg; line = ad->line; obj = ad->obj; evas_object_geometry_get(bg, &x, &y, &w, &h); int rem = h % ad->cpu_count; h -= rem; evas_object_image_size_set(obj, w, h); evas_object_resize(bg, w, h); evas_object_image_data_update_add(obj, 0, 0, w, h); evas_object_geometry_get(obj, NULL, NULL, NULL, &h); evas_object_move(line, x + w - ad->pos, y); evas_object_resize(line, 1, h); evas_object_show(line); if (ad->redraw) { _bg_fill(ad); return EINA_TRUE; } pixels = evas_object_image_data_get(obj, EINA_TRUE); if (!pixels) return EINA_TRUE; int block = h / ad->cpu_count; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { int n = y / block; Core *core = eina_list_nth(ad->cores, n); if (core && x == (w - ad->pos)) { if (ad->show_cpufreq && ad->cpu_freq) *(pixels) = _core_alpha(core->percent, core->freq, ad->freq_min, ad->freq_max); else *(pixels) = _core_color(core->percent); } pixels++; } } ad->step += (double) (w * ecore_animator_frametime_get()) / 60.0; ad->pos = ad->step; if (ad->pos >= w) _reset(ad); return EINA_TRUE; } static void _anim_resize_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Evas_Coord w, h, x, y; uint32_t *pixels; Animate *ad = data; ad->redraw = EINA_TRUE; _reset(ad); evas_object_hide(ad->line); // Update our color guide. h = BAR_HEIGHT * elm_config_scale_get(); evas_object_size_hint_min_set(ad->colors, -1, h); evas_object_geometry_get(ad->bg, NULL, NULL, &w, NULL); evas_object_image_size_set(ad->colors, w, h); evas_object_image_data_update_add(ad->colors, 0, 0, w, h); pixels = evas_object_image_data_get(ad->colors, EINA_TRUE); if (!pixels) return; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { int n = (100.0 / w) * x; *(pixels++) = _core_alpha(n, 0, 0, 0); } } } static void _anim_move_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Animate *ad = data; evas_object_hide(ad->line); } static void _options_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Evas_Object *fr = obj; elm_frame_collapse_go(fr, !elm_frame_collapse_get(fr)); } static void _check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Animate *ad = data; ad->show_cpufreq = elm_check_state_get(obj); } static void _graph(Ui *ui, Evas_Object *parent) { Evas_Object *frame, *tbl, *box, *bg, *obj, *line; Evas_Object *fr, *hbx, *bx, *colors, *check; int n; box = parent; n = system_cpu_online_count_get(); frame = elm_frame_add(box); evas_object_size_hint_align_set(frame, FILL, FILL); evas_object_size_hint_weight_set(frame, EXPAND, EXPAND); evas_object_show(frame); if (n > 1) elm_object_text_set(frame, eina_slstr_printf(_("%d CPU Cores Available"), n)); else elm_object_text_set(frame, _("ONE CPU CORE...MAKE IT COUNT!!!")); tbl = elm_table_add(box); evas_object_size_hint_align_set(tbl, FILL, FILL); evas_object_size_hint_weight_set(tbl, EXPAND, EXPAND); evas_object_show(tbl); bg = evas_object_rectangle_add(evas_object_evas_get(box)); evas_object_size_hint_align_set(bg, FILL, FILL); evas_object_size_hint_weight_set(bg, EXPAND, EXPAND); evas_object_show(bg); line = evas_object_rectangle_add(evas_object_evas_get(bg)); evas_object_size_hint_align_set(line, FILL, FILL); evas_object_size_hint_weight_set(line, EXPAND, EXPAND); evas_object_color_set(line, 255, 47, 153, 255); evas_object_size_hint_max_set(line, 1, -1); evas_object_show(line); obj = evas_object_image_add(evas_object_evas_get(bg)); evas_object_size_hint_align_set(obj, FILL, FILL); evas_object_size_hint_weight_set(obj, EXPAND, EXPAND); evas_object_image_filled_set(obj, EINA_TRUE); evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_ARGB8888); evas_object_show(obj); elm_table_pack(tbl, bg, 0, 0, 1, 1); elm_table_pack(tbl, obj, 0, 0, 1, 1); elm_table_pack(tbl, line, 0, 0, 1, 1); bx = elm_box_add(box); evas_object_size_hint_align_set(bx, FILL, FILL); evas_object_size_hint_weight_set(bx, EXPAND, EXPAND); evas_object_show(bx); elm_box_pack_end(bx, tbl); // Set the main content. elm_object_content_set(frame, bx); elm_box_pack_end(box, frame); hbx = elm_box_add(box); evas_object_size_hint_align_set(hbx, FILL, FILL); evas_object_size_hint_weight_set(hbx, EXPAND, 0); elm_box_horizontal_set(hbx, 1); evas_object_show(hbx); fr = elm_frame_add(box); evas_object_size_hint_align_set(fr, FILL, FILL); evas_object_size_hint_weight_set(fr, EXPAND, 0); evas_object_show(fr); elm_object_text_set(fr, _("Increasing %")); elm_object_content_set(fr, hbx); colors = evas_object_image_add(evas_object_evas_get(fr)); evas_object_size_hint_align_set(colors, FILL, FILL); evas_object_size_hint_weight_set(colors, EXPAND, EXPAND); evas_object_image_filled_set(colors, EINA_TRUE); evas_object_image_colorspace_set(colors, EVAS_COLORSPACE_ARGB8888); evas_object_show(colors); elm_box_pack_end(hbx, colors); elm_box_pack_end(box, fr); fr = elm_frame_add(box); evas_object_size_hint_align_set(fr, FILL, FILL); evas_object_size_hint_weight_set(fr, EXPAND, 0); evas_object_show(fr); elm_object_text_set(fr, _("Options")); elm_frame_collapse_set(fr, 0); evas_object_smart_callback_add(fr, "clicked", _options_clicked_cb, NULL); elm_box_pack_end(box, fr); check = elm_check_add(fr); evas_object_size_hint_align_set(check, FILL, FILL); evas_object_size_hint_weight_set(check, EXPAND, 0); elm_object_text_set(check, _("Overlay CPU frequency?")); evas_object_show(check); elm_object_content_set(fr, check); Animate *ad = calloc(1, sizeof(Animate)); if (!ad) return; ad->bg = bg; ad->obj = obj; ad->line = line; ad->ui = ui; ad->redraw = EINA_TRUE; ad->cpu_count = system_cpu_online_count_get(); ad->colors = colors; for (int i = 0; i < ad->cpu_count; i++) { Core *core = calloc(1, sizeof(Core)); if (core) { core->id = i; ad->cores = eina_list_append(ad->cores, core); } } // Enough space for our CPUs cores. evas_object_size_hint_min_set(bg, 1, (BAR_HEIGHT * ad->cpu_count) * elm_config_scale_get()); evas_object_smart_callback_add(check, "changed", _check_changed_cb, ad); evas_object_smart_callback_add(tbl, "resize", _anim_resize_cb, ad); evas_object_smart_callback_add(tbl, "move", _anim_move_cb, ad); evas_object_smart_callback_add(ui->win_cpu, "delete,request", _win_del_cb, ad); ad->animator = ecore_animator_add(_animate, ad); ui->thread_cpu = ecore_thread_run(_core_times_cb, NULL, NULL, ad); } void ui_win_cpu_add(Ui *ui) { Evas_Object *win, *box, *scroller; if (ui->win_cpu) return; ui->win_cpu = win = elm_win_util_standard_add("evisum", _("CPU Usage")); evas_object_size_hint_weight_set(win, EXPAND, EXPAND); evas_object_size_hint_align_set(win, FILL, FILL); evisum_ui_background_random_add(win, evisum_ui_effects_enabled_get()); scroller = elm_scroller_add(win); evas_object_size_hint_weight_set(scroller, EXPAND, EXPAND); evas_object_size_hint_align_set(scroller, FILL, FILL); elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); evas_object_show(scroller); box = elm_box_add(win); evas_object_size_hint_align_set(box, FILL, FILL); evas_object_size_hint_weight_set(box, EXPAND, EXPAND); evas_object_show(box); _graph(ui, box); elm_object_content_set(scroller, box); elm_object_content_set(win, scroller); evisum_child_window_show(ui->win, win); }