1 #include "cpumonitor.h"
2 
3 typedef struct _Thread_Config Thread_Config;
4 
5 struct _Thread_Config
6 {
7    int                  interval;
8    int                  num_cores;
9    int                  percent;
10    unsigned long        total;
11    unsigned long        idle;
12    Instance            *inst;
13    E_Powersave_Sleeper *sleeper;
14    Eina_List           *cores;
15 };
16 
17 static void
_cpumonitor_face_update(Thread_Config * thc)18 _cpumonitor_face_update(Thread_Config *thc)
19 {
20    Eina_List *l;
21    CPU_Core *core;
22 
23    EINA_LIST_FOREACH(thc->cores, l, core)
24      {
25         Edje_Message_Int_Set *usage_msg;
26         usage_msg = malloc(sizeof(Edje_Message_Int_Set) + 1 * sizeof(int));
27         EINA_SAFETY_ON_NULL_RETURN(usage_msg);
28         usage_msg->count = 1;
29         usage_msg->val[0] = core->percent;
30         edje_object_message_send(elm_layout_edje_get(core->layout), EDJE_MESSAGE_INT_SET, 1,
31                                  usage_msg);
32         E_FREE(usage_msg);
33      }
34    if (thc->inst->cfg->cpumonitor.popup)
35      {
36         elm_progressbar_value_set(thc->inst->cfg->cpumonitor.popup_pbar,
37                                   (float)thc->percent / 100);
38      }
39 }
40 
41 static Evas_Object *
_cpumonitor_configure_cb(Evas_Object * g)42 _cpumonitor_configure_cb(Evas_Object *g)
43 {
44    Instance *inst = evas_object_data_get(g, "Instance");
45 
46    if (!sysinfo_config) return NULL;
47    return cpumonitor_configure(inst);
48 }
49 
50 static void
_cpumonitor_popup_dismissed(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)51 _cpumonitor_popup_dismissed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
52 {
53    Instance *inst = data;
54    E_FREE_FUNC(obj, evas_object_del);
55    inst->cfg->cpumonitor.popup = NULL;
56 }
57 
58 static void
_cpumonitor_popup_deleted(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)59 _cpumonitor_popup_deleted(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
60 {
61    Instance *inst = data;
62    inst->cfg->cpumonitor.popup = NULL;
63 }
64 
65 static void
_cpumonitor_mouse_up_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data)66 _cpumonitor_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data)
67 {
68    Evas_Object *popup, *box, *pbar, *label;
69    Evas_Event_Mouse_Up *ev = event_data;
70    Instance *inst = data;
71    char text[256];
72 
73    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
74    if (ev->button == 1)
75      {
76         if (inst->cfg->cpumonitor.popup)
77           {
78              elm_ctxpopup_dismiss(inst->cfg->cpumonitor.popup);
79              return;
80           }
81         popup = elm_ctxpopup_add(e_comp->elm);
82         elm_object_style_set(popup, "noblock");
83         evas_object_smart_callback_add(popup, "dismissed", _cpumonitor_popup_dismissed, inst);
84         evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, _cpumonitor_popup_deleted, inst);
85 
86         box = elm_box_add(popup);
87         E_EXPAND(box); E_FILL(box);
88         elm_object_content_set(popup, box);
89         evas_object_show(box);
90 
91         snprintf(text, sizeof(text), "<big><b>%s</b></big>", _("Total CPU Usage"));
92         label = elm_label_add(box);
93         E_EXPAND(label); E_ALIGN(label, 0.5, 0.5);
94         elm_object_text_set(label, text);
95         elm_box_pack_end(box, label);
96         evas_object_show(label);
97 
98         pbar = elm_progressbar_add(box);
99         E_EXPAND(pbar); E_FILL(pbar);
100         elm_progressbar_span_size_set(pbar, 200 * e_scale);
101         elm_progressbar_value_set(pbar, (float)inst->cfg->cpumonitor.percent / 100);
102         elm_box_pack_end(box, pbar);
103         evas_object_show(pbar);
104         inst->cfg->cpumonitor.popup_pbar = pbar;
105 
106         e_gadget_util_ctxpopup_place(inst->o_main, popup,
107                                      inst->cfg->cpumonitor.o_gadget);
108         evas_object_show(popup);
109         inst->cfg->cpumonitor.popup = popup;
110      }
111 }
112 
113 static void
_cpumonitor_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_data EINA_UNUSED)114 _cpumonitor_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
115 {
116    Evas_Coord w = 1, h = 1, sw, sh;
117    Instance *inst = data;
118    int num_cores = inst->cfg->cpumonitor.cores;
119 
120    if (!num_cores || !inst->o_main) return;
121 
122    edje_object_parts_extends_calc(elm_layout_edje_get(obj), 0, 0, &w, &h);
123    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _cpumonitor_resize_cb, inst);
124    if (inst->cfg->esm == E_SYSINFO_MODULE_CPUMONITOR)
125      {
126         evas_object_geometry_get(inst->o_main, 0, 0, &sw, &sh);
127      }
128    else
129      {
130         sw = w;
131         sh = h;
132      }
133    if (e_gadget_site_orient_get(e_gadget_site_get(inst->o_main)) == E_GADGET_SITE_ORIENT_VERTICAL)
134      {
135         w = sw;
136         h *= num_cores;
137      }
138    else
139      {
140         w *= num_cores;
141         h = sh;
142      }
143    if (w < 1) w = 1;
144    if (h < 1) h = 1;
145    evas_object_size_hint_aspect_set(inst->cfg->cpumonitor.o_gadget_box, EVAS_ASPECT_CONTROL_BOTH, w, h);
146    if (inst->cfg->esm == E_SYSINFO_MODULE_CPUMONITOR)
147      evas_object_size_hint_aspect_set(inst->o_main, EVAS_ASPECT_CONTROL_BOTH, w, h);
148 }
149 
150 static void
_cpumonitor_cb_usage_check_main(void * data,Ecore_Thread * th)151 _cpumonitor_cb_usage_check_main(void *data, Ecore_Thread *th)
152 {
153    Thread_Config *thc = data;
154    for (;; )
155      {
156         if (ecore_thread_check(th)) break;
157 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
158         _cpumonitor_sysctl_getusage(&thc->total, &thc->idle, &thc->percent, thc->cores);
159 #else
160         _cpumonitor_proc_getusage(&thc->total, &thc->idle, &thc->percent, thc->cores);
161 #endif
162         ecore_thread_feedback(th, NULL);
163         if (ecore_thread_check(th)) break;
164         e_powersave_sleeper_sleep(thc->sleeper, thc->interval);
165         if (ecore_thread_check(th)) break;
166      }
167 }
168 
169 static void
_cpumonitor_cb_usage_check_notify(void * data,Ecore_Thread * th EINA_UNUSED,void * msg EINA_UNUSED)170 _cpumonitor_cb_usage_check_notify(void *data,
171                                   Ecore_Thread *th EINA_UNUSED,
172                                   void *msg EINA_UNUSED)
173 {
174    Thread_Config *thc = data;
175 
176    if (!thc->inst || !thc->inst->cfg) return;
177    if (thc->inst->cfg->esm != E_SYSINFO_MODULE_CPUMONITOR && thc->inst->cfg->esm != E_SYSINFO_MODULE_SYSINFO) return;
178    thc->inst->cfg->cpumonitor.percent = thc->percent;
179    _cpumonitor_face_update(thc);
180 }
181 
182 static void
_cpumonitor_cb_usage_check_end(void * data,Ecore_Thread * th EINA_UNUSED)183 _cpumonitor_cb_usage_check_end(void *data, Ecore_Thread *th EINA_UNUSED)
184 {
185    Thread_Config *thc = data;
186    CPU_Core *core;
187 
188    e_powersave_sleeper_free(thc->sleeper);
189    EINA_LIST_FREE(thc->cores, core)
190      E_FREE(core);
191    E_FREE(thc);
192 }
193 
194 Evas_Object *
_cpumonitor_add_layout(Instance * inst)195 _cpumonitor_add_layout(Instance *inst)
196 {
197    Evas_Object *layout;
198    int orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main));
199 
200    layout = elm_layout_add(inst->cfg->cpumonitor.o_gadget_box);
201    edje_object_update_hints_set(elm_layout_edje_get(layout), EINA_TRUE);
202    if (orient == E_GADGET_SITE_ORIENT_VERTICAL)
203      e_theme_edje_object_set(layout, "base/theme/gadget/cpumonitor",
204                              "e/gadget/cpumonitor/core/main_vert");
205    else
206      e_theme_edje_object_set(layout, "base/theme/gadget/cpumonitor",
207                              "e/gadget/cpumonitor/core/main");
208    E_EXPAND(layout);
209    E_FILL(layout);
210    elm_box_pack_end(inst->cfg->cpumonitor.o_gadget_box, layout);
211    evas_object_show(layout);
212 
213    return layout;
214 }
215 
216 static void
_cpumonitor_del_layouts(Instance * inst)217 _cpumonitor_del_layouts(Instance *inst)
218 {
219    elm_box_clear(inst->cfg->cpumonitor.o_gadget_box);
220 }
221 
222 static Eina_Bool
_screensaver_on(void * data)223 _screensaver_on(void *data)
224 {
225    Instance *inst = data;
226 
227    if (!ecore_thread_check(inst->cfg->cpumonitor.usage_check_thread))
228      {
229         _cpumonitor_del_layouts(inst);
230         ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
231         inst->cfg->cpumonitor.usage_check_thread = NULL;
232      }
233    return ECORE_CALLBACK_RENEW;
234 }
235 
236 static Eina_Bool
_screensaver_off(void * data)237 _screensaver_off(void *data)
238 {
239    Instance *inst = data;
240 
241    _cpumonitor_config_updated(inst);
242 
243    return ECORE_CALLBACK_RENEW;
244 }
245 
246 void
_cpumonitor_config_updated(Instance * inst)247 _cpumonitor_config_updated(Instance *inst)
248 {
249    Thread_Config *thc;
250    CPU_Core *core;
251    int i = 0;
252 
253    if (inst->cfg->id == -1)
254      {
255         int percent = 15;
256         thc = E_NEW(Thread_Config, 1);
257         if (thc)
258           {
259              thc->inst = inst;
260              thc->total = 0;
261              thc->idle = 0;
262              thc->percent = 60;
263              thc->num_cores = 4;
264              inst->cfg->cpumonitor.cores = thc->num_cores;
265              for (i = 0; i < 4; i++)
266                {
267                   core = E_NEW(CPU_Core, 1);
268                   core->layout = _cpumonitor_add_layout(inst);
269                   if (i == 0)
270                     evas_object_event_callback_add(core->layout, EVAS_CALLBACK_RESIZE, _cpumonitor_resize_cb, inst);
271                   core->percent = percent;
272                   core->total = 0;
273                   core->idle = 0;
274                   thc->cores = eina_list_append(thc->cores, core);
275                   percent += 15;
276                }
277              _cpumonitor_face_update(thc);
278              EINA_LIST_FREE(thc->cores, core)
279                E_FREE(core);
280              E_FREE(thc);
281           }
282         return;
283      }
284    if (!ecore_thread_check(inst->cfg->cpumonitor.usage_check_thread))
285      {
286         _cpumonitor_del_layouts(inst);
287         ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
288         inst->cfg->cpumonitor.usage_check_thread = NULL;
289      }
290    thc = E_NEW(Thread_Config, 1);
291    if (thc)
292      {
293         thc->inst = inst;
294         thc->total = 0;
295         thc->idle = 0;
296         thc->percent = 0;
297         thc->interval = inst->cfg->cpumonitor.poll_interval;
298         thc->sleeper = e_powersave_sleeper_new();
299 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
300         thc->num_cores = _cpumonitor_sysctl_getcores();
301 #else
302         thc->num_cores = _cpumonitor_proc_getcores();
303 #endif
304         inst->cfg->cpumonitor.cores = thc->num_cores;
305         for (i = 0; i < thc->num_cores; i++)
306           {
307              core = E_NEW(CPU_Core, 1);
308              core->layout = _cpumonitor_add_layout(inst);
309              if (i == 0)
310                evas_object_event_callback_add(core->layout, EVAS_CALLBACK_RESIZE, _cpumonitor_resize_cb, inst);
311              core->percent = 0;
312              core->total = 0;
313              core->idle = 0;
314              thc->cores = eina_list_append(thc->cores, core);
315           }
316         inst->cfg->cpumonitor.usage_check_thread =
317           ecore_thread_feedback_run(_cpumonitor_cb_usage_check_main,
318                                     _cpumonitor_cb_usage_check_notify,
319                                     _cpumonitor_cb_usage_check_end,
320                                     _cpumonitor_cb_usage_check_end, thc, EINA_TRUE);
321      }
322    e_config_save_queue();
323 }
324 
325 static void
_cpumonitor_removed_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_data)326 _cpumonitor_removed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_data)
327 {
328    Instance *inst = data;
329    Ecore_Event_Handler *handler;
330 
331    if (inst->o_main != event_data) return;
332 
333    if (inst->cfg->cpumonitor.popup)
334      E_FREE_FUNC(inst->cfg->cpumonitor.popup, evas_object_del);
335    if (inst->cfg->cpumonitor.configure)
336      E_FREE_FUNC(inst->cfg->cpumonitor.configure, evas_object_del);
337    EINA_LIST_FREE(inst->cfg->cpumonitor.handlers, handler)
338      ecore_event_handler_del(handler);
339    evas_object_smart_callback_del_full(e_gadget_site_get(inst->o_main), "gadget_removed",
340                                        _cpumonitor_removed_cb, inst);
341    evas_object_event_callback_del_full(inst->o_main, EVAS_CALLBACK_DEL, sysinfo_cpumonitor_remove, data);
342    if (!ecore_thread_check(inst->cfg->cpumonitor.usage_check_thread))
343      {
344         _cpumonitor_del_layouts(inst);
345         ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
346         inst->cfg->cpumonitor.usage_check_thread = NULL;
347      }
348    sysinfo_config->items = eina_list_remove(sysinfo_config->items, inst->cfg);
349    if (inst->cfg->id >= 0)
350      sysinfo_instances = eina_list_remove(sysinfo_instances, inst);
351    E_FREE(inst->cfg);
352    E_FREE(inst);
353 }
354 
355 void
sysinfo_cpumonitor_remove(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_data EINA_UNUSED)356 sysinfo_cpumonitor_remove(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_data EINA_UNUSED)
357 {
358    Instance *inst = data;
359    Ecore_Event_Handler *handler;
360 
361    if (inst->cfg->cpumonitor.popup)
362      E_FREE_FUNC(inst->cfg->cpumonitor.popup, evas_object_del);
363    if (inst->cfg->cpumonitor.configure)
364      E_FREE_FUNC(inst->cfg->cpumonitor.configure, evas_object_del);
365    EINA_LIST_FREE(inst->cfg->cpumonitor.handlers, handler)
366      ecore_event_handler_del(handler);
367    if (!ecore_thread_check(inst->cfg->cpumonitor.usage_check_thread))
368      {
369         _cpumonitor_del_layouts(inst);
370         ecore_thread_cancel(inst->cfg->cpumonitor.usage_check_thread);
371         inst->cfg->cpumonitor.usage_check_thread = NULL;
372      }
373 }
374 
375 static void
_cpumonitor_created_cb(void * data,Evas_Object * obj,void * event_data EINA_UNUSED)376 _cpumonitor_created_cb(void *data, Evas_Object *obj, void *event_data EINA_UNUSED)
377 {
378    Instance *inst = data;
379    int orient = e_gadget_site_orient_get(e_gadget_site_get(inst->o_main));
380 
381    e_gadget_configure_cb_set(inst->o_main, _cpumonitor_configure_cb);
382 
383    inst->cfg->cpumonitor.o_gadget = elm_layout_add(inst->o_main);
384    if (orient == E_GADGET_SITE_ORIENT_VERTICAL)
385      e_theme_edje_object_set(inst->cfg->cpumonitor.o_gadget,
386                              "base/theme/gadget/cpumonitor",
387                              "e/gadget/cpumonitor/main_vert");
388    else
389      e_theme_edje_object_set(inst->cfg->cpumonitor.o_gadget,
390                              "base/theme/gadget/cpumonitor",
391                              "e/gadget/cpumonitor/main");
392    E_EXPAND(inst->cfg->cpumonitor.o_gadget);
393    E_FILL(inst->cfg->cpumonitor.o_gadget);
394    elm_box_pack_end(inst->o_main, inst->cfg->cpumonitor.o_gadget);
395    evas_object_event_callback_add(inst->cfg->cpumonitor.o_gadget, EVAS_CALLBACK_MOUSE_UP,
396                                   _cpumonitor_mouse_up_cb, inst);
397    evas_object_show(inst->cfg->cpumonitor.o_gadget);
398 
399    inst->cfg->cpumonitor.o_gadget_box = elm_box_add(inst->cfg->cpumonitor.o_gadget);
400    elm_box_homogeneous_set(inst->cfg->cpumonitor.o_gadget_box, EINA_TRUE);
401    if (orient == E_GADGET_SITE_ORIENT_VERTICAL)
402      elm_box_horizontal_set(inst->cfg->cpumonitor.o_gadget_box, EINA_FALSE);
403    else
404      elm_box_horizontal_set(inst->cfg->cpumonitor.o_gadget_box, EINA_TRUE);
405    E_EXPAND(inst->cfg->cpumonitor.o_gadget_box);
406    E_FILL(inst->cfg->cpumonitor.o_gadget_box);
407    elm_layout_content_set(inst->cfg->cpumonitor.o_gadget, "e.swallow.content", inst->cfg->cpumonitor.o_gadget_box);
408    evas_object_show(inst->cfg->cpumonitor.o_gadget_box);
409 
410    evas_object_smart_callback_del_full(obj, "gadget_created", _cpumonitor_created_cb, data);
411 
412    E_LIST_HANDLER_APPEND(inst->cfg->cpumonitor.handlers, E_EVENT_SCREENSAVER_ON, _screensaver_on, inst);
413    E_LIST_HANDLER_APPEND(inst->cfg->cpumonitor.handlers, E_EVENT_SCREENSAVER_OFF, _screensaver_off, inst);
414 
415    _cpumonitor_config_updated(inst);
416 }
417 
418 Evas_Object *
sysinfo_cpumonitor_create(Evas_Object * parent,Instance * inst)419 sysinfo_cpumonitor_create(Evas_Object *parent, Instance *inst)
420 {
421    inst->cfg->cpumonitor.percent = 0;
422    inst->cfg->cpumonitor.popup = NULL;
423    inst->cfg->cpumonitor.configure = NULL;
424    inst->cfg->cpumonitor.o_gadget = elm_layout_add(parent);
425    e_theme_edje_object_set(inst->cfg->cpumonitor.o_gadget,
426                            "base/theme/gadget/cpumonitor",
427                            "e/gadget/cpumonitor/main");
428    E_EXPAND(inst->cfg->cpumonitor.o_gadget);
429    E_FILL(inst->cfg->cpumonitor.o_gadget);
430    evas_object_event_callback_add(inst->cfg->cpumonitor.o_gadget, EVAS_CALLBACK_MOUSE_UP,
431                                   _cpumonitor_mouse_up_cb, inst);
432    evas_object_show(inst->cfg->cpumonitor.o_gadget);
433 
434    inst->cfg->cpumonitor.o_gadget_box = elm_box_add(inst->cfg->cpumonitor.o_gadget);
435    elm_box_homogeneous_set(inst->cfg->cpumonitor.o_gadget_box, EINA_TRUE);
436    elm_box_horizontal_set(inst->cfg->cpumonitor.o_gadget_box, EINA_TRUE);
437    E_EXPAND(inst->cfg->cpumonitor.o_gadget_box);
438    E_FILL(inst->cfg->cpumonitor.o_gadget_box);
439    elm_layout_content_set(inst->cfg->cpumonitor.o_gadget, "e.swallow.content", inst->cfg->cpumonitor.o_gadget_box);
440    evas_object_show(inst->cfg->cpumonitor.o_gadget_box);
441 
442    E_LIST_HANDLER_APPEND(inst->cfg->cpumonitor.handlers, E_EVENT_SCREENSAVER_ON, _screensaver_on, inst);
443    E_LIST_HANDLER_APPEND(inst->cfg->cpumonitor.handlers, E_EVENT_SCREENSAVER_OFF, _screensaver_off, inst);
444 
445    _cpumonitor_config_updated(inst);
446 
447    return inst->cfg->cpumonitor.o_gadget;
448 }
449 
450 static Config_Item *
_conf_item_get(int * id)451 _conf_item_get(int *id)
452 {
453    Config_Item *ci;
454    Eina_List *l;
455 
456    if (*id > 0)
457      {
458         EINA_LIST_FOREACH(sysinfo_config->items, l, ci)
459           if (*id == ci->id && ci->esm == E_SYSINFO_MODULE_CPUMONITOR) return ci;
460      }
461 
462    ci = E_NEW(Config_Item, 1);
463 
464    if (*id != -1)
465      ci->id = eina_list_count(sysinfo_config->items) + 1;
466    else
467      ci->id = -1;
468 
469    ci->esm = E_SYSINFO_MODULE_CPUMONITOR;
470    ci->cpumonitor.poll_interval = 32;
471    ci->cpumonitor.popup = NULL;
472    ci->cpumonitor.configure = NULL;
473    sysinfo_config->items = eina_list_append(sysinfo_config->items, ci);
474 
475    return ci;
476 }
477 
478 Evas_Object *
cpumonitor_create(Evas_Object * parent,int * id,E_Gadget_Site_Orient orient EINA_UNUSED)479 cpumonitor_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient EINA_UNUSED)
480 {
481    Instance *inst;
482 
483    inst = E_NEW(Instance, 1);
484    inst->cfg = _conf_item_get(id);
485    *id = inst->cfg->id;
486    inst->cfg->cpumonitor.popup = NULL;
487    inst->cfg->cpumonitor.configure = NULL;
488    inst->o_main = elm_box_add(parent);
489    evas_object_data_set(inst->o_main, "Instance", inst);
490    evas_object_smart_callback_add(parent, "gadget_created", _cpumonitor_created_cb, inst);
491    evas_object_smart_callback_add(parent, "gadget_removed", _cpumonitor_removed_cb, inst);
492    evas_object_event_callback_add(inst->o_main, EVAS_CALLBACK_DEL, sysinfo_cpumonitor_remove, inst);
493    evas_object_show(inst->o_main);
494 
495    if (inst->cfg->id < 0) return inst->o_main;
496 
497    sysinfo_instances =
498      eina_list_append(sysinfo_instances, inst);
499 
500    return inst->o_main;
501 }
502 
503