diff --git a/src/ui.c b/src/ui.c index a461c49..3a94a9e 100644 --- a/src/ui.c +++ b/src/ui.c @@ -11,15 +11,9 @@ #endif static Eina_Lock _lock; - static results_t *_results = NULL; -static long _memory_total = 0; -static long _memory_used = 0; - -static void _disk_view_update(Ui *ui); -static void _extra_view_update(Ui *ui, results_t *results); -static void _cpu_view_update(Ui *ui, results_t *results); -static void _memory_view_update(Ui *ui, results_t *results); +static long _memory_total = 0, _memory_used = 0; +static Data_Unit _data_unit_current = 0; void ui_shutdown(Ui *ui) @@ -38,7 +32,6 @@ ui_shutdown(Ui *ui) if (ui->thread_process) ecore_thread_wait(ui->thread_process, 1.0); - eina_lock_free(&_lock); ecore_main_loop_quit(); @@ -74,1219 +67,1223 @@ _system_stats_thread(void *data, Ecore_Thread *thread) } } -static void -_system_stats_thread_feedback_cb(void *data, Ecore_Thread *thread, void *msg) +const char * +_data_unit_symbol_get(Data_Unit unit) { - Ui *ui; - results_t *results; - double cpu_usage = 0.0; - int i; - - ui = data; - results = msg; - - if (ecore_thread_check(thread)) - goto out; - - _cpu_view_update(ui, results); - _memory_view_update(ui, results); - _disk_view_update(ui); - _extra_view_update(ui, results); + const char *symbol; - for (i = 0; i < results->cpu_count; i++) + switch (unit) { - cpu_usage += results->cores[i]->percent; - - free(results->cores[i]); - } - - cpu_usage = cpu_usage / results->cpu_count; + case DATA_UNIT_KB: + symbol = "K"; + break; - _memory_total = results->memory.total >>= 10; - _memory_used = results->memory.used >>= 10; + case DATA_UNIT_MB: + symbol = "M"; + break; - elm_progressbar_value_set(ui->progress_cpu, (double)cpu_usage / 100); - elm_progressbar_value_set(ui->progress_mem, (double)((results->memory.total / 100.0) * results->memory.used) / 1000000); + case DATA_UNIT_GB: + symbol = "G"; + break; + } -out: - free(results->cores); - free(results); + return symbol; } -static int -_sort_by_pid(const void *p1, const void *p2) +static unsigned long +_mem_adjust(Data_Unit unit, unsigned long value) { - const Proc_Stats *inf1, *inf2; - - inf1 = p1; inf2 = p2; + if (unit == DATA_UNIT_KB) + { + //FIXME: KB is memory base default. + } + else if (unit == DATA_UNIT_MB) + { + value >>= 10; + } + else if (unit == DATA_UNIT_GB) + { + value >>= 20; + } - return inf1->pid - inf2->pid; + return value; } -static int -_sort_by_uid(const void *p1, const void *p2) +static char * +_progress_mem_format_cb(double val) { - const Proc_Stats *inf1, *inf2; + char buf[1024]; + const char *symbol = _data_unit_symbol_get(_data_unit_current); - inf1 = p1; inf2 = p2; + snprintf(buf, sizeof(buf), "%ld %c out of %ld %c", + _mem_adjust(_data_unit_current, _memory_used), *symbol, + _mem_adjust(_data_unit_current, _memory_total), *symbol); - return inf1->uid - inf2->uid; + return strdup(buf); } -static int -_sort_by_nice(const void *p1, const void *p2) +static void +_progress_mem_format_free_cb(char *str) { - const Proc_Stats *inf1, *inf2; - - inf1 = p1; inf2 = p2; - - return inf1->nice - inf2->nice; + if (str) + free(str); } -static int -_sort_by_pri(const void *p1, const void *p2) +static char * +_progress_incoming_format_cb(double val) { - const Proc_Stats *inf1, *inf2; - - inf1 = p1; inf2 = p2; - - return inf1->priority - inf2->priority; -} + char buf[1024]; + double incoming; + const char *unit = "B/s"; -static int -_sort_by_cpu(const void *p1, const void *p2) -{ - const Proc_Stats *inf1, *inf2; + incoming = _results->incoming; + if (incoming > 1048576) + { + incoming /= 1048576; + unit = "MB/s"; + } + else if (incoming > 1024 && incoming < 1048576) + { + incoming /= 1024; + unit = "KB/s"; + } - inf1 = p1; inf2 = p2; + snprintf(buf, sizeof(buf), "%.2f %s", incoming, unit); - return inf1->cpu_id - inf2->cpu_id; + return strdup(buf); } -static int -_sort_by_threads(const void *p1, const void *p2) +static void +_progress_incoming_format_free_cb(char *str) { - const Proc_Stats *inf1, *inf2; - - inf1 = p1; inf2 = p2; - - return inf1->numthreads - inf2->numthreads; + if (str) + free(str); } -static int -_sort_by_size(const void *p1, const void *p2) +static char * +_progress_outgoing_format_cb(double val) { - const Proc_Stats *inf1, *inf2; - int64_t size1, size2; - - inf1 = p1; inf2 = p2; + char buf[1024]; + double outgoing; + const char *unit = "B/s"; - size1 = inf1->mem_size; - size2 = inf2->mem_size; + outgoing = _results->outgoing; + if (outgoing > 1048576) + { + outgoing /= 1048576; + unit = "MB/s"; + } + else if (outgoing > 1024 && outgoing < 1048576) + { + outgoing /= 1024; + unit = "KB/s"; + } - if (size1 < size2) - return -1; - if (size2 > size1) - return 1; + snprintf(buf, sizeof(buf), "%.2f %s", outgoing, unit); - return 0; + return strdup(buf); } -static int -_sort_by_rss(const void *p1, const void *p2) +static void +_progress_outgoing_format_free_cb(char *str) { - const Proc_Stats *inf1, *inf2; - int64_t size1, size2; - - inf1 = p1; inf2 = p2; - - size1 = inf1->mem_rss; - size2 = inf2->mem_rss; - - if (size1 < size2) - return -1; - if (size2 > size1) - return 1; - - return 0; + if (str) + free(str); } -static int -_sort_by_cpu_usage(const void *p1, const void *p2) +static void +_extra_view_update(Ui *ui, results_t *results) { - const Proc_Stats *inf1, *inf2; - double one, two; + Evas_Object *box, *frame, *progress; + int i; - inf1 = p1; inf2 = p2; + if (!ui->extra_visible) + return; - one = inf1->cpu_usage; - two = inf2->cpu_usage; + _results = results; - if (one < two) - return -1; - if (two > one) - return 1; + elm_box_clear(ui->extra_activity); - return 0; -} + box = elm_box_add(ui->content); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(box); -static int -_sort_by_cmd(const void *p1, const void *p2) -{ - const Proc_Stats *inf1, *inf2; + if (results->power.battery_count) + { + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + if (results->power.have_ac) + elm_object_text_set(frame, "Battery (plugged in)"); + else + elm_object_text_set(frame, "Battery"); - inf1 = p1; inf2 = p2; + evas_object_show(frame); - return strcasecmp(inf1->command, inf2->command); -} + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, "%1.2f%%"); + elm_progressbar_value_set(progress, (double)results->power.percent / 100); + evas_object_show(progress); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); + } -static int -_sort_by_state(const void *p1, const void *p2) -{ - const Proc_Stats *inf1, *inf2; + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(frame, "Network Incoming"); + evas_object_show(frame); - inf1 = p1; inf2 = p2; + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, ""); + elm_progressbar_unit_format_function_set(progress, _progress_incoming_format_cb, _progress_incoming_format_free_cb); - return strcmp(inf1->state, inf2->state); -} + if (results->incoming == 0) + elm_progressbar_value_set(progress, 0); + else + elm_progressbar_value_set(progress, 1.0); -const char * -_data_unit_symbol_get(Data_Unit unit) -{ - const char *symbol; - - switch (unit) - { - case DATA_UNIT_KB: - symbol = "K"; - break; - - case DATA_UNIT_MB: - symbol = "M"; - break; + evas_object_show(progress); - case DATA_UNIT_GB: - symbol = "G"; - break; - } + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); - return symbol; -} + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(frame, "Network Outgoing"); + evas_object_show(frame); -static void -_fields_append(Ui *ui, Proc_Stats *proc) -{ - const char *symbol; - int64_t mem_size, mem_rss; + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, ""); + elm_progressbar_unit_format_function_set(progress, _progress_outgoing_format_cb, _progress_outgoing_format_free_cb); + if (results->outgoing == 0) + elm_progressbar_value_set(progress, 0); + else + elm_progressbar_value_set(progress, 1.0); - if (ui->program_pid == proc->pid) - return; + evas_object_show(progress); - symbol = _data_unit_symbol_get(ui->data_unit); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); - mem_size = proc->mem_size; - mem_rss = proc->mem_rss; + elm_box_pack_end(ui->extra_activity, box); +} - if (ui->data_unit == DATA_UNIT_KB) +static unsigned long +_disk_adjust(Data_Unit unit, unsigned long value) +{ + if (unit == DATA_UNIT_KB) { - mem_size >>= 10; - mem_rss >>= 10; + value >>= 10; } - else if (ui->data_unit == DATA_UNIT_MB) + else if (unit == DATA_UNIT_MB) { - mem_size >>= 20; - mem_rss >>= 20; + value >>= 20; } - else + else if (unit == DATA_UNIT_GB) { - mem_size >>= 30; - mem_rss >>= 30; + value >>= 30; } - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_PID], eina_slstr_printf("%d
", proc->pid), TEXT_FIELD_MAX); - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_UID], eina_slstr_printf("%d
", proc->uid), TEXT_FIELD_MAX); - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_SIZE], eina_slstr_printf("%lld %c
", mem_size, *symbol), TEXT_FIELD_MAX); - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_RSS], eina_slstr_printf("%lld %c
", mem_rss, *symbol), TEXT_FIELD_MAX); - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_COMMAND], eina_slstr_printf("%s
", proc->command), TEXT_FIELD_MAX); - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_STATE], eina_slstr_printf("%s
", proc->state), TEXT_FIELD_MAX); - eina_strlcat(ui->fields[PROCESS_INFO_FIELD_CPU_USAGE], eina_slstr_printf("%.1f%%
", proc->cpu_usage), TEXT_FIELD_MAX); + return value; } static void -_fields_show(Ui *ui) +_ui_disk_add(Ui *ui, const char *path, const char *mount, unsigned long total, unsigned long used) { - elm_object_text_set(ui->entry_pid, ui->fields[PROCESS_INFO_FIELD_PID]); - elm_object_text_set(ui->entry_uid, ui->fields[PROCESS_INFO_FIELD_UID]); - elm_object_text_set(ui->entry_size, ui->fields[PROCESS_INFO_FIELD_SIZE]); - elm_object_text_set(ui->entry_rss, ui->fields[PROCESS_INFO_FIELD_RSS]); - elm_object_text_set(ui->entry_cmd, ui->fields[PROCESS_INFO_FIELD_COMMAND]); - elm_object_text_set(ui->entry_state, ui->fields[PROCESS_INFO_FIELD_STATE]); - elm_object_text_set(ui->entry_cpu_usage, ui->fields[PROCESS_INFO_FIELD_CPU_USAGE]); + Evas_Object *frame, *progress; + const char *symbol; + double ratio, value; + + frame = elm_frame_add(ui->disk_activity); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, 0); + elm_object_text_set(frame, eina_slstr_printf("%s on %s", path, mount)); + evas_object_show(frame); + + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + + symbol = _data_unit_symbol_get(ui->data_unit); + + elm_progressbar_unit_format_set(progress, + eina_slstr_printf( + "%lu%c of %lu%c", + _disk_adjust(ui->data_unit, used), *symbol, + _disk_adjust(ui->data_unit, total), *symbol)); + + elm_object_content_set(frame, progress); + + ratio = total / 100.0; + value = used / ratio; + + if (used == 0 && total == 0) + elm_progressbar_value_set(progress, 1.0); + else + elm_progressbar_value_set(progress, value / 100.0); + + evas_object_show(progress); + + elm_box_pack_end(ui->disk_activity, frame); } static void -_fields_clear(Ui *ui) +_disk_view_update(Ui *ui) { - for (int i = 0; i < PROCESS_INFO_FIELDS; i++) + Eina_List *disks; + char *path; + unsigned long total, used; + + if (!ui->disk_visible) + return; + + elm_box_clear(ui->disk_activity); + + disks = disks_get(); + EINA_LIST_FREE(disks, path) { - ui->fields[i][0] = '\0'; + char *mount = disk_mount_point_get(path); + if (mount) + { + if (disk_usage_get(mount, &total, &used)) + { + _ui_disk_add(ui, path, mount, total, used); + } + free(mount); + } + + free(path); } + if (disks) + free(disks); } static void -_fields_free(Ui *ui) +_memory_view_update(Ui *ui, results_t *results) { - for (int i = 0; i < PROCESS_INFO_FIELDS; i++) - { - free(ui->fields[i]); - } -} + Evas_Object *box, *frame, *progress; + const char *symbol; + double ratio, value; -static Eina_List * -_list_sort(Ui *ui, Eina_List *list) -{ - switch (ui->sort_type) - { - case SORT_BY_NONE: - case SORT_BY_PID: - list = eina_list_sort(list, eina_list_count(list), _sort_by_pid); - break; + if (!ui->mem_visible) + return; - case SORT_BY_UID: - list = eina_list_sort(list, eina_list_count(list), _sort_by_uid); - break; + elm_box_clear(ui->mem_activity); - case SORT_BY_NICE: - list = eina_list_sort(list, eina_list_count(list), _sort_by_nice); - break; + symbol = _data_unit_symbol_get(ui->data_unit); - case SORT_BY_PRI: - list = eina_list_sort(list, eina_list_count(list), _sort_by_pri); - break; + box = elm_box_add(ui->content); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(box); - case SORT_BY_CPU: - list = eina_list_sort(list, eina_list_count(list), _sort_by_cpu); - break; + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(frame, "Memory Used"); + evas_object_show(frame); + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, + eina_slstr_printf( + "%lu %c / %lu %c", + _mem_adjust(ui->data_unit, results->memory.used), *symbol, + _mem_adjust(ui->data_unit, results->memory.total), *symbol)); - case SORT_BY_THREADS: - list = eina_list_sort(list, eina_list_count(list), _sort_by_threads); - break; + ratio = results->memory.total / 100.0; + value = results->memory.used / ratio; + elm_progressbar_value_set(progress, value / 100); + evas_object_show(progress); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); - case SORT_BY_SIZE: - list = eina_list_sort(list, eina_list_count(list), _sort_by_size); - break; + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(frame, "Memory Cached"); + evas_object_show(frame); + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, eina_slstr_printf( + "%lu %c / %lu %c", + _mem_adjust(ui->data_unit, results->memory.cached), *symbol, + _mem_adjust(ui->data_unit, results->memory.total), *symbol)); - case SORT_BY_RSS: - list = eina_list_sort(list, eina_list_count(list), _sort_by_rss); - break; + ratio = results->memory.total / 100.0; + value = results->memory.cached / ratio; + elm_progressbar_value_set(progress, value / 100); + evas_object_show(progress); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); - case SORT_BY_CMD: - list = eina_list_sort(list, eina_list_count(list), _sort_by_cmd); - break; + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(frame, "Memory Buffered"); + evas_object_show(frame); + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, + eina_slstr_printf( + "%lu %c / %lu %c", + _mem_adjust(ui->data_unit, results->memory.buffered), *symbol, + _mem_adjust(ui->data_unit, results->memory.total), *symbol)); - case SORT_BY_STATE: - list = eina_list_sort(list, eina_list_count(list), _sort_by_state); - break; + ratio = results->memory.total / 100.0; + value = results->memory.buffered / ratio; + elm_progressbar_value_set(progress, value / 100); + evas_object_show(progress); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); - case SORT_BY_CPU_USAGE: - list = eina_list_sort(list, eina_list_count(list), _sort_by_cpu_usage); - break; - } + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(frame, "Memory Shared"); + evas_object_show(frame); + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, + eina_slstr_printf( + "%lu %c / %lu %c", + _mem_adjust(ui->data_unit, results->memory.shared), *symbol, + _mem_adjust(ui->data_unit, results->memory.total), *symbol)); - if (ui->sort_reverse) - list = eina_list_reverse(list); + ratio = results->memory.total / 100.0; + value = results->memory.shared / ratio; + elm_progressbar_value_set(progress, value / 100); + evas_object_show(progress); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); - return list; + elm_box_pack_end(ui->mem_activity, box); } static void -_system_process_list_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg EINA_UNUSED) +_cpu_view_update(Ui *ui, results_t *results) { - Ui *ui; - Eina_List *list, *l; - Proc_Stats *proc; + Evas_Object *box, *frame, *progress; + int i; - eina_lock_take(&_lock); + if (!ui->cpu_visible) + return; - ui = data; + elm_box_clear(ui->cpu_activity); - list = proc_info_all_get(); + box = elm_box_add(ui->content); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(box); - EINA_LIST_FOREACH(list, l, proc) + for (i = 0; i < results->cpu_count; i++) { - int64_t time_prev = ui->cpu_times[proc->pid]; - proc->cpu_usage = 0; - if (!ui->first_run && proc->cpu_time > time_prev) - { - proc->cpu_usage = (double)(proc->cpu_time - time_prev) / ui->poll_delay; - } - } + frame = elm_frame_add(box); + evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); + evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + if (i == 0 && results->temperature != INVALID_TEMP) + elm_object_text_set(frame, eina_slstr_printf("CPU %d (%d °C)", i, results->temperature)); + else + elm_object_text_set(frame, eina_slstr_printf("CPU %d", i)); - list = _list_sort(ui, list); + evas_object_show(frame); - EINA_LIST_FREE(list, proc) - { - _fields_append(ui, proc); - ui->first_run = EINA_FALSE; - ui->cpu_times[proc->pid] = proc->cpu_time; + progress = elm_progressbar_add(frame); + evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_progressbar_span_size_set(progress, 1.0); + elm_progressbar_unit_format_set(progress, "%1.2f%%"); - free(proc); + elm_progressbar_value_set(progress, results->cores[i]->percent / 100); + evas_object_show(progress); + elm_object_content_set(frame, progress); + elm_box_pack_end(box, frame); } - if (list) - eina_list_free(list); - - _fields_show(ui); - _fields_clear(ui); - - eina_lock_release(&_lock); -} - -static void -_system_process_list_update(Ui *ui) -{ - _system_process_list_feedback_cb(ui, NULL, NULL); + elm_box_pack_end(ui->cpu_activity, box); } static void -_system_process_list(void *data, Ecore_Thread *thread) +_system_stats_thread_feedback_cb(void *data, Ecore_Thread *thread, void *msg) { Ui *ui; + results_t *results; + double cpu_usage = 0.0; int i; ui = data; + results = msg; - while (1) - { - ecore_thread_feedback(thread, ui); - for (i = 0; i < ui->poll_delay * 2; i++) - { - if (ecore_thread_check(thread)) - return; + if (ecore_thread_check(thread)) + goto out; - if (ui->skip_wait) - { - ui->skip_wait = EINA_FALSE; - break; - } + _cpu_view_update(ui, results); + _memory_view_update(ui, results); + _disk_view_update(ui); + _extra_view_update(ui, results); - usleep(500000); - } + for (i = 0; i < results->cpu_count; i++) + { + cpu_usage += results->cores[i]->percent; + + free(results->cores[i]); } -} -static void -_thread_end_cb(void *data EINA_UNUSED, Ecore_Thread *thread) -{ - thread = NULL; -} + cpu_usage = cpu_usage / results->cpu_count; -static void -_thread_error_cb(void *data EINA_UNUSED, Ecore_Thread *thread) -{ - thread = NULL; -} + _memory_total = results->memory.total; + _memory_used = results->memory.used; -static char * -_progress_mem_format_cb(double val) + elm_progressbar_value_set(ui->progress_cpu, (double)cpu_usage / 100); + elm_progressbar_value_set(ui->progress_mem, (double)((results->memory.total / 100.0) * results->memory.used) / 1000000000000); + +out: + free(results->cores); + free(results); +} + +static int +_sort_by_pid(const void *p1, const void *p2) { - char buf[1024]; + const Proc_Stats *inf1, *inf2; - snprintf(buf, sizeof(buf), "%ld M out of %ld M", _memory_used, _memory_total); + inf1 = p1; inf2 = p2; - return strdup(buf); + return inf1->pid - inf2->pid; } -static void -_progress_mem_format_free_cb(char *str) +static int +_sort_by_uid(const void *p1, const void *p2) { - if (str) - free(str); -} + const Proc_Stats *inf1, *inf2; -static void -_btn_icon_state_set(Evas_Object *button, Eina_Bool reverse) -{ - Evas_Object *icon = elm_icon_add(button); - if (reverse) - elm_icon_standard_set(icon, "go-down"); - else - elm_icon_standard_set(icon, "go-up"); + inf1 = p1; inf2 = p2; - elm_object_part_content_set(button, "icon", icon); - evas_object_show(icon); + return inf1->uid - inf2->uid; } -static void -_btn_pid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +static int +_sort_by_nice(const void *p1, const void *p2) { - Ui *ui = data; + const Proc_Stats *inf1, *inf2; - if (ui->sort_type == SORT_BY_PID) - ui->sort_reverse = !ui->sort_reverse; + inf1 = p1; inf2 = p2; - _btn_icon_state_set(ui->btn_pid, ui->sort_reverse); + return inf1->nice - inf2->nice; +} - ui->sort_type = SORT_BY_PID; +static int +_sort_by_pri(const void *p1, const void *p2) +{ + const Proc_Stats *inf1, *inf2; - _system_process_list_update(ui); + inf1 = p1; inf2 = p2; - elm_scroller_page_bring_in(ui->scroller, 0, 0); + return inf1->priority - inf2->priority; } -static void -_btn_uid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +static int +_sort_by_cpu(const void *p1, const void *p2) { - Ui *ui = data; + const Proc_Stats *inf1, *inf2; - if (ui->sort_type == SORT_BY_UID) - ui->sort_reverse = !ui->sort_reverse; + inf1 = p1; inf2 = p2; - _btn_icon_state_set(ui->btn_uid, ui->sort_reverse); + return inf1->cpu_id - inf2->cpu_id; +} - ui->sort_type = SORT_BY_UID; +static int +_sort_by_threads(const void *p1, const void *p2) +{ + const Proc_Stats *inf1, *inf2; - _system_process_list_update(ui); + inf1 = p1; inf2 = p2; - elm_scroller_page_bring_in(ui->scroller, 0, 0); + return inf1->numthreads - inf2->numthreads; } -static void -_btn_cpu_usage_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +static int +_sort_by_size(const void *p1, const void *p2) { - Ui *ui = data; - - if (ui->sort_type == SORT_BY_CPU_USAGE) - ui->sort_reverse = !ui->sort_reverse; + const Proc_Stats *inf1, *inf2; + int64_t size1, size2; - _btn_icon_state_set(ui->btn_cpu_usage, ui->sort_reverse); + inf1 = p1; inf2 = p2; - ui->sort_type = SORT_BY_CPU_USAGE; + size1 = inf1->mem_size; + size2 = inf2->mem_size; - _system_process_list_update(ui); + if (size1 < size2) + return -1; + if (size2 > size1) + return 1; - elm_scroller_page_bring_in(ui->scroller, 0, 0); + return 0; } -static void -_btn_size_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +static int +_sort_by_rss(const void *p1, const void *p2) { - Ui *ui = data; - - if (ui->sort_type == SORT_BY_SIZE) - ui->sort_reverse = !ui->sort_reverse; + const Proc_Stats *inf1, *inf2; + int64_t size1, size2; - _btn_icon_state_set(ui->btn_size, ui->sort_reverse); + inf1 = p1; inf2 = p2; - ui->sort_type = SORT_BY_SIZE; + size1 = inf1->mem_rss; + size2 = inf2->mem_rss; - _system_process_list_update(ui); + if (size1 < size2) + return -1; + if (size2 > size1) + return 1; - elm_scroller_page_bring_in(ui->scroller, 0, 0); + return 0; } -static void -_btn_rss_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +static int +_sort_by_cpu_usage(const void *p1, const void *p2) { - Ui *ui = data; - - if (ui->sort_type == SORT_BY_RSS) - ui->sort_reverse = !ui->sort_reverse; + const Proc_Stats *inf1, *inf2; + double one, two; - _btn_icon_state_set(ui->btn_rss, ui->sort_reverse); + inf1 = p1; inf2 = p2; - ui->sort_type = SORT_BY_RSS; + one = inf1->cpu_usage; + two = inf2->cpu_usage; - _system_process_list_update(ui); + if (one < two) + return -1; + if (two > one) + return 1; - elm_scroller_page_bring_in(ui->scroller, 0, 0); + return 0; } -static void -_btn_cmd_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +static int +_sort_by_cmd(const void *p1, const void *p2) { - Ui *ui = data; + const Proc_Stats *inf1, *inf2; - if (ui->sort_type == SORT_BY_CMD) - ui->sort_reverse = !ui->sort_reverse; + inf1 = p1; inf2 = p2; - _btn_icon_state_set(ui->btn_cmd, ui->sort_reverse); + return strcasecmp(inf1->command, inf2->command); +} - ui->sort_type = SORT_BY_CMD; +static int +_sort_by_state(const void *p1, const void *p2) +{ + const Proc_Stats *inf1, *inf2; - _system_process_list_update(ui); + inf1 = p1; inf2 = p2; - elm_scroller_page_bring_in(ui->scroller, 0, 0); + return strcmp(inf1->state, inf2->state); } static void -_btn_state_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_fields_append(Ui *ui, Proc_Stats *proc) { - Ui *ui = data; + const char *symbol; + int64_t mem_size, mem_rss; - if (ui->sort_type == SORT_BY_STATE) - ui->sort_reverse = !ui->sort_reverse; + if (ui->program_pid == proc->pid) + return; - _btn_icon_state_set(ui->btn_state, ui->sort_reverse); + symbol = _data_unit_symbol_get(ui->data_unit); - ui->sort_type = SORT_BY_STATE; + mem_size = proc->mem_size; + mem_rss = proc->mem_rss; - _system_process_list_update(ui); + if (ui->data_unit == DATA_UNIT_KB) + { + mem_size >>= 10; + mem_rss >>= 10; + } + else if (ui->data_unit == DATA_UNIT_MB) + { + mem_size >>= 20; + mem_rss >>= 20; + } + else + { + mem_size >>= 30; + mem_rss >>= 30; + } - elm_scroller_page_bring_in(ui->scroller, 0, 0); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_PID], eina_slstr_printf("%d
", proc->pid), TEXT_FIELD_MAX); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_UID], eina_slstr_printf("%d
", proc->uid), TEXT_FIELD_MAX); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_SIZE], eina_slstr_printf("%lld %c
", mem_size, *symbol), TEXT_FIELD_MAX); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_RSS], eina_slstr_printf("%lld %c
", mem_rss, *symbol), TEXT_FIELD_MAX); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_COMMAND], eina_slstr_printf("%s
", proc->command), TEXT_FIELD_MAX); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_STATE], eina_slstr_printf("%s
", proc->state), TEXT_FIELD_MAX); + eina_strlcat(ui->fields[PROCESS_INFO_FIELD_CPU_USAGE], eina_slstr_printf("%.1f%%
", proc->cpu_usage), TEXT_FIELD_MAX); } static void -_btn_quit_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_fields_show(Ui *ui) { - Ui *ui = data; - - ui_shutdown(ui); + elm_object_text_set(ui->entry_pid, ui->fields[PROCESS_INFO_FIELD_PID]); + elm_object_text_set(ui->entry_uid, ui->fields[PROCESS_INFO_FIELD_UID]); + elm_object_text_set(ui->entry_size, ui->fields[PROCESS_INFO_FIELD_SIZE]); + elm_object_text_set(ui->entry_rss, ui->fields[PROCESS_INFO_FIELD_RSS]); + elm_object_text_set(ui->entry_cmd, ui->fields[PROCESS_INFO_FIELD_COMMAND]); + elm_object_text_set(ui->entry_state, ui->fields[PROCESS_INFO_FIELD_STATE]); + elm_object_text_set(ui->entry_cpu_usage, ui->fields[PROCESS_INFO_FIELD_CPU_USAGE]); } static void -_list_item_del_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_fields_clear(Ui *ui) { - pid_t *pid = data; - - free(pid); + for (int i = 0; i < PROCESS_INFO_FIELDS; i++) + { + ui->fields[i][0] = '\0'; + } } static void -_process_panel_pids_update(Ui *ui) +_fields_free(Ui *ui) { - Proc_Stats *proc; - Elm_Widget_Item *item; - Eina_List *list; - pid_t *pid; - char buf[64]; + for (int i = 0; i < PROCESS_INFO_FIELDS; i++) + { + free(ui->fields[i]); + } +} - if (!ui->panel_visible) - return; +static Eina_List * +_list_sort(Ui *ui, Eina_List *list) +{ + switch (ui->sort_type) + { + case SORT_BY_NONE: + case SORT_BY_PID: + list = eina_list_sort(list, eina_list_count(list), _sort_by_pid); + break; - list = proc_info_all_get(); - list = eina_list_sort(list, eina_list_count(list), _sort_by_pid); + case SORT_BY_UID: + list = eina_list_sort(list, eina_list_count(list), _sort_by_uid); + break; + + case SORT_BY_NICE: + list = eina_list_sort(list, eina_list_count(list), _sort_by_nice); + break; + + case SORT_BY_PRI: + list = eina_list_sort(list, eina_list_count(list), _sort_by_pri); + break; + + case SORT_BY_CPU: + list = eina_list_sort(list, eina_list_count(list), _sort_by_cpu); + break; - elm_list_clear(ui->list_pid); + case SORT_BY_THREADS: + list = eina_list_sort(list, eina_list_count(list), _sort_by_threads); + break; - EINA_LIST_FREE(list, proc) - { - snprintf(buf, sizeof(buf), "%d", proc->pid); + case SORT_BY_SIZE: + list = eina_list_sort(list, eina_list_count(list), _sort_by_size); + break; - pid = malloc(sizeof(pid_t)); - *pid = proc->pid; + case SORT_BY_RSS: + list = eina_list_sort(list, eina_list_count(list), _sort_by_rss); + break; - item = elm_list_item_append(ui->list_pid, buf, NULL, NULL, NULL, pid); - elm_object_item_del_cb_set(item, _list_item_del_cb); + case SORT_BY_CMD: + list = eina_list_sort(list, eina_list_count(list), _sort_by_cmd); + break; - free(proc); + case SORT_BY_STATE: + list = eina_list_sort(list, eina_list_count(list), _sort_by_state); + break; + + case SORT_BY_CPU_USAGE: + list = eina_list_sort(list, eina_list_count(list), _sort_by_cpu_usage); + break; } - elm_list_go(ui->list_pid); + if (ui->sort_reverse) + list = eina_list_reverse(list); - if (list) - eina_list_free(list); + return list; } -static Eina_Bool -_process_panel_update(void *data) +static void +_system_process_list_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg EINA_UNUSED) { Ui *ui; - const Eina_List *l, *list; - Elm_Widget_Item *it; - struct passwd *pwd_entry; + Eina_List *list, *l; Proc_Stats *proc; - double cpu_usage = 0.0; - ui = data; + eina_lock_take(&_lock); - proc = proc_info_by_pid(ui->selected_pid); - if (!proc) - { - _process_panel_pids_update(ui); + ui = data; - return ECORE_CALLBACK_CANCEL; - } + list = proc_info_all_get(); - list = elm_list_items_get(ui->list_pid); - EINA_LIST_FOREACH(list, l, it) + EINA_LIST_FOREACH(list, l, proc) { - pid_t *pid = elm_object_item_data_get(it); - if (pid && *pid == ui->selected_pid) + int64_t time_prev = ui->cpu_times[proc->pid]; + proc->cpu_usage = 0; + if (!ui->first_run && proc->cpu_time > time_prev) { - elm_list_item_selected_set(it, EINA_TRUE); - elm_list_item_bring_in(it); - break; + proc->cpu_usage = (double)(proc->cpu_time - time_prev) / ui->poll_delay; } } - elm_object_text_set(ui->entry_pid_cmd, proc->command); - - pwd_entry = getpwuid(proc->uid); - if (pwd_entry) - elm_object_text_set(ui->entry_pid_user, pwd_entry->pw_name); - - elm_object_text_set(ui->entry_pid_pid, eina_slstr_printf("%d", proc->pid)); - elm_object_text_set(ui->entry_pid_uid, eina_slstr_printf("%d", proc->uid)); - elm_object_text_set(ui->entry_pid_cpu, eina_slstr_printf("%d", proc->cpu_id)); - elm_object_text_set(ui->entry_pid_threads, eina_slstr_printf("%d", proc->numthreads)); - elm_object_text_set(ui->entry_pid_size, eina_slstr_printf("%lld bytes", proc->mem_size)); - elm_object_text_set(ui->entry_pid_rss, eina_slstr_printf("%lld bytes", proc->mem_rss)); - elm_object_text_set(ui->entry_pid_nice, eina_slstr_printf("%d", proc->nice)); - elm_object_text_set(ui->entry_pid_pri, eina_slstr_printf("%d", proc->priority)); - elm_object_text_set(ui->entry_pid_state, proc->state); + list = _list_sort(ui, list); - if (ui->pid_cpu_time && proc->cpu_time >= ui->pid_cpu_time) + EINA_LIST_FREE(list, proc) { - cpu_usage = (double)(proc->cpu_time - ui->pid_cpu_time) / ui->poll_delay; + _fields_append(ui, proc); + ui->first_run = EINA_FALSE; + ui->cpu_times[proc->pid] = proc->cpu_time; + + free(proc); } - elm_object_text_set(ui->entry_pid_cpu_usage, eina_slstr_printf("%.1f%%", cpu_usage)); + if (list) + eina_list_free(list); - ui->pid_cpu_time = proc->cpu_time; + _fields_show(ui); + _fields_clear(ui); - free(proc); + eina_lock_release(&_lock); +} - return ECORE_CALLBACK_RENEW; +static void +_system_process_list_update(Ui *ui) +{ + _system_process_list_feedback_cb(ui, NULL, NULL); } static void -_process_panel_list_selected_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +_system_process_list(void *data, Ecore_Thread *thread) { - Elm_Object_Item *it; Ui *ui; - const char *text; + int i; ui = data; - it = elm_list_selected_item_get(obj); - - text = elm_object_item_text_get(it); - - if (ui->timer_pid) + while (1) { - ecore_timer_del(ui->timer_pid); - ui->timer_pid = NULL; - } - - ui->selected_pid = atoi(text); - - ui->pid_cpu_time = 0; - - _process_panel_update(ui); + ecore_thread_feedback(thread, ui); + for (i = 0; i < ui->poll_delay * 2; i++) + { + if (ecore_thread_check(thread)) + return; - ui->timer_pid = ecore_timer_add(ui->poll_delay, _process_panel_update, ui); + if (ui->skip_wait) + { + ui->skip_wait = EINA_FALSE; + break; + } - elm_scroller_page_bring_in(ui->scroller, 0, 0); + usleep(500000); + } + } } static void -_panel_scrolled_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_thread_end_cb(void *data EINA_UNUSED, Ecore_Thread *thread) { - Ui *ui = data; - - ui->panel_visible = !ui->panel_visible; + thread = NULL; } static void -_btn_start_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_thread_error_cb(void *data EINA_UNUSED, Ecore_Thread *thread) { - Ui *ui = data; - - if (ui->selected_pid == -1) - return; - - kill(ui->selected_pid, SIGCONT); + thread = NULL; } static void -_btn_stop_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_btn_icon_state_set(Evas_Object *button, Eina_Bool reverse) { - Ui *ui = data; - - if (ui->selected_pid == -1) - return; + Evas_Object *icon = elm_icon_add(button); + if (reverse) + elm_icon_standard_set(icon, "go-down"); + else + elm_icon_standard_set(icon, "go-up"); - kill(ui->selected_pid, SIGSTOP); + elm_object_part_content_set(button, "icon", icon); + evas_object_show(icon); } static void -_btn_kill_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_btn_pid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Ui *ui = data; - if (ui->selected_pid == -1) - return; - - kill(ui->selected_pid, SIGKILL); -} - -static void -_entry_pid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - Ui *ui; - Evas_Object *textblock; - Evas_Textblock_Cursor *pos; - const char *text; - char *pid_text, *start, *end; - - ui = data; - - textblock = elm_entry_textblock_get(obj); - if (!textblock) - return; + if (ui->sort_type == SORT_BY_PID) + ui->sort_reverse = !ui->sort_reverse; - pos = evas_object_textblock_cursor_get(textblock); - if (!pos) - return; + _btn_icon_state_set(ui->btn_pid, ui->sort_reverse); - text = evas_textblock_cursor_paragraph_text_get(pos); - if (!text) - return; + ui->sort_type = SORT_BY_PID; - pid_text = strdup(text); + _system_process_list_update(ui); - start = strchr(pid_text, '>') + 1; - if (start) - { - end = strchr(start, '<'); - if (end) - *end = '\0'; - } - else - { - free(pid_text); - return; - } + elm_scroller_page_bring_in(ui->scroller, 0, 0); +} - ui->selected_pid = atol(start); +static void +_btn_uid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ui *ui = data; - free(pid_text); + if (ui->sort_type == SORT_BY_UID) + ui->sort_reverse = !ui->sort_reverse; - _process_panel_update(ui); + _btn_icon_state_set(ui->btn_uid, ui->sort_reverse); - if (ui->timer_pid) - { - ecore_timer_del(ui->timer_pid); - ui->timer_pid = NULL; - } + ui->sort_type = SORT_BY_UID; - ui->timer_pid = ecore_timer_add(ui->poll_delay, _process_panel_update, ui); + _system_process_list_update(ui); - elm_panel_toggle(ui->panel); - ui->panel_visible = EINA_TRUE; + elm_scroller_page_bring_in(ui->scroller, 0, 0); } -static unsigned long -_disk_adjust(Data_Unit unit, unsigned long value) +static void +_btn_cpu_usage_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - if (unit == DATA_UNIT_KB) - { - value >>= 10; - } - else if (unit == DATA_UNIT_MB) - { - value >>= 20; - } - else if (unit == DATA_UNIT_GB) - { - value >>= 30; - } + Ui *ui = data; + + if (ui->sort_type == SORT_BY_CPU_USAGE) + ui->sort_reverse = !ui->sort_reverse; - return value; + _btn_icon_state_set(ui->btn_cpu_usage, ui->sort_reverse); + + ui->sort_type = SORT_BY_CPU_USAGE; + + _system_process_list_update(ui); + + elm_scroller_page_bring_in(ui->scroller, 0, 0); } static void -_ui_disk_add(Ui *ui, const char *path, const char *mount, unsigned long total, unsigned long used) +_btn_size_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - Evas_Object *frame, *progress; - const char *symbol; - double ratio, value; + Ui *ui = data; - frame = elm_frame_add(ui->disk_activity); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, 0); - elm_object_text_set(frame, eina_slstr_printf("%s on %s", path, mount)); - evas_object_show(frame); + if (ui->sort_type == SORT_BY_SIZE) + ui->sort_reverse = !ui->sort_reverse; - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); + _btn_icon_state_set(ui->btn_size, ui->sort_reverse); - symbol = _data_unit_symbol_get(ui->data_unit); + ui->sort_type = SORT_BY_SIZE; - elm_progressbar_unit_format_set(progress, - eina_slstr_printf( - "%lu%c of %lu%c", - _disk_adjust(ui->data_unit, used), *symbol, - _disk_adjust(ui->data_unit, total), *symbol)); + _system_process_list_update(ui); - elm_object_content_set(frame, progress); + elm_scroller_page_bring_in(ui->scroller, 0, 0); +} - ratio = total / 100.0; - value = used / ratio; +static void +_btn_rss_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ui *ui = data; - if (used == 0 && total == 0) - elm_progressbar_value_set(progress, 1.0); - else - elm_progressbar_value_set(progress, value / 100.0); + if (ui->sort_type == SORT_BY_RSS) + ui->sort_reverse = !ui->sort_reverse; - evas_object_show(progress); + _btn_icon_state_set(ui->btn_rss, ui->sort_reverse); - elm_box_pack_end(ui->disk_activity, frame); + ui->sort_type = SORT_BY_RSS; + + _system_process_list_update(ui); + + elm_scroller_page_bring_in(ui->scroller, 0, 0); } static void -_disk_view_update(Ui *ui) +_btn_cmd_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - Eina_List *disks; - char *path; - unsigned long total, used; + Ui *ui = data; - if (!ui->disk_visible) - return; + if (ui->sort_type == SORT_BY_CMD) + ui->sort_reverse = !ui->sort_reverse; - elm_box_clear(ui->disk_activity); + _btn_icon_state_set(ui->btn_cmd, ui->sort_reverse); - disks = disks_get(); - EINA_LIST_FREE(disks, path) - { - char *mount = disk_mount_point_get(path); - if (mount) - { - if (disk_usage_get(mount, &total, &used)) - { - _ui_disk_add(ui, path, mount, total, used); - } - free(mount); - } + ui->sort_type = SORT_BY_CMD; - free(path); - } - if (disks) - free(disks); + _system_process_list_update(ui); + + elm_scroller_page_bring_in(ui->scroller, 0, 0); } -static char * -_progress_incoming_format_cb(double val) +static void +_btn_state_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - char buf[1024]; - double incoming; - const char *unit = "B/s"; + Ui *ui = data; - incoming = _results->incoming; - if (incoming > 1048576) - { - incoming /= 1048576; - unit = "MB/s"; - } - else if (incoming > 1024 && incoming < 1048576) - { - incoming /= 1024; - unit = "KB/s"; - } + if (ui->sort_type == SORT_BY_STATE) + ui->sort_reverse = !ui->sort_reverse; - snprintf(buf, sizeof(buf), "%.2f %s", incoming, unit); + _btn_icon_state_set(ui->btn_state, ui->sort_reverse); - return strdup(buf); -} + ui->sort_type = SORT_BY_STATE; -static void -_progress_incoming_format_free_cb(char *str) -{ - if (str) - free(str); + _system_process_list_update(ui); + + elm_scroller_page_bring_in(ui->scroller, 0, 0); } -static char * -_progress_outgoing_format_cb(double val) +static void +_btn_quit_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - char buf[1024]; - double outgoing; - const char *unit = "B/s"; - - outgoing = _results->outgoing; - if (outgoing > 1048576) - { - outgoing /= 1048576; - unit = "MB/s"; - } - else if (outgoing > 1024 && outgoing < 1048576) - { - outgoing /= 1024; - unit = "KB/s"; - } - - snprintf(buf, sizeof(buf), "%.2f %s", outgoing, unit); + Ui *ui = data; - return strdup(buf); + ui_shutdown(ui); } static void -_progress_outgoing_format_free_cb(char *str) +_list_item_del_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - if (str) - free(str); + pid_t *pid = data; + + free(pid); } static void -_cpu_view_update(Ui *ui, results_t *results) +_process_panel_pids_update(Ui *ui) { - Evas_Object *box, *frame, *progress; - int i; + Proc_Stats *proc; + Elm_Widget_Item *item; + Eina_List *list; + pid_t *pid; + char buf[64]; - if (!ui->cpu_visible) + if (!ui->panel_visible) return; - elm_box_clear(ui->cpu_activity); + list = proc_info_all_get(); + list = eina_list_sort(list, eina_list_count(list), _sort_by_pid); - box = elm_box_add(ui->content); - evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(box); + elm_list_clear(ui->list_pid); - for (i = 0; i < results->cpu_count; i++) + EINA_LIST_FREE(list, proc) { - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - if (i == 0 && results->temperature != INVALID_TEMP) - elm_object_text_set(frame, eina_slstr_printf("CPU %d (%d °C)", i, results->temperature)); - else - elm_object_text_set(frame, eina_slstr_printf("CPU %d", i)); + snprintf(buf, sizeof(buf), "%d", proc->pid); - evas_object_show(frame); + pid = malloc(sizeof(pid_t)); + *pid = proc->pid; - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, "%1.2f%%"); + item = elm_list_item_append(ui->list_pid, buf, NULL, NULL, NULL, pid); + elm_object_item_del_cb_set(item, _list_item_del_cb); - elm_progressbar_value_set(progress, results->cores[i]->percent / 100); - evas_object_show(progress); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); + free(proc); } - elm_box_pack_end(ui->cpu_activity, box); + elm_list_go(ui->list_pid); + + if (list) + eina_list_free(list); } -static unsigned long -_mem_adjust(Data_Unit unit, unsigned long value) +static Eina_Bool +_process_panel_update(void *data) { - if (unit == DATA_UNIT_KB) + Ui *ui; + const Eina_List *l, *list; + Elm_Widget_Item *it; + struct passwd *pwd_entry; + Proc_Stats *proc; + double cpu_usage = 0.0; + + ui = data; + + proc = proc_info_by_pid(ui->selected_pid); + if (!proc) { + _process_panel_pids_update(ui); + + return ECORE_CALLBACK_CANCEL; } - else if (unit == DATA_UNIT_MB) + + list = elm_list_items_get(ui->list_pid); + EINA_LIST_FOREACH(list, l, it) { - value >>= 10; + pid_t *pid = elm_object_item_data_get(it); + if (pid && *pid == ui->selected_pid) + { + elm_list_item_selected_set(it, EINA_TRUE); + elm_list_item_bring_in(it); + break; + } } - else if (unit == DATA_UNIT_GB) + + elm_object_text_set(ui->entry_pid_cmd, proc->command); + + pwd_entry = getpwuid(proc->uid); + if (pwd_entry) + elm_object_text_set(ui->entry_pid_user, pwd_entry->pw_name); + + elm_object_text_set(ui->entry_pid_pid, eina_slstr_printf("%d", proc->pid)); + elm_object_text_set(ui->entry_pid_uid, eina_slstr_printf("%d", proc->uid)); + elm_object_text_set(ui->entry_pid_cpu, eina_slstr_printf("%d", proc->cpu_id)); + elm_object_text_set(ui->entry_pid_threads, eina_slstr_printf("%d", proc->numthreads)); + elm_object_text_set(ui->entry_pid_size, eina_slstr_printf("%lld bytes", proc->mem_size)); + elm_object_text_set(ui->entry_pid_rss, eina_slstr_printf("%lld bytes", proc->mem_rss)); + elm_object_text_set(ui->entry_pid_nice, eina_slstr_printf("%d", proc->nice)); + elm_object_text_set(ui->entry_pid_pri, eina_slstr_printf("%d", proc->priority)); + elm_object_text_set(ui->entry_pid_state, proc->state); + + if (ui->pid_cpu_time && proc->cpu_time >= ui->pid_cpu_time) { - value >>= 20; + cpu_usage = (double)(proc->cpu_time - ui->pid_cpu_time) / ui->poll_delay; } - return value; + elm_object_text_set(ui->entry_pid_cpu_usage, eina_slstr_printf("%.1f%%", cpu_usage)); + + ui->pid_cpu_time = proc->cpu_time; + + free(proc); + + return ECORE_CALLBACK_RENEW; } static void -_memory_view_update(Ui *ui, results_t *results) +_process_panel_list_selected_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { - Evas_Object *box, *frame, *progress; - const char *symbol; - double ratio, value; + Elm_Object_Item *it; + Ui *ui; + const char *text; - if (!ui->mem_visible) - return; + ui = data; - elm_box_clear(ui->mem_activity); + it = elm_list_selected_item_get(obj); - symbol = _data_unit_symbol_get(ui->data_unit); + text = elm_object_item_text_get(it); - box = elm_box_add(ui->content); - evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(box); + if (ui->timer_pid) + { + ecore_timer_del(ui->timer_pid); + ui->timer_pid = NULL; + } - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(frame, "Memory Used"); - evas_object_show(frame); - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, - eina_slstr_printf( - "%lu %c / %lu %c", - _mem_adjust(ui->data_unit, results->memory.used), *symbol, - _mem_adjust(ui->data_unit, results->memory.total), *symbol)); + ui->selected_pid = atoi(text); - ratio = results->memory.total / 100.0; - value = results->memory.used / ratio; - elm_progressbar_value_set(progress, value / 100); - evas_object_show(progress); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); + ui->pid_cpu_time = 0; - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(frame, "Memory Cached"); - evas_object_show(frame); - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, eina_slstr_printf( - "%lu %c / %lu %c", - _mem_adjust(ui->data_unit, results->memory.cached), *symbol, - _mem_adjust(ui->data_unit, results->memory.total), *symbol)); + _process_panel_update(ui); - ratio = results->memory.total / 100.0; - value = results->memory.cached / ratio; - elm_progressbar_value_set(progress, value / 100); - evas_object_show(progress); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); + ui->timer_pid = ecore_timer_add(ui->poll_delay, _process_panel_update, ui); - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(frame, "Memory Buffered"); - evas_object_show(frame); - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, - eina_slstr_printf( - "%lu %c / %lu %c", - _mem_adjust(ui->data_unit, results->memory.buffered), *symbol, - _mem_adjust(ui->data_unit, results->memory.total), *symbol)); + elm_scroller_page_bring_in(ui->scroller, 0, 0); +} - ratio = results->memory.total / 100.0; - value = results->memory.buffered / ratio; - elm_progressbar_value_set(progress, value / 100); - evas_object_show(progress); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); +static void +_panel_scrolled_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ui *ui = data; - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(frame, "Memory Shared"); - evas_object_show(frame); - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, - eina_slstr_printf( - "%lu %c / %lu %c", - _mem_adjust(ui->data_unit, results->memory.shared), *symbol, - _mem_adjust(ui->data_unit, results->memory.total), *symbol)); + ui->panel_visible = !ui->panel_visible; +} - ratio = results->memory.total / 100.0; - value = results->memory.shared / ratio; - elm_progressbar_value_set(progress, value / 100); - evas_object_show(progress); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); +static void +_btn_start_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ui *ui = data; - elm_box_pack_end(ui->mem_activity, box); + if (ui->selected_pid == -1) + return; + + kill(ui->selected_pid, SIGCONT); } static void -_extra_view_update(Ui *ui, results_t *results) +_btn_stop_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { - Evas_Object *box, *frame, *progress; - int i; + Ui *ui = data; - if (!ui->extra_visible) + if (ui->selected_pid == -1) return; - _results = results; + kill(ui->selected_pid, SIGSTOP); +} - elm_box_clear(ui->extra_activity); +static void +_btn_kill_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ui *ui = data; - box = elm_box_add(ui->content); - evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_show(box); + if (ui->selected_pid == -1) + return; - if (results->power.battery_count) - { - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - if (results->power.have_ac) - elm_object_text_set(frame, "Battery (plugged in)"); - else - elm_object_text_set(frame, "Battery"); + kill(ui->selected_pid, SIGKILL); +} - evas_object_show(frame); +static void +_entry_pid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ui *ui; + Evas_Object *textblock; + Evas_Textblock_Cursor *pos; + const char *text; + char *pid_text, *start, *end; - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, "%1.2f%%"); - elm_progressbar_value_set(progress, (double)results->power.percent / 100); - evas_object_show(progress); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); - } + ui = data; - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(frame, "Network Incoming"); - evas_object_show(frame); + textblock = elm_entry_textblock_get(obj); + if (!textblock) + return; - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, ""); - elm_progressbar_unit_format_function_set(progress, _progress_incoming_format_cb, _progress_incoming_format_free_cb); + pos = evas_object_textblock_cursor_get(textblock); + if (!pos) + return; - if (results->incoming == 0) - elm_progressbar_value_set(progress, 0); - else - elm_progressbar_value_set(progress, 1.0); + text = evas_textblock_cursor_paragraph_text_get(pos); + if (!text) + return; - evas_object_show(progress); + pid_text = strdup(text); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); + start = strchr(pid_text, '>') + 1; + if (start) + { + end = strchr(start, '<'); + if (end) + *end = '\0'; + } + else + { + free(pid_text); + return; + } - frame = elm_frame_add(box); - evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, 0); - evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_object_text_set(frame, "Network Outgoing"); - evas_object_show(frame); + ui->selected_pid = atol(start); - progress = elm_progressbar_add(frame); - evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_progressbar_span_size_set(progress, 1.0); - elm_progressbar_unit_format_set(progress, ""); - elm_progressbar_unit_format_function_set(progress, _progress_outgoing_format_cb, _progress_outgoing_format_free_cb); - if (results->outgoing == 0) - elm_progressbar_value_set(progress, 0); - else - elm_progressbar_value_set(progress, 1.0); + free(pid_text); - evas_object_show(progress); + _process_panel_update(ui); - elm_object_content_set(frame, progress); - elm_box_pack_end(box, frame); + if (ui->timer_pid) + { + ecore_timer_del(ui->timer_pid); + ui->timer_pid = NULL; + } - elm_box_pack_end(ui->extra_activity, box); + ui->timer_pid = ecore_timer_add(ui->poll_delay, _process_panel_update, ui); + + elm_panel_toggle(ui->panel); + ui->panel_visible = EINA_TRUE; } static void @@ -2182,17 +2179,17 @@ _evisum_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) if ((ev->keyname[0] == 'K' || ev->keyname[0] == 'k') && !ev->keyname[1]) { - ui->data_unit = DATA_UNIT_KB; + ui->data_unit = _data_unit_current = DATA_UNIT_KB; ui->skip_wait = EINA_TRUE; } else if ((ev->keyname[0] == 'M' || ev->keyname[0] == 'm') && !ev->keyname[1]) { - ui->data_unit = DATA_UNIT_MB; + ui->data_unit = _data_unit_current = DATA_UNIT_MB; ui->skip_wait = EINA_TRUE; } else if ((ev->keyname[0] == 'G' || ev->keyname[0] == 'g') && !ev->keyname[1]) { - ui->data_unit = DATA_UNIT_GB; + ui->data_unit = _data_unit_current = DATA_UNIT_GB; ui->skip_wait = EINA_TRUE; } else if (!strcmp(ev->keyname, "Escape")) @@ -2217,7 +2214,7 @@ ui_add(Evas_Object *parent) ui->program_pid = getpid(); ui->panel_visible = EINA_TRUE; ui->disk_visible = ui->cpu_visible = ui->mem_visible = ui->extra_visible = EINA_TRUE; - ui->data_unit = DATA_UNIT_MB; + ui->data_unit = _data_unit_current = DATA_UNIT_MB; memset(ui->cpu_times, 0, PID_MAX * sizeof(int64_t)); @@ -2243,6 +2240,7 @@ ui_add(Evas_Object *parent) evas_object_event_callback_add(ui->content, EVAS_CALLBACK_KEY_DOWN, _evisum_key_down_cb, ui); /* Start polling the data */ + _system_process_list_update(ui); _disk_view_update(ui); _process_panel_update(ui); @@ -2252,3 +2250,4 @@ ui_add(Evas_Object *parent) return ui; } + diff --git a/src/ui.h b/src/ui.h index fcca49e..c5c60f4 100644 --- a/src/ui.h +++ b/src/ui.h @@ -26,9 +26,9 @@ typedef enum typedef enum { - DATA_UNIT_KB, - DATA_UNIT_MB, - DATA_UNIT_GB, + DATA_UNIT_KB = 1, + DATA_UNIT_MB = 2, + DATA_UNIT_GB = 3, } Data_Unit; typedef enum @@ -52,7 +52,6 @@ typedef struct Ui Evas_Object *win; Evas_Object *panel; Evas_Object *scroller; - Evas_Object *content; Evas_Object *disk_view; @@ -110,6 +109,7 @@ typedef struct Ui pid_t program_pid; Data_Unit data_unit; + const char *data_unit_symbol; #define TEXT_FIELD_MAX 65535 char *fields[PROCESS_INFO_FIELDS];