6 // FIXME: backlight should be tied per zone but this implementation is just
7 // a signleton right now as thats 99% of use cases. but api supports
8 // doing more. for now make it work in the singleton
14 static double bl_val = 1.0;
15 static double bl_animval = 1.0;
16 static int sysmode = MODE_NONE;
17 static Ecore_Animator *bl_anim = NULL;
18 static Eina_List *bl_devs = NULL;
20 static Ecore_Event_Handler *_e_backlight_handler_config_mode = NULL;
21 static Ecore_Event_Handler *_e_backlight_handler_border_fullscreen = NULL;
22 static Ecore_Event_Handler *_e_backlight_handler_border_unfullscreen = NULL;
23 static Ecore_Event_Handler *_e_backlight_handler_border_remove = NULL;
24 static Ecore_Event_Handler *_e_backlight_handler_border_iconify = NULL;
25 static Ecore_Event_Handler *_e_backlight_handler_border_uniconify = NULL;
26 static Ecore_Event_Handler *_e_backlight_handler_border_desk_set = NULL;
27 static Ecore_Event_Handler *_e_backlight_handler_desk_show = NULL;
29 static Ecore_Timer *_e_backlight_timer = NULL;
31 static void _e_backlight_update(E_Zone *zone);
32 static void _e_backlight_set(E_Zone *zone, double val);
33 static Eina_Bool _bl_anim(void *data, double pos);
34 static Eina_Bool bl_avail = EINA_FALSE;
35 static Eina_Bool _e_backlight_handler(void *d, int type, void *ev);
36 static Eina_Bool _e_backlight_timer_cb(void *d);
38 static const char *bl_sysval = NULL;
39 static Ecore_Event_Handler *bl_sys_exit_handler = NULL;
40 static Ecore_Exe *bl_sys_set_exe = NULL;
41 static Eina_Bool bl_sys_pending_set = EINA_FALSE;
42 static Eina_Bool bl_sys_set_exe_ready = EINA_TRUE;
44 static void _bl_sys_find(void);
45 static void _bl_sys_level_get(void);
46 static Eina_Bool _e_bl_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event);
47 static void _bl_sys_level_set(double val);
51 e_backlight_init(void)
56 // why did someone do this? this makes it ONLY work if xrandr has bl support.
58 // bl_avail = ecore_x_randr_output_backlight_available();
61 _e_backlight_handler_config_mode = ecore_event_handler_add
62 (E_EVENT_CONFIG_MODE_CHANGED, _e_backlight_handler, NULL);
64 _e_backlight_handler_border_fullscreen = ecore_event_handler_add
65 (E_EVENT_BORDER_FULLSCREEN, _e_backlight_handler, NULL);
67 _e_backlight_handler_border_unfullscreen = ecore_event_handler_add
68 (E_EVENT_BORDER_UNFULLSCREEN, _e_backlight_handler, NULL);
70 _e_backlight_handler_border_remove = ecore_event_handler_add
71 (E_EVENT_BORDER_REMOVE, _e_backlight_handler, NULL);
73 _e_backlight_handler_border_iconify = ecore_event_handler_add
74 (E_EVENT_BORDER_ICONIFY, _e_backlight_handler, NULL);
76 _e_backlight_handler_border_uniconify = ecore_event_handler_add
77 (E_EVENT_BORDER_UNICONIFY, _e_backlight_handler, NULL);
79 _e_backlight_handler_border_desk_set = ecore_event_handler_add
80 (E_EVENT_BORDER_DESK_SET, _e_backlight_handler, NULL);
82 _e_backlight_handler_desk_show = ecore_event_handler_add
83 (E_EVENT_DESK_SHOW, _e_backlight_handler, NULL);
88 if (!getenv("E_RESTART"))
90 e_backlight_level_set(NULL, 0.0, 0.0);
91 e_backlight_level_set(NULL, e_config->backlight.normal, 1.0);
98 e_backlight_shutdown(void)
102 if (bl_anim) ecore_animator_del(bl_anim);
104 EINA_LIST_FREE(bl_devs, s) eina_stringshare_del(s);
106 if (bl_sysval) eina_stringshare_del(bl_sysval);
108 if (bl_sys_exit_handler) ecore_event_handler_del(bl_sys_exit_handler);
109 bl_sys_exit_handler = NULL;
110 bl_sys_set_exe = NULL;
111 bl_sys_pending_set = EINA_FALSE;
114 if (_e_backlight_handler_config_mode)
116 ecore_event_handler_del(_e_backlight_handler_config_mode);
117 _e_backlight_handler_config_mode = NULL;
120 if (_e_backlight_handler_border_fullscreen)
122 ecore_event_handler_del(_e_backlight_handler_border_fullscreen);
123 _e_backlight_handler_border_fullscreen = NULL;
126 if (_e_backlight_handler_border_unfullscreen)
128 ecore_event_handler_del(_e_backlight_handler_border_unfullscreen);
129 _e_backlight_handler_border_unfullscreen = NULL;
132 if (_e_backlight_handler_border_remove)
134 ecore_event_handler_del(_e_backlight_handler_border_remove);
135 _e_backlight_handler_border_remove = NULL;
138 if (_e_backlight_handler_border_iconify)
140 ecore_event_handler_del(_e_backlight_handler_border_iconify);
141 _e_backlight_handler_border_iconify = NULL;
144 if (_e_backlight_handler_border_uniconify)
146 ecore_event_handler_del(_e_backlight_handler_border_uniconify);
147 _e_backlight_handler_border_uniconify = NULL;
150 if (_e_backlight_handler_border_desk_set)
152 ecore_event_handler_del(_e_backlight_handler_border_desk_set);
153 _e_backlight_handler_border_desk_set = NULL;
156 if (_e_backlight_handler_desk_show)
158 ecore_event_handler_del(_e_backlight_handler_desk_show);
159 _e_backlight_handler_desk_show = NULL;
165 e_backlight_exists(void)
167 if (sysmode == MODE_NONE) return EINA_FALSE;
172 e_backlight_update(void)
174 Eina_List *m, *c, *z;
179 if (bl_avail == EINA_FALSE) return;
181 EINA_LIST_FOREACH(e_manager_list(), m, man)
183 EINA_LIST_FOREACH(man->containers, c, con)
185 EINA_LIST_FOREACH(con->zones, z, zone)
187 _e_backlight_update(zone);
192 /* idle dimming disabled: clear timer */
193 if (!e_config->backlight.idle_dim)
195 if (_e_backlight_timer)
196 ecore_timer_del(_e_backlight_timer);
197 _e_backlight_timer = NULL;
200 /* dimming enabled, timer active: update interval and reset */
201 if (_e_backlight_timer)
203 if (e_config->backlight.timer != ecore_timer_interval_get(_e_backlight_timer))
204 ecore_timer_interval_set(_e_backlight_timer, e_config->backlight.timer);
205 ecore_timer_reset(_e_backlight_timer);
208 /* dimming enabled, timer inactive: */
210 /* timer is 0 seconds: return */
211 if (!e_config->backlight.timer) return;
212 /* current mode is dimmed: undim */
213 if (e_config->backlight.mode == E_BACKLIGHT_MODE_DIM)
214 e_backlight_mode_set(NULL, E_BACKLIGHT_MODE_NORMAL);
215 _e_backlight_timer = ecore_timer_add(e_config->backlight.timer, _e_backlight_timer_cb, NULL);
219 e_backlight_level_set(E_Zone *zone, double val, double tim)
222 // zone == NULL == everything
223 // set backlight associated with zone to val over period of tim
224 // if tim == 0.0 - then do it instantnly, if time == -1 use some default
226 if (val < 0.0) val = 0.0;
227 else if (val > 1.0) val = 1.0;
228 if (val == bl_val) return;
229 if (!zone) zone = e_util_zone_current_get(e_manager_current_get());
232 if (e_config->backlight.mode != E_BACKLIGHT_MODE_NORMAL) return;
233 if (tim < 0.0) tim = e_config->backlight.transition;
238 ecore_animator_del(bl_anim);
241 _e_backlight_set(zone, val);
244 if (bl_anim) ecore_animator_del(bl_anim);
245 bl_anim = ecore_animator_timeline_add(tim, _bl_anim, zone);
250 e_backlight_level_get(E_Zone *zone __UNUSED__)
252 // zone == NULL == everything
257 e_backlight_mode_set(E_Zone *zone, E_Backlight_Mode mode)
259 // zone == NULL == everything
260 if (e_config->backlight.mode == mode) return;
261 e_config->backlight.mode = mode;
262 if (e_config->backlight.mode == E_BACKLIGHT_MODE_NORMAL)
263 e_backlight_level_set(zone, bl_val, -1.0);
264 else if (e_config->backlight.mode == E_BACKLIGHT_MODE_OFF)
265 e_backlight_level_set(zone, 0.0, -1.0);
266 else if (e_config->backlight.mode == E_BACKLIGHT_MODE_DIM)
267 e_backlight_level_set(zone, e_config->backlight.dim, -1.0);
268 else if (e_config->backlight.mode == E_BACKLIGHT_MODE_MAX)
269 e_backlight_level_set(zone, 1.0, -1.0);
272 EAPI E_Backlight_Mode
273 e_backlight_mode_get(E_Zone *zone __UNUSED__)
275 // zone == NULL == everything
276 return e_config->backlight.mode;
279 EAPI const Eina_List *
280 e_backlight_devices_get(void)
285 /* local subsystem functions */
288 _e_backlight_handler(void *d __UNUSED__, int type __UNUSED__, void *ev __UNUSED__)
290 e_backlight_update();
291 return ECORE_CALLBACK_PASS_ON;
295 _e_backlight_timer_cb(void *d __UNUSED__)
297 e_backlight_mode_set(NULL, E_BACKLIGHT_MODE_DIM);
298 _e_backlight_timer = NULL;
303 _e_backlight_update(E_Zone *zone)
307 Ecore_X_Randr_Output *out;
310 root = zone->container->manager->root;
312 out = ecore_x_randr_window_outputs_get(root, &num);
313 if ((out) && (num > 0) && (ecore_x_randr_output_backlight_available()))
317 Eina_Bool gotten = EINA_FALSE;
319 EINA_LIST_FREE(bl_devs, s) eina_stringshare_del(s);
320 for (i = 0; i < num; i++)
322 name = ecore_x_randr_output_name_get(root, out[i], NULL);
323 bl_devs = eina_list_append(bl_devs, eina_stringshare_add(name));
324 if ((name) && (e_config->backlight.sysdev) &&
325 (!strcmp(name, e_config->backlight.sysdev)))
327 x_bl = ecore_x_randr_output_backlight_level_get(root, out[i]);
330 if (name) free(name);
333 x_bl = ecore_x_randr_output_backlight_level_get(root, out[0]);
339 sysmode = MODE_RANDR;
354 _e_backlight_set(E_Zone *zone, double val)
356 if (sysmode == MODE_RANDR)
359 Ecore_X_Randr_Output *out;
363 root = zone->container->manager->root;
364 out = ecore_x_randr_window_outputs_get(root, &num);
365 if ((out) && (num > 0))
367 Eina_Bool gotten = EINA_FALSE;
368 for (i = 0; i < num; i++)
370 name = ecore_x_randr_output_name_get(root, out[i], NULL);
373 if ((e_config->backlight.sysdev) &&
374 (!strcmp(name, e_config->backlight.sysdev)))
376 ecore_x_randr_output_backlight_level_set(root, out[i], val);
384 for (i = 0; i < num; i++)
385 ecore_x_randr_output_backlight_level_set(root, out[i], val);
391 else if (sysmode == MODE_SYS)
395 _bl_sys_level_set(val);
402 _bl_anim(void *data, double pos)
407 // FIXME: if zone is deleted while anim going... bad things.
408 pos = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
409 v = (bl_animval * (1.0 - pos)) + (bl_val *pos);
410 _e_backlight_set(zone, v);
423 Eina_List *l, *devs, *pdevs = NULL;
428 devs = eeze_udev_find_by_filter("backlight", NULL, NULL);
431 /* FIXME: need to make this more precise so we don't set keyboard LEDs or something */
432 devs = eeze_udev_find_by_filter("leds", NULL, NULL);
435 if (eina_list_count(devs) > 1)
437 /* prefer backlights of type "firmware" where available */
438 EINA_LIST_FOREACH(devs, l, f)
440 s = eeze_udev_syspath_get_sysattr(f, "type");
441 use = (s && (!strcmp(s, "firmware")));
442 eina_stringshare_del(s);
444 s = eeze_udev_syspath_get_sysattr(f, "brightness");
447 eina_stringshare_del(s);
449 pdevs = eina_list_append(pdevs, eina_stringshare_add(f));
450 eina_stringshare_del(f);
453 EINA_LIST_FOREACH(devs, l, f)
455 if (!l->data) continue;
456 s = eeze_udev_syspath_get_sysattr(f, "brightness");
459 eina_stringshare_del(s);
461 pdevs = eina_list_append(pdevs, eina_stringshare_add(f));
466 /* add the other backlight or led's if none found */
467 EINA_LIST_FOREACH(devs, l, f)
470 s = eeze_udev_syspath_get_sysattr(f, "brightness");
473 eina_stringshare_del(s);
475 pdevs = eina_list_append(pdevs, eina_stringshare_add(f));
478 /* clear out original devs list now we've filtered */
479 EINA_LIST_FREE(devs, f)
481 if (f) eina_stringshare_del(f);
483 /* clear out old configured bl sysval */
486 eina_stringshare_del(bl_sysval);
489 EINA_LIST_FREE(bl_devs, s) eina_stringshare_del(s);
490 /* if configured backlight is there - use it, or if not use first */
491 EINA_LIST_FOREACH(pdevs, l, f)
493 bl_devs = eina_list_append(bl_devs, eina_stringshare_add(f));
496 if ((e_config->backlight.sysdev) &&
497 (!strcmp(e_config->backlight.sysdev, f)))
498 bl_sysval = eina_stringshare_add(f);
500 bl_sysval = eina_stringshare_add(f);
505 EINA_LIST_FOREACH(pdevs, l, f)
508 bl_sysval = eina_stringshare_add(f);
511 /* clear out preferred devs list */
512 EINA_LIST_FREE(pdevs, f)
514 eina_stringshare_del(f);
519 _bl_sys_level_get(void)
524 str = eeze_udev_syspath_get_sysattr(bl_sysval, "max_brightness");
528 eina_stringshare_del(str);
529 if (maxval <= 0) maxval = 255;
530 str = eeze_udev_syspath_get_sysattr(bl_sysval, "brightness");
534 eina_stringshare_del(str);
535 if ((val >= 0) && (val <= maxval))
536 bl_val = (double)val / (double)maxval;
537 // printf("GET: %i/%i (%1.3f)\n", val, maxval, bl_val);
541 _e_bl_cb_ext_delay(void *data __UNUSED__)
543 bl_sys_set_exe_ready = EINA_TRUE;
544 if (bl_sys_pending_set)
546 bl_sys_pending_set = EINA_FALSE;
547 _bl_sys_level_set(bl_val);
553 _e_bl_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
555 Ecore_Exe_Event_Del *ev;
558 if (ev->exe == bl_sys_set_exe)
560 bl_sys_set_exe_ready = EINA_FALSE;
561 bl_sys_set_exe = NULL;
562 ecore_timer_add(0.1, _e_bl_cb_ext_delay, NULL);
564 return ECORE_CALLBACK_RENEW;
568 _bl_sys_level_set(double val)
572 if (!bl_sys_exit_handler)
573 bl_sys_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
574 _e_bl_cb_exit, NULL);
575 if ((bl_sys_set_exe) || (!bl_sys_set_exe_ready))
577 bl_sys_pending_set = EINA_TRUE;
580 // printf("SET: %1.3f\n", val);
581 snprintf(buf, sizeof(buf),
582 "%s/enlightenment/utils/enlightenment_backlight %i %s",
583 e_prefix_lib_get(), (int)(val * 1000.0), bl_sysval);
584 bl_sys_set_exe = ecore_exe_run(buf, NULL);