2b63d1665bdd299ca4d70f4f4d91036a52fe5b52
[platform/upstream/enlightenment.git] / src / modules / backlight / e_mod_main.c
1 /**
2  * @addtogroup Optional_Devices
3  * @{
4  *
5  * @defgroup Module_Backlight Backlight
6  *
7  * Controls backlights such as laptop LCD.
8  *
9  * @}
10  */
11
12 #include "e.h"
13
14 /* gadcon requirements */
15 static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
16 static void _gc_shutdown(E_Gadcon_Client *gcc);
17 static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient);
18 static const char *_gc_label(const E_Gadcon_Client_Class *client_class);
19 static Evas_Object *_gc_icon(const E_Gadcon_Client_Class *client_class, Evas *evas);
20 static const char *_gc_id_new(const E_Gadcon_Client_Class *client_class);
21
22 /* and actually define the gadcon class that this module provides (just 1) */
23 static const E_Gadcon_Client_Class _gadcon_class =
24 {
25    GADCON_CLIENT_CLASS_VERSION,
26      "backlight",
27      {
28         _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, NULL
29      },
30    E_GADCON_CLIENT_STYLE_PLAIN
31 };
32
33 /* actual module specifics */
34 typedef struct _Instance Instance;
35
36 struct _Instance
37 {
38    E_Gadcon_Client *gcc;
39    Evas_Object     *o_backlight, *o_table, *o_slider;
40    E_Gadcon_Popup  *popup;
41    double           val;
42    Ecore_Timer     *popup_timer;
43 };
44
45 static Eina_List *backlight_instances = NULL;
46 static E_Module *backlight_module = NULL;
47 static E_Action *act = NULL;
48 static Eina_List *handlers;
49
50
51 static void _backlight_popup_free(Instance *inst);
52 static void _backlight_level_set(Instance *inst, double value, Eina_Bool set_slider);
53
54 static void
55 _backlight_gadget_update(Instance *inst)
56 {
57    Edje_Message_Float msg;
58    
59    msg.val = inst->val;
60    if (msg.val < 0.0) msg.val = 0.0;
61    else if (msg.val > 1.0) msg.val = 1.0;
62    edje_object_message_send(inst->o_backlight, EDJE_MESSAGE_FLOAT, 0, &msg);
63 }
64
65 static void
66 _backlight_level_set(Instance *inst, double val, Eina_Bool set_slider)
67 {
68    if (val > 1.0) val = 1.0;
69    if (val < 0.0) val = 0.0;
70    if (set_slider)
71      e_widget_slider_value_double_set(inst->o_slider, val);
72    inst->val = val;
73    e_backlight_mode_set(inst->gcc->gadcon->zone, E_BACKLIGHT_MODE_NORMAL);
74    e_backlight_level_set(inst->gcc->gadcon->zone, val, 0.0);
75    e_config->backlight.normal = val;
76    e_config_save_queue();
77 }
78
79 static Eina_Bool
80 _backlight_win_key_down_cb(void *data, Ecore_Event_Key *ev)
81 {
82    Instance *inst = data;
83    const char *keysym;
84    
85    keysym = ev->key;
86    if (!strcmp(keysym, "Escape"))
87       _backlight_popup_free(inst);
88    else if ((!strcmp(keysym, "Up")) ||
89             (!strcmp(keysym, "Left")) ||
90             (!strcmp(keysym, "KP_Up")) ||
91             (!strcmp(keysym, "KP_Left")) ||
92             (!strcmp(keysym, "w")) ||
93             (!strcmp(keysym, "d")) ||
94             (!strcmp(keysym, "bracketright")) ||
95             (!strcmp(keysym, "Prior")))
96      {
97         _backlight_level_set(inst, inst->val + 0.1, EINA_TRUE);
98         _backlight_gadget_update(inst);
99      }
100    else if ((!strcmp(keysym, "Down")) ||
101             (!strcmp(keysym, "Right")) ||
102             (!strcmp(keysym, "KP_Down")) ||
103             (!strcmp(keysym, "KP_Right")) ||
104             (!strcmp(keysym, "s")) ||
105             (!strcmp(keysym, "a")) ||
106             (!strcmp(keysym, "bracketleft")) ||
107             (!strcmp(keysym, "Next")))
108      {
109         _backlight_level_set(inst, inst->val - 0.1, EINA_TRUE);
110         _backlight_gadget_update(inst);
111      }
112    else if ((!strcmp(keysym, "0")) ||
113             (!strcmp(keysym, "1")) ||
114             (!strcmp(keysym, "2")) ||
115             (!strcmp(keysym, "3")) ||
116             (!strcmp(keysym, "4")) ||
117             (!strcmp(keysym, "5")) ||
118             (!strcmp(keysym, "6")) ||
119             (!strcmp(keysym, "7")) ||
120             (!strcmp(keysym, "8")) ||
121             (!strcmp(keysym, "9")))
122      {
123         _backlight_level_set(inst, (double)atoi(keysym) / 9.0, EINA_TRUE);
124         _backlight_gadget_update(inst);
125      }
126    else
127      {
128         Eina_List *l;
129         E_Config_Binding_Key *binding;
130         E_Binding_Modifier mod;
131
132         EINA_LIST_FOREACH(e_bindings->key_bindings, l, binding)
133           {
134              if (binding->action && strcmp(binding->action, "backlight")) continue;
135              
136              mod = 0;
137              
138              if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
139                 mod |= E_BINDING_MODIFIER_SHIFT;
140              if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
141                 mod |= E_BINDING_MODIFIER_CTRL;
142              if (ev->modifiers & ECORE_EVENT_MODIFIER_ALT)
143                 mod |= E_BINDING_MODIFIER_ALT;
144              if (ev->modifiers & ECORE_EVENT_MODIFIER_WIN)
145                 mod |= E_BINDING_MODIFIER_WIN;
146              
147              if (binding->key && (!strcmp(binding->key, ev->key)) &&
148                  ((binding->modifiers == mod) || (binding->any_mod)))
149                {
150                   _backlight_popup_free(inst);
151                   break;
152                }
153           }
154      }
155    return ECORE_CALLBACK_PASS_ON;
156 }
157
158 static void
159 _backlight_settings_cb(void *d1, void *d2 __UNUSED__)
160 {
161    Instance *inst = d1;
162    e_configure_registry_call("screen/power_management", NULL, NULL);
163    _backlight_popup_free(inst);
164 }
165
166 static void
167 _slider_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
168 {
169    Instance *inst = data;
170    _backlight_level_set(inst, inst->val, EINA_FALSE);
171 }
172
173 static void
174 _backlight_popup_del_cb(void *obj)
175 {
176    _backlight_popup_free(e_object_data_get(obj));
177 }
178
179 static void
180 _backlight_popup_comp_del_cb(void *data, Evas_Object *obj EINA_UNUSED)
181 {
182    _backlight_popup_free(data);
183 }
184
185 static void
186 _backlight_popup_new(Instance *inst)
187 {
188    Evas *evas;
189    Evas_Object *o;
190    
191    if (inst->popup) return;
192
193    e_backlight_update();
194    e_backlight_mode_set(inst->gcc->gadcon->zone, E_BACKLIGHT_MODE_NORMAL);
195    inst->val = e_backlight_level_get(inst->gcc->gadcon->zone);
196    _backlight_gadget_update(inst);
197    
198    inst->popup = e_gadcon_popup_new(inst->gcc, 0);
199    evas = e_comp_get(inst->popup)->evas;
200    
201    inst->o_table = e_widget_table_add(evas, 0);
202
203    o = e_widget_slider_add(evas, 0, 0, NULL, 0.1, 1.0, 0.05, 0, &(inst->val), NULL, 100);
204    evas_object_smart_callback_add(o, "changed", _slider_cb, inst);
205    inst->o_slider = o;
206    e_widget_table_object_align_append(inst->o_table, o, 
207                                       0, 0, 1, 1, 0, 0, 0, 0, 0.5, 0.5);
208    
209    o = e_widget_button_add(evas, NULL, "preferences-system",
210                            _backlight_settings_cb, inst, NULL);
211    e_widget_table_object_align_append(inst->o_table, o, 
212                                       0, 1, 1, 1, 0, 0, 0, 0, 0.5, 1.0);
213    
214    e_gadcon_popup_content_set(inst->popup, inst->o_table);
215    e_gadcon_popup_show(inst->popup);
216    e_comp_object_util_autoclose(inst->popup->comp_object, _backlight_popup_comp_del_cb,
217      _backlight_win_key_down_cb, inst);
218    e_object_data_set(E_OBJECT(inst->popup), inst);
219    E_OBJECT_DEL_SET(inst->popup, _backlight_popup_del_cb);
220 }
221
222 static void
223 _backlight_popup_free(Instance *inst)
224 {
225    E_FREE_FUNC(inst->popup, e_object_del);
226 }
227
228 static void
229 _backlight_menu_cb_cfg(void *data, E_Menu *menu __UNUSED__, E_Menu_Item *mi __UNUSED__)
230 {
231    Instance *inst = data;
232
233    _backlight_popup_free(inst);
234    e_configure_registry_call("screen/power_management", NULL, NULL);
235 }
236
237 static void
238 _backlight_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
239 {
240    Instance *inst = data;
241    Evas_Event_Mouse_Down *ev = event;
242    
243    if (ev->button == 1)
244      {
245         if (inst->popup) _backlight_popup_free(inst);
246         else _backlight_popup_new(inst);
247      }
248    else if (ev->button == 3)
249      {
250         E_Zone *zone;
251         E_Menu *m;
252         E_Menu_Item *mi;
253         int x, y;
254         
255         zone = e_util_zone_current_get(e_manager_current_get());
256         
257         m = e_menu_new();
258         
259         mi = e_menu_item_new(m);
260         e_menu_item_label_set(mi, _("Settings"));
261         e_util_menu_item_theme_icon_set(mi, "configure");
262         e_menu_item_callback_set(mi, _backlight_menu_cb_cfg, inst);
263         
264         m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
265         
266         e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL);
267         e_menu_activate_mouse(m, zone, x + ev->output.x, y + ev->output.y,
268                               1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
269         evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
270                                  EVAS_BUTTON_NONE, ev->timestamp, NULL);
271      }
272 }
273
274 static void
275 _backlight_cb_mouse_wheel(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
276 {
277    Evas_Event_Mouse_Wheel *ev = event;
278    Instance *inst = data;
279
280    inst->val = e_backlight_level_get(inst->gcc->gadcon->zone);
281    if (ev->z > 0)
282      _backlight_level_set(inst, inst->val - 0.1, EINA_FALSE);
283    else if (ev->z < 0)
284      _backlight_level_set(inst, inst->val + 0.1, EINA_FALSE);
285 }
286
287 static E_Gadcon_Client *
288 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
289 {
290    Evas_Object *o;
291    E_Gadcon_Client *gcc;
292    Instance *inst;
293    
294    inst = E_NEW(Instance, 1);
295
296    o = edje_object_add(gc->evas);
297    e_theme_edje_object_set(o, "base/theme/modules/backlight",
298                            "e/modules/backlight/main");
299    evas_object_show(o);
300    
301    gcc = e_gadcon_client_new(gc, name, id, style, o);
302    gcc->data = inst;
303    
304    inst->gcc = gcc;
305    inst->o_backlight = o;
306
307    e_backlight_update();
308    inst->val = e_backlight_level_get(inst->gcc->gadcon->zone);
309    _backlight_gadget_update(inst);
310    
311    evas_object_event_callback_add(inst->o_backlight, 
312                                   EVAS_CALLBACK_MOUSE_DOWN,
313                                   _backlight_cb_mouse_down,
314                                   inst);
315    evas_object_event_callback_add(inst->o_backlight, 
316                                   EVAS_CALLBACK_MOUSE_WHEEL,
317                                   _backlight_cb_mouse_wheel,
318                                   inst);
319    
320    backlight_instances = eina_list_append(backlight_instances, inst);
321    return gcc;
322 }
323
324 static void
325 _gc_shutdown(E_Gadcon_Client *gcc)
326 {
327    Instance *inst;
328    
329    inst = gcc->data;
330    _backlight_popup_free(inst);
331    backlight_instances = eina_list_remove(backlight_instances, inst);
332    evas_object_del(inst->o_backlight);
333    free(inst);
334 }
335
336 static void
337 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient __UNUSED__)
338 {
339    Instance *inst;
340    Evas_Coord mw, mh;
341    
342    inst = gcc->data;
343    mw = 0, mh = 0;
344    edje_object_size_min_get(inst->o_backlight, &mw, &mh);
345    if ((mw < 1) || (mh < 1))
346      edje_object_size_min_calc(inst->o_backlight, &mw, &mh);
347    if (mw < 4) mw = 4;
348    if (mh < 4) mh = 4;
349    e_gadcon_client_aspect_set(gcc, mw, mh);
350    e_gadcon_client_min_size_set(gcc, mw, mh);
351 }
352
353 static const char *
354 _gc_label(const E_Gadcon_Client_Class *client_class __UNUSED__)
355 {
356    return _("Backlight");
357 }
358
359 static Evas_Object *
360 _gc_icon(const E_Gadcon_Client_Class *client_class __UNUSED__, Evas *evas)
361 {
362    Evas_Object *o;
363    char buf[4096];
364    
365    o = edje_object_add(evas);
366    snprintf(buf, sizeof(buf), "%s/e-module-backlight.edj",
367             e_module_dir_get(backlight_module));
368    edje_object_file_set(o, buf, "icon");
369    return o;
370 }
371
372 static const char *
373 _gc_id_new(const E_Gadcon_Client_Class *client_class)
374 {
375    static char buf[4096];
376
377    snprintf(buf, sizeof(buf), "%s.%d", client_class->name, 
378             eina_list_count(backlight_instances) + 1);
379    return buf;
380 }
381
382 static Eina_Bool
383 _backlight_popup_timer_cb(void *data)
384 {
385    Instance *inst;
386    inst = data;
387
388    if (inst->popup)
389       _backlight_popup_del_cb(inst->popup);
390    inst->popup_timer = NULL;
391
392    return ECORE_CALLBACK_CANCEL;
393 }
394
395 static void
396 _backlight_popup_timer_new(Instance *inst)
397 {
398    if (inst->popup)
399      {
400         if (inst->popup_timer)
401           {
402              ecore_timer_del(inst->popup_timer);
403              e_widget_slider_value_double_set(inst->o_slider, inst->val);
404              inst->popup_timer = ecore_timer_add(1.0, _backlight_popup_timer_cb, inst);
405           }
406      }
407    else
408      {
409         _backlight_popup_new(inst);
410         inst->popup_timer = ecore_timer_add(1.0, _backlight_popup_timer_cb, inst);
411      }
412 }
413
414 static void
415 _e_mod_action_cb(E_Object *obj __UNUSED__,
416                  const char *params)
417 {
418    Eina_List *l;
419    Instance *inst;
420    
421    EINA_LIST_FOREACH(backlight_instances, l, inst)
422      {
423         if (!params)
424           {
425              if (inst->popup) _backlight_popup_free(inst);
426              else _backlight_popup_new(inst);
427           }
428         else
429           {
430              _backlight_level_set(inst, inst->val + atof(params), EINA_FALSE);
431              _backlight_popup_timer_new(inst);
432           }
433      }
434 }
435
436 static Eina_Bool
437 _backlight_cb_mod_init_end(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
438 {
439    Eina_List *l;
440    Instance *inst;
441
442    e_backlight_update();
443    EINA_LIST_FOREACH(backlight_instances, l, inst)
444      {
445         inst->val = e_backlight_level_get(inst->gcc->gadcon->zone);
446         _backlight_gadget_update(inst);
447      }
448    return ECORE_CALLBACK_RENEW;
449 }
450
451 static Eina_Bool
452 _backlight_cb_changed(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
453 {
454    Eina_List *l;
455    Instance *inst;
456
457    EINA_LIST_FOREACH(backlight_instances, l, inst)
458      {
459         inst->val = e_backlight_level_get(inst->gcc->gadcon->zone);
460         _backlight_gadget_update(inst);
461      }
462    return ECORE_CALLBACK_RENEW;
463 }
464
465 /* module setup */
466 EAPI E_Module_Api e_modapi =
467 {
468    E_MODULE_API_VERSION,
469      "Backlight"
470 };
471
472 EAPI void *
473 e_modapi_init(E_Module *m)
474 {
475    backlight_module = m;
476    e_gadcon_provider_register(&_gadcon_class);
477    E_LIST_HANDLER_APPEND(handlers, E_EVENT_BACKLIGHT_CHANGE, _backlight_cb_changed, NULL);
478    E_LIST_HANDLER_APPEND(handlers, E_EVENT_MODULE_INIT_END, _backlight_cb_mod_init_end, NULL);
479    act = e_action_add("backlight");
480    if (act)
481      {
482         act->func.go = _e_mod_action_cb;
483         e_action_predef_name_set(N_("Screen"), N_("Backlight Controls"), "backlight",
484                                  NULL, "syntax: brightness change(-1.0 - 1.0), example: -0.1", 1);
485      }
486    return m;
487 }
488
489 EAPI int
490 e_modapi_shutdown(E_Module *m __UNUSED__)
491 {
492    if (act)
493      {
494         e_action_predef_name_del("Screen", "Backlight Controls");
495         e_action_del("backlight");
496         act = NULL;
497      }
498    E_FREE_LIST(handlers, ecore_event_handler_del);
499    e_gadcon_provider_unregister(&_gadcon_class);
500    return 1;
501 }
502
503 EAPI int
504 e_modapi_save(E_Module *m __UNUSED__)
505 {
506    return 1;
507 }