From ee393a201f881e0c0958096582d677e8faad2ec1 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Sat, 1 Feb 2020 11:01:22 +0000 Subject: [PATCH] e backlight - restructure to have real per screen backlight now it really does look for the right way to control per screen and only use the new e_system back-end to query/list devices etc. ... this now opens the door to adding ddc support to e_system then using it from e_backlight. i can't test this... yet - but this means in theory the backlight gadget will control the backlight of the screen it is on... --- src/bin/e_backlight.c | 985 +++++++++++++++++++++++------------------- src/bin/e_comp_x.c | 12 +- src/bin/e_config.h | 1 - src/bin/e_zone.h | 2 + 4 files changed, 541 insertions(+), 459 deletions(-) diff --git a/src/bin/e_backlight.c b/src/bin/e_backlight.c index 6ff1eaedc..8eb8faeda 100644 --- a/src/bin/e_backlight.c +++ b/src/bin/e_backlight.c @@ -1,190 +1,622 @@ #include "e.h" -#ifdef HAVE_EEZE -# include -#endif -#include -#ifdef __FreeBSD_kernel__ -# include -# include -# include -#endif -// FIXME: backlight should be tied per zone but this implementation is just -// a signleton right now as thats 99% of use cases. but api supports -// doing more. for now make it work in the singleton - -#define MODE_NONE -1 -#define MODE_RANDR 0 -#define MODE_SYS 1 - -EINTERN double e_bl_val = 1.0; -static double bl_animval = 1.0; -static double bl_anim_toval = 1.0; -static int sysmode = MODE_NONE; -static Ecore_Animator *bl_anim = NULL; -static Eina_List *bl_devs = NULL; - -static void _e_backlight_update(void); -static void _e_backlight_set(double val); -static Eina_Bool _bl_anim(void *data, double pos); -static Eina_Bool bl_avail = EINA_TRUE; -#ifndef HAVE_WAYLAND_ONLY -static Eina_Bool xbl_avail = EINA_FALSE; -#endif -#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) -const char *bl_sysval = NULL; - -static void _bl_sys_find(void); -static void _bl_sys_level_get(void); -static void _bl_sys_level_set(double val); -#endif -#ifdef __FreeBSD_kernel__ -static const char *bl_acpi_sysctl = "hw.acpi.video.lcd0.brightness"; -static int bl_mib[CTL_MAXNAME]; -static int bl_mib_len = -1; -#endif +typedef struct +{ + const char *dev; + const char *output; + const char *edid; + double val; + double from_val, to_val; + Ecore_Animator *anim; +} Backlight_Device; E_API int E_EVENT_BACKLIGHT_CHANGE = -1; +static Eina_List *bl_devs = NULL; +static Eina_List *handlers = NULL; +static Ecore_Job *zone_change_job = NULL; +static Eina_List *_devices = NULL; +static int _devices_pending_ops = 0; +static Eina_Bool _devices_zones_update = EINA_FALSE; + +static void +_backlight_system_get_cb(void *data, const char *params) +{ + char dev[1024]; + int val = 0; + double fval; + Backlight_Device *bd = data; + + if (!params) return; + if (sscanf(params, "%1023s %i", dev, &val) != 2) return; + if (!!strcmp(bd->dev, dev)) return; + e_system_handler_del("bklight-val", _backlight_system_get_cb, bd); + fval = (double)val / 1000.0; + if (fabs(fval - bd->val) >= DBL_EPSILON) + { + bd->val = fval; + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); + } +} + +static void +_backlight_devices_clear(void) +{ + Backlight_Device *bd; + + EINA_LIST_FREE(_devices, bd) + { + eina_stringshare_del(bd->dev); + eina_stringshare_del(bd->output); + eina_stringshare_del(bd->edid); + if (bd->anim) ecore_animator_del(bd->anim); + e_system_handler_del("bklight-val", _backlight_system_get_cb, bd); + free(bd); + } +} + +static Backlight_Device * +_backlight_devices_zone_device_find(E_Zone *zone) +{ + Eina_List *l; + Backlight_Device *bd; + char *tmp, *sep; + const char *out, *edid; + + if (!zone->randr2_id) return NULL; + tmp = strdup(zone->randr2_id); + if (!tmp) return NULL; + sep = strchr(tmp, '/'); + if (!sep) + { + free(tmp); + return NULL; + } + *sep = '\0'; + out = tmp; + edid = sep + 1; + EINA_LIST_FOREACH(_devices, l, bd) + { + if ((bd->output) && (!strcmp(out, bd->output))) + { + if ((edid[0] && (!strcmp(edid, bd->edid))) || (!edid[0])) + return bd; + } + } + return NULL; +} + +#ifndef HAVE_WAYLAND_ONLY +static const char * +_backlight_devices_randr_out_edid_str_get(Ecore_X_Window root, Ecore_X_Randr_Output *out) +{ + const char *str = NULL; + unsigned long edid_len = 0; + unsigned char *edid = ecore_x_randr_output_edid_get(root, *out, &edid_len); + if (edid) + { + char *edid_str = malloc((edid_len * 2) + 1); + + if (edid_str) + { + const char *hexch = "0123456789abcdef"; + char *dc = edid_str; + unsigned long i; + + for (i = 0; i < edid_len; i++) + { + dc[0] = hexch[(edid[i] >> 4) & 0xf]; + dc[1] = hexch[(edid[i] ) & 0xf]; + dc += 2; + } + *dc = 0; + str = eina_stringshare_add(edid_str); + free(edid_str); + } + free(edid); + } + return str; +} + +static Ecore_X_Randr_Output +_backlight_devices_randr_output_get(Ecore_X_Window root, const char *output, const char *edid) +{ + Ecore_X_Randr_Output *out; + int i, num = 0; + + out = ecore_x_randr_window_outputs_get(root, &num); + if ((out) && (num > 0)) + { + for (i = 0; i < num; i++) + { + char *name = ecore_x_randr_output_name_get(root, out[i], NULL); + if (!name) continue; + const char *edid_str = _backlight_devices_randr_out_edid_str_get(root, &(out[i])); + if (edid_str) + { + if ((!strcmp(output, name)) && (!strcmp(edid, edid_str))) + { + eina_stringshare_del(edid_str); + free(name); + return out[i]; + } + eina_stringshare_del(edid_str); + } + free(name); + } + } + return 0; +} +#endif + +static void +_backlight_devices_device_set(Backlight_Device *bd, double val) +{ + bd->val = val; +#ifndef HAVE_WAYLAND_ONLY + if (!strcmp(bd->dev, "randr")) + { + if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X) && (e_comp->root)) + { + Ecore_X_Randr_Output o = _backlight_devices_randr_output_get(e_comp->root, bd->output, bd->edid); + if (o) + { + ecore_x_randr_output_backlight_level_set(e_comp->root, o, bd->val); + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); + } + } + } + else +#endif + if (!strncmp(bd->dev, "ddc:", 4)) + { + // XXX: implement ddc support + } + else + { + e_system_send("bklight-set", "%s %i", bd->dev, (int)(bd->val * 1000.0)); + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); + } +} + +static E_Zone * +_backlight_devices_device_zone_get(Backlight_Device *bd) +{ + char buf[1024]; + Eina_List *l; + E_Zone *zone; + + snprintf(buf, sizeof(buf), "%s/%s", bd->output? bd->output: "", bd->edid ? bd->edid : ""); + EINA_LIST_FOREACH(e_comp->zones, l, zone) + { + if (!strcmp(zone->randr2_id, buf)) return zone; + } + return NULL; +} + +static void +_backlight_devices_device_update(Backlight_Device *bd) +{ + if (!bd->dev) return; +#ifndef HAVE_WAYLAND_ONLY + if (!strcmp(bd->dev, "randr")) + { + if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X) && (e_comp->root)) + { + Ecore_X_Randr_Output o = _backlight_devices_randr_output_get(e_comp->root, bd->output, bd->edid); + if (o) + { + double x_bl = ecore_x_randr_output_backlight_level_get(e_comp->root, o); + if ((x_bl >= 0.0) && (fabs(x_bl - bd->val) >= DBL_EPSILON)) + { + bd->val = x_bl; + E_Zone *zone = _backlight_devices_device_zone_get(bd); + if (zone) zone->bl = bd->val; + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); + } + } + } + } + else +#endif + if (!strncmp(bd->dev, "ddc:", 4)) + { + // XXX: implement ddc support + } + else + { + e_system_handler_add("bklight-val", _backlight_system_get_cb, bd); + e_system_send("bklight-get", "%s", bd->dev); + } +} + +static void +_backlight_devices_update(void) +{ + Eina_List *l; + Backlight_Device *bd; + + EINA_LIST_FOREACH(_devices, l, bd) + _backlight_devices_device_update(bd); +} + +static void +_backlight_devices_pending_done(void) +{ + _devices_pending_ops--; + if (_devices_pending_ops > 0) return; + _backlight_devices_update(); +} + +static E_Randr2_Screen * +_backlight_devices_screen_lid_get(void) +{ + Eina_List *l; + E_Randr2_Screen *sc; + + if (!e_randr2) return NULL; + EINA_LIST_FOREACH(e_randr2->screens, l, sc) + { + if (sc->info.is_lid) return sc; + } + return NULL; +} + +static Backlight_Device * +_backlight_devices_edid_find(const char *edid) +{ + Eina_List *l; + Backlight_Device *bd; + + EINA_LIST_FOREACH(_devices, l, bd) + { + if ((bd->edid) && (edid) && (!strcmp(edid, bd->edid))) + return bd; + } + return NULL; +} + +static void +_backlight_devices_lid_register(const char *dev, Eina_Bool force) +{ + E_Randr2_Screen *sc = _backlight_devices_screen_lid_get(); + Backlight_Device *bd; + if (!sc) return; + bd = _backlight_devices_edid_find(sc->info.edid); + if (!bd) + { + bd = calloc(1, sizeof(Backlight_Device)); + if (!bd) return; + bd->edid = eina_stringshare_add(sc->info.edid); + bd->output = eina_stringshare_add(sc->info.name); + _devices = eina_list_append(_devices, bd); + } + if (bd->dev) + { + if (!strcmp(bd->dev, "randr")) return; // randr devices win + if (!strncmp(bd->dev, "ddc:", 4)) return; // ddc devices also beat these "sys" devices + } + // if bl device has a device assigned and we're not forcing a change + // then skip assigning this device to the backlight device + if ((bd->dev) && (!force)) return; + eina_stringshare_replace(&(bd->dev), dev); +} + +static void +_backlight_system_list_cb(void *data EINA_UNUSED, const char *params) +{ + // params "dev flag dev flag ..." + const char *p = params, *s; + char dev[1024], flag, devnum = 0; + + e_system_handler_del("bklight-list", _backlight_system_list_cb, NULL); + EINA_LIST_FREE(bl_devs, s) + eina_stringshare_del(s); +#ifndef HAVE_WAYLAND_ONLY + if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X)) + { + if (ecore_x_randr_output_backlight_available()) + bl_devs = eina_list_append(bl_devs, eina_stringshare_add("randr")); + } +#endif + while ((p) && (*p)) + { + if (sscanf(p, "%1023s", dev) == 1) + { + p += strlen(dev); + if (*p == ' ') + { + p++; + flag = *p; + if (flag) + { + bl_devs = eina_list_append + (bl_devs, eina_stringshare_add(dev)); + if ((devnum == 0) || (flag == 'p') || + (strstr(dev, "/drm/")) || + (strstr(dev, ".video."))) + { + _backlight_devices_lid_register(dev, EINA_TRUE); + } + else + { + // XXX: what to do with other bl devices? + // for now just assign spare bl devices to screens that do not have one already + _backlight_devices_lid_register(dev, EINA_FALSE); + } + devnum++; + // XXX: find bed bl dev for screens not supporting randr + // note that this is a vallback and ddc should take precedence + // it matched up to a screen over this, but randr shoule be + // the top priority if found + } + else break; + p++; + if (*p != ' ') break; + p++; + if (*p == '\0') break; + } + else break; + } + else break; + } + _backlight_devices_pending_done(); +} + +static void +_backlight_devices_probe(void) +{ + _backlight_devices_clear(); +#ifndef HAVE_WAYLAND_ONLY + // pass 1: if in x look at all the randr outputs to see if they have some backlight + // property to swizzle then make the randr device the kind of device to use - + // record this in our devices list + if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X)) + { + Eina_Bool avail = ecore_x_randr_output_backlight_available(); + if ((avail) && (e_comp->root)) + { + double x_bl; + Ecore_X_Window root = e_comp->root; + Ecore_X_Randr_Output *out; + int i, num = 0; + + out = ecore_x_randr_window_outputs_get(root, &num); + if ((out) && (num > 0)) + { + for (i = 0; i < num; i++) + { + char *name = ecore_x_randr_output_name_get(root, out[i], NULL); + if (!name) continue; + x_bl = ecore_x_randr_output_backlight_level_get(root, out[0]); + if (x_bl >= 0.0) + { + Backlight_Device *bd = calloc(1, sizeof(Backlight_Device)); + if (bd) + { + const char *edid_str = _backlight_devices_randr_out_edid_str_get(root, &(out[i])); + + if (edid_str) + { + bd->dev = eina_stringshare_add("randr"); + bd->output = eina_stringshare_add(name); + bd->edid = edid_str; + _devices = eina_list_append(_devices, bd); + } + else free(bd); + } + } + free(name); + } + } + free(out); + } + } +#endif + // ask enlightenment_system to list backlight devices. this is async so we have + // to respond to the device listing later + _devices_pending_ops++; + e_system_handler_add("bklight-list", _backlight_system_list_cb, NULL); + e_system_send("bklight-refresh", NULL); + e_system_send("bklight-list", NULL); + // XXXX: add ddc to e_syystem and query that too +} + +static Eina_Bool +_bl_anim(void *data, double pos) +{ + Backlight_Device *bd = data; + + // FIXME: if zone is deleted while anim going... bad things. + pos = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0); + bd->val = (bd->from_val * (1.0 - pos)) + (bd->to_val * pos); + _backlight_devices_device_set(bd, bd->val); + if (pos >= 1.0) + { + bd->anim = NULL; + _backlight_devices_device_update(bd); + return EINA_FALSE; + } + return EINA_TRUE; +} + +static void +_cb_job_zone_change(void *data EINA_UNUSED) +{ + zone_change_job = NULL; + _backlight_devices_probe(); + e_backlight_update(); +} + +static Eina_Bool +_cb_handler_zone_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *info EINA_UNUSED) +{ + if (zone_change_job) ecore_job_del(zone_change_job); + zone_change_job = ecore_job_add(_cb_job_zone_change, NULL); + return EINA_TRUE; +} + EINTERN int e_backlight_init(void) { -#ifdef HAVE_EEZE - eeze_init(); -#endif - -#ifndef HAVE_WAYLAND_ONLY - if (e_comp->comp_type == E_PIXMAP_TYPE_X) - xbl_avail = ecore_x_randr_output_backlight_available(); -#endif + E_EVENT_BACKLIGHT_CHANGE = ecore_event_type_new(); + _backlight_devices_probe(); +#define H(ev, cb) \ + handlers = eina_list_append(handlers, \ + ecore_event_handler_add(ev, cb, NULL)); + H(E_EVENT_ZONE_ADD, _cb_handler_zone_change); + H(E_EVENT_ZONE_DEL, _cb_handler_zone_change); + H(E_EVENT_ZONE_MOVE_RESIZE, _cb_handler_zone_change); + H(E_EVENT_ZONE_STOW, _cb_handler_zone_change); + H(E_EVENT_ZONE_UNSTOW, _cb_handler_zone_change); e_backlight_update(); if (!getenv("E_RESTART")) e_backlight_level_set(NULL, e_config->backlight.normal, 0.0); - - E_EVENT_BACKLIGHT_CHANGE = ecore_event_type_new(); - return 1; } EINTERN int e_backlight_shutdown(void) { + Ecore_Event_Handler *h; const char *s; - if (bl_anim) ecore_animator_del(bl_anim); - bl_anim = NULL; - - if (e_config->backlight.mode != E_BACKLIGHT_MODE_NORMAL) - e_backlight_level_set(NULL, e_config->backlight.normal, 0.0); - + if (zone_change_job) + { + ecore_job_del(zone_change_job); + zone_change_job = NULL; + } + EINA_LIST_FREE(handlers, h) + ecore_event_handler_del(h); EINA_LIST_FREE(bl_devs, s) eina_stringshare_del(s); -#ifdef HAVE_EEZE - if (bl_sysval) eina_stringshare_del(bl_sysval); - bl_sysval = NULL; - eeze_shutdown(); -#endif - + _backlight_devices_clear(); return 1; } E_API Eina_Bool e_backlight_exists(void) { - if (sysmode == MODE_NONE) return EINA_FALSE; + // XXX: properly check backlight devices return EINA_TRUE; } E_API void e_backlight_update(void) { - if (bl_avail == EINA_FALSE) return; - - _e_backlight_update(); + if (_devices_pending_ops > 0) _devices_zones_update = EINA_TRUE; + else _backlight_devices_update(); } E_API void e_backlight_level_set(E_Zone *zone, double val, double tim) { + Backlight_Device *bd; double bl_now; - // zone == NULL == everything + + if (!zone) // zone == NULL == everything + { + Eina_List *l; + + if (!e_comp) return; + EINA_LIST_FOREACH(e_comp->zones, l, zone) + e_backlight_level_set(zone, val, tim); + return; + } + bd = _backlight_devices_zone_device_find(zone); + if (!bd) return; // set backlight associated with zone to val over period of tim // if tim == 0.0 - then do it instantnly, if time == -1 use some default // transition time if ((!e_comp->screen) || (!e_comp->screen->backlight_enabled)) return; if (val < 0.0) val = 0.0; - else if (val > 1.0) - val = 1.0; - if ((fabs(val - e_bl_val) < DBL_EPSILON) && (!bl_anim)) return; - if (!zone) zone = e_zone_current_get(); - ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); - bl_now = e_bl_val; + else if (val > 1.0) val = 1.0; + if ((fabs(val - zone->bl) < DBL_EPSILON) && (!bd->anim)) return; + bl_now = zone->bl; - if (sysmode != MODE_RANDR) - e_bl_val = val; + zone->bl = val; if (fabs(tim) < DBL_EPSILON) { - _e_backlight_set(val); - e_backlight_update(); + _backlight_devices_device_set(bd, val); + _backlight_devices_device_update(bd); + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); return; } -// if (e_config->backlight.mode != E_BACKLIGHT_MODE_NORMAL) return; - if (e_config->backlight.mode == E_BACKLIGHT_MODE_NORMAL) - tim = 0.5; - else - if (tim < 0.0) - tim = e_config->backlight.transition; + if (zone->bl_mode == E_BACKLIGHT_MODE_NORMAL) tim = 0.5; + else if (tim < 0.0) tim = e_config->backlight.transition; - E_FREE_FUNC(bl_anim, ecore_animator_del); - bl_anim = ecore_animator_timeline_add(tim, _bl_anim, zone); - bl_animval = bl_now; - bl_anim_toval = val; + // XXX: store in bl device + E_FREE_FUNC(bd->anim, ecore_animator_del); + bd->anim = ecore_animator_timeline_add(tim, _bl_anim, bd); + bd->from_val = bl_now; + bd->to_val = val; } E_API double -e_backlight_level_get(E_Zone *zone EINA_UNUSED) +e_backlight_level_get(E_Zone *zone) { - // zone == NULL == everything - return e_bl_val; + Backlight_Device *bd; + + if (!zone) + { + zone = e_zone_current_get(); + if (!zone) return -1.0; + } + bd = _backlight_devices_zone_device_find(zone); + if (!bd) return -1.0; + zone->bl = bd->val; + return bd->val; } E_API void e_backlight_mode_set(E_Zone *zone, E_Backlight_Mode mode) { E_Backlight_Mode pmode; - - // zone == NULL == everything - if (e_config->backlight.mode == mode) return; + + if (!zone) // zone == NULL == everything + { + Eina_List *l; + + if (!e_comp) return; + EINA_LIST_FOREACH(e_comp->zones, l, zone) + e_backlight_mode_set(zone, mode); + return; + } + if (zone->bl_mode == mode) return; if (eina_streq(ecore_evas_engine_name_get(e_comp->ee), "buffer") || strstr(ecore_evas_engine_name_get(e_comp->ee), "wayland")) return; - pmode = e_config->backlight.mode; - e_config->backlight.mode = mode; - if (e_config->backlight.mode == E_BACKLIGHT_MODE_NORMAL) + pmode = zone->bl_mode; + zone->bl_mode = mode; + if (zone->bl_mode == E_BACKLIGHT_MODE_NORMAL) { e_backlight_level_set(zone, e_config->backlight.normal, -1.0); } - else if (e_config->backlight.mode == E_BACKLIGHT_MODE_OFF) + else if (zone->bl_mode == E_BACKLIGHT_MODE_OFF) { e_backlight_level_set(zone, 0.0, -1.0); } - else if (e_config->backlight.mode == E_BACKLIGHT_MODE_DIM) + else if (zone->bl_mode == E_BACKLIGHT_MODE_DIM) { if ((pmode != E_BACKLIGHT_MODE_NORMAL) || ((pmode == E_BACKLIGHT_MODE_NORMAL) && (e_config->backlight.normal > e_config->backlight.dim))) e_backlight_level_set(zone, e_config->backlight.dim, -1.0); } - else if (e_config->backlight.mode == E_BACKLIGHT_MODE_MAX) + else if (zone->bl_mode == E_BACKLIGHT_MODE_MAX) e_backlight_level_set(zone, 1.0, -1.0); } E_API E_Backlight_Mode -e_backlight_mode_get(E_Zone *zone EINA_UNUSED) +e_backlight_mode_get(E_Zone *zone) { - // zone == NULL == everything - return e_config->backlight.mode; + if (!zone) + { + zone = e_zone_current_get(); + if (!zone) return E_BACKLIGHT_MODE_NORMAL; + } + return zone->bl_mode; } E_API const Eina_List * @@ -192,344 +624,3 @@ e_backlight_devices_get(void) { return bl_devs; } - -/* local subsystem functions */ - -static void -_e_backlight_update(void) -{ -#ifndef HAVE_WAYLAND_ONLY - double x_bl = -1.0; - Ecore_X_Window root; - Ecore_X_Randr_Output *out; - int i, num = 0; - - if (!e_comp) return; - root = e_comp->root; - // try randr - if (root && xbl_avail) - { - out = ecore_x_randr_window_outputs_get(root, &num); - if ((out) && (num > 0)) - { - char *name; - Eina_Bool gotten = EINA_FALSE; - - E_FREE_LIST(bl_devs, eina_stringshare_del); - for (i = 0; i < num; i++) - { - Eina_Stringshare *n; - - name = ecore_x_randr_output_name_get(root, out[i], NULL); - if (!name) continue; - n = eina_stringshare_add(name); - free(name); - bl_devs = eina_list_append(bl_devs, n); - if (!e_util_strcmp(n, e_config->backlight.sysdev)) - { - x_bl = ecore_x_randr_output_backlight_level_get(root, out[i]); - gotten = EINA_TRUE; - } - } - if (!gotten) - x_bl = ecore_x_randr_output_backlight_level_get(root, out[0]); - } - free(out); - } - if (x_bl >= 0.0) - { - e_bl_val = x_bl; - sysmode = MODE_RANDR; - return; - } -#endif -#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) - _bl_sys_find(); - if (bl_sysval) - { - sysmode = MODE_SYS; -#ifndef HAVE_WAYLAND_ONLY - xbl_avail = EINA_FALSE; -#endif - _bl_sys_level_get(); - return; - } -#endif -} - -static void -_e_backlight_set(double val) -{ -#ifdef HAVE_WAYLAND_ONLY - if (0) - { - (void)val; - return; - } -#else - if (val < 0.05) val = 0.05; - if (sysmode == MODE_RANDR) - { - Ecore_X_Window root; - Ecore_X_Randr_Output *out; - int num = 0, i; - char *name; - - if (!e_comp) return; - root = e_comp->root; - out = ecore_x_randr_window_outputs_get(root, &num); - if ((out) && (num > 0)) - { - Eina_Bool gotten = EINA_FALSE; - if (e_config->backlight.sysdev) - { - for (i = 0; i < num; i++) - { - name = ecore_x_randr_output_name_get(root, out[i], NULL); - if (name) - { - if (!strcmp(name, e_config->backlight.sysdev)) - { - ecore_x_randr_output_backlight_level_set(root, out[i], val); - gotten = EINA_TRUE; - } - free(name); - } - } - } - if (!gotten) - { - for (i = 0; i < num; i++) - ecore_x_randr_output_backlight_level_set(root, out[i], val); - } - } - free(out); - } -#endif -#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) - else if (sysmode == MODE_SYS) - { - if (bl_sysval) - { - _bl_sys_level_set(val); - } - } -#endif -} - -static Eina_Bool -_bl_anim(void *data EINA_UNUSED, double pos) -{ - double v; - - // FIXME: if zone is deleted while anim going... bad things. - pos = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0); - v = (bl_animval * (1.0 - pos)) + (bl_anim_toval * pos); - _e_backlight_set(v); - if (pos >= 1.0) - { - bl_anim = NULL; - e_backlight_update(); - return EINA_FALSE; - } - return EINA_TRUE; -} - -#ifdef HAVE_EEZE -static void -_bl_sys_change(const char *device, Eeze_Udev_Event event EINA_UNUSED, void *data EINA_UNUSED, Eeze_Udev_Watch *watch EINA_UNUSED) -{ - if (device == bl_sysval) - { - _bl_sys_level_get(); - ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); - } - eina_stringshare_del(device); -} - -static void -_bl_sys_find(void) -{ - Eina_List *l, *devs, *pdevs = NULL; - Eina_Bool use; - const char *f, *s; - int v; - - devs = eeze_udev_find_by_filter("backlight", NULL, NULL); - if (!devs) - { - /* FIXME: need to make this more precise so we don't set keyboard LEDs or something */ - devs = eeze_udev_find_by_filter("leds", NULL, NULL); - if (!devs) return; - } - if (eina_list_count(devs) > 1) - { - /* prefer backlights of type "firmware" where available */ - EINA_LIST_FOREACH(devs, l, f) - { - use = eeze_udev_syspath_check_sysattr(f, "type", "firmware"); - if (!use) continue; - s = eeze_udev_syspath_get_sysattr(f, "brightness"); - if (!s) continue; - v = atoi(s); - eina_stringshare_del(s); - if (v < 0) continue; - pdevs = eina_list_append(pdevs, eina_stringshare_ref(f)); - eina_stringshare_del(f); - l->data = NULL; - } - EINA_LIST_FOREACH(devs, l, f) - { - if (!l->data) continue; - s = eeze_udev_syspath_get_sysattr(f, "brightness"); - if (!s) continue; - v = atoi(s); - eina_stringshare_del(s); - if (v < 0) continue; - pdevs = eina_list_append(pdevs, eina_stringshare_ref(f)); - } - } - if (!pdevs) - { - /* add the other backlight or led's if none found */ - EINA_LIST_FOREACH(devs, l, f) - { - use = EINA_FALSE; - s = eeze_udev_syspath_get_sysattr(f, "brightness"); - if (!s) continue; - v = atoi(s); - eina_stringshare_del(s); - if (v < 0) continue; - pdevs = eina_list_append(pdevs, eina_stringshare_ref(f)); - } - } - /* clear out original devs list now we've filtered */ - E_FREE_LIST(devs, eina_stringshare_del); - /* clear out old configured bl sysval */ - eina_stringshare_replace(&bl_sysval, NULL); - E_FREE_LIST(bl_devs, eina_stringshare_del); - /* if configured backlight is there - use it, or if not use first */ - EINA_LIST_FOREACH(pdevs, l, f) - { - bl_devs = eina_list_append(bl_devs, eina_stringshare_add(f)); - if (!bl_sysval) - { - if (!e_util_strcmp(e_config->backlight.sysdev, f)) - bl_sysval = eina_stringshare_ref(f); - } - } - if (!bl_sysval) - { - EINA_LIST_FOREACH(pdevs, l, f) - { - if ((!strstr(f, "kbd")) && (!strstr(f, "mail")) && (!strstr(f, "input"))) - { - bl_sysval = eina_stringshare_add(f); - break; - } - } - } - /* clear out preferred devs list */ - E_FREE_LIST(pdevs, eina_stringshare_del); - eeze_udev_watch_add(EEZE_UDEV_TYPE_BACKLIGHT, EEZE_UDEV_EVENT_CHANGE, _bl_sys_change, NULL); -} - -static void -_bl_sys_level_get(void) -{ - int maxval, val; - const char *str; - - if (bl_anim) return; - - str = eeze_udev_syspath_get_sysattr(bl_sysval, "max_brightness"); - if (!str) return; - - maxval = atoi(str); - eina_stringshare_del(str); - if (maxval < 0) maxval = 255; - str = eeze_udev_syspath_get_sysattr(bl_sysval, "brightness"); - if (!str) return; - - val = atoi(str); - eina_stringshare_del(str); - if ((!maxval) && (!val)) - { - e_bl_val = 0; - sysmode = MODE_NONE; - return; - } - if (!maxval) maxval = 255; - if ((val >= 0) && (val <= maxval)) - e_bl_val = (double)val / (double)maxval; -// fprintf(stderr, "GET: %i/%i (%1.3f)\n", val, maxval, e_bl_val); -} -#endif // HAVE_EEZE - -#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) -static void -_bl_sys_level_set(double val) -{ - e_system_send("bklight-set", "%s %i", bl_sysval, (int)(val * 1000.0)); -} -#endif // HAVE_EEZE || __FreeBSD_kernel__ - -#ifdef __FreeBSD_kernel__ -static void -_bl_sys_find(void) -{ - int rc; - size_t mlen; - - if (!bl_avail) return; - if (bl_mib_len >= 0) return; - - mlen = sizeof(bl_mib) / sizeof(bl_mib[0]); - rc = sysctlnametomib(bl_acpi_sysctl, bl_mib, &mlen); - if (rc < 0) - { - if (errno == ENOENT) ERR("ACPI brightness sysctl '%s' not found, consider 'kldload acpi_video'", bl_acpi_sysctl); - else ERR("sysctlnametomib(%s): %s(%d)", bl_acpi_sysctl, strerror(errno), errno); - - bl_avail = EINA_FALSE; - return; - } - bl_mib_len = (int)mlen; - sysmode = MODE_SYS; - eina_stringshare_replace(&bl_sysval, bl_acpi_sysctl); -} - -static void -_bl_sys_level_get(void) -{ - int rc, brightness; - size_t oldlen; - - if (!bl_avail) return; - if (bl_mib_len < 0) return; - - oldlen = sizeof(brightness); - rc = sysctl(bl_mib, bl_mib_len, &brightness, &oldlen, NULL, 0); - if (rc < 0) - { - ERR("Could not retrieve ACPI brightness: %s(%d)", strerror(errno), errno); - bl_avail = EINA_FALSE; - return; - } - if (oldlen != sizeof(brightness)) - { - // This really should not happen. - ERR("!!! Brightness sysctl changed size !!!"); - bl_avail = EINA_FALSE; - return; - } - if (brightness < 0 || brightness > 100) - { - // This really should not happen either. - ERR("!!! Brightness sysctl out of range !!!"); - bl_avail = EINA_FALSE; - return; - } - e_bl_val = (double)brightness / 100.; -} -#endif // __FreeBSD_kernel__ diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c index 33bf1b005..f6b93792f 100644 --- a/src/bin/e_comp_x.c +++ b/src/bin/e_comp_x.c @@ -75,7 +75,6 @@ static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 }; static int screen_size_index = -1; static Ecore_X_Atom backlight_atom = 0; -extern double e_bl_val; static Ecore_Timer *mouse_in_fix_check_timer = NULL; @@ -5293,17 +5292,8 @@ _e_comp_x_screensaver_notify_cb(void *data EINA_UNUSED, int type EINA_UNUSED, Ec static Eina_Bool _e_comp_x_backlight_notify_cb(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Randr_Output_Property_Notify *ev) { - double x_bl; - if (ev->property != backlight_atom) return ECORE_CALLBACK_RENEW; - x_bl = ecore_x_randr_output_backlight_level_get(0, ev->output); - - if (x_bl >= 0.0) - { - if (fabs(e_bl_val - x_bl) < DBL_EPSILON) - ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);; - e_bl_val = x_bl; - } + e_backlight_update(); return ECORE_CALLBACK_RENEW; } diff --git a/src/bin/e_config.h b/src/bin/e_config.h index 7bb7711a0..9e396476e 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -372,7 +372,6 @@ struct _E_Config double battery_timer; // GUI const char *sysdev; // GUI unsigned char idle_dim; // GUI - E_Backlight_Mode mode; /* not saved, display-only */ } backlight; struct diff --git a/src/bin/e_zone.h b/src/bin/e_zone.h index da08c9f42..93940a3be 100644 --- a/src/bin/e_zone.h +++ b/src/bin/e_zone.h @@ -62,6 +62,8 @@ struct _E_Zone /* formerly E_Comp_Zone */ Evas_Object *base; Evas_Object *over; + + E_Backlight_Mode bl_mode; double bl; Eina_Bool bloff;