summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-02-01 11:01:22 +0000
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-02-01 11:29:38 +0000
commitee393a201f881e0c0958096582d677e8faad2ec1 (patch)
tree8db08de507d20f8cbbd14e80ffe3ed4f6d93d936
parent1d7041b6ad69c24e4a9e2242b9f9656f38795ffe (diff)
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...
-rw-r--r--src/bin/e_backlight.c905
-rw-r--r--src/bin/e_comp_x.c12
-rw-r--r--src/bin/e_config.h1
-rw-r--r--src/bin/e_zone.h2
4 files changed, 501 insertions, 419 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,535 +1,626 @@
1#include "e.h" 1#include "e.h"
2#ifdef HAVE_EEZE
3# include <Eeze.h>
4#endif
5#include <sys/param.h>
6#ifdef __FreeBSD_kernel__
7# include <sys/sysctl.h>
8# include <errno.h>
9# include <string.h>
10#endif
11 2
12// FIXME: backlight should be tied per zone but this implementation is just 3typedef struct
13// a signleton right now as thats 99% of use cases. but api supports 4{
14// doing more. for now make it work in the singleton 5 const char *dev;
6 const char *output;
7 const char *edid;
8 double val;
9 double from_val, to_val;
10 Ecore_Animator *anim;
11} Backlight_Device;
15 12
16#define MODE_NONE -1 13E_API int E_EVENT_BACKLIGHT_CHANGE = -1;
17#define MODE_RANDR 0
18#define MODE_SYS 1
19 14
20EINTERN double e_bl_val = 1.0;
21static double bl_animval = 1.0;
22static double bl_anim_toval = 1.0;
23static int sysmode = MODE_NONE;
24static Ecore_Animator *bl_anim = NULL;
25static Eina_List *bl_devs = NULL; 15static Eina_List *bl_devs = NULL;
16static Eina_List *handlers = NULL;
17static Ecore_Job *zone_change_job = NULL;
18static Eina_List *_devices = NULL;
19static int _devices_pending_ops = 0;
20static Eina_Bool _devices_zones_update = EINA_FALSE;
26 21
27static void _e_backlight_update(void); 22static void
28static void _e_backlight_set(double val); 23_backlight_system_get_cb(void *data, const char *params)
29static Eina_Bool _bl_anim(void *data, double pos); 24{
30static Eina_Bool bl_avail = EINA_TRUE; 25 char dev[1024];
31#ifndef HAVE_WAYLAND_ONLY 26 int val = 0;
32static Eina_Bool xbl_avail = EINA_FALSE; 27 double fval;
33#endif 28 Backlight_Device *bd = data;
34#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) 29
35const char *bl_sysval = NULL; 30 if (!params) return;
31 if (sscanf(params, "%1023s %i", dev, &val) != 2) return;
32 if (!!strcmp(bd->dev, dev)) return;
33 e_system_handler_del("bklight-val", _backlight_system_get_cb, bd);
34 fval = (double)val / 1000.0;
35 if (fabs(fval - bd->val) >= DBL_EPSILON)
36 {
37 bd->val = fval;
38 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
39 }
40}
36 41
37static void _bl_sys_find(void); 42static void
38static void _bl_sys_level_get(void); 43_backlight_devices_clear(void)
39static void _bl_sys_level_set(double val); 44{
40#endif 45 Backlight_Device *bd;
41#ifdef __FreeBSD_kernel__
42static const char *bl_acpi_sysctl = "hw.acpi.video.lcd0.brightness";
43static int bl_mib[CTL_MAXNAME];
44static int bl_mib_len = -1;
45#endif
46 46
47E_API int E_EVENT_BACKLIGHT_CHANGE = -1; 47 EINA_LIST_FREE(_devices, bd)
48 {
49 eina_stringshare_del(bd->dev);
50 eina_stringshare_del(bd->output);
51 eina_stringshare_del(bd->edid);
52 if (bd->anim) ecore_animator_del(bd->anim);
53 e_system_handler_del("bklight-val", _backlight_system_get_cb, bd);
54 free(bd);
55 }
56}
48 57
49EINTERN int 58static Backlight_Device *
50e_backlight_init(void) 59_backlight_devices_zone_device_find(E_Zone *zone)
51{ 60{
52#ifdef HAVE_EEZE 61 Eina_List *l;
53 eeze_init(); 62 Backlight_Device *bd;
54#endif 63 char *tmp, *sep;
64 const char *out, *edid;
65
66 if (!zone->randr2_id) return NULL;
67 tmp = strdup(zone->randr2_id);
68 if (!tmp) return NULL;
69 sep = strchr(tmp, '/');
70 if (!sep)
71 {
72 free(tmp);
73 return NULL;
74 }
75 *sep = '\0';
76 out = tmp;
77 edid = sep + 1;
78 EINA_LIST_FOREACH(_devices, l, bd)
79 {
80 if ((bd->output) && (!strcmp(out, bd->output)))
81 {
82 if ((edid[0] && (!strcmp(edid, bd->edid))) || (!edid[0]))
83 return bd;
84 }
85 }
86 return NULL;
87}
55 88
56#ifndef HAVE_WAYLAND_ONLY 89#ifndef HAVE_WAYLAND_ONLY
57 if (e_comp->comp_type == E_PIXMAP_TYPE_X) 90static const char *
58 xbl_avail = ecore_x_randr_output_backlight_available(); 91_backlight_devices_randr_out_edid_str_get(Ecore_X_Window root, Ecore_X_Randr_Output *out)
59#endif 92{
60 e_backlight_update(); 93 const char *str = NULL;
61 if (!getenv("E_RESTART")) 94 unsigned long edid_len = 0;
62 e_backlight_level_set(NULL, e_config->backlight.normal, 0.0); 95 unsigned char *edid = ecore_x_randr_output_edid_get(root, *out, &edid_len);
96 if (edid)
97 {
98 char *edid_str = malloc((edid_len * 2) + 1);
63 99
64 E_EVENT_BACKLIGHT_CHANGE = ecore_event_type_new(); 100 if (edid_str)
101 {
102 const char *hexch = "0123456789abcdef";
103 char *dc = edid_str;
104 unsigned long i;
65 105
66 return 1; 106 for (i = 0; i < edid_len; i++)
107 {
108 dc[0] = hexch[(edid[i] >> 4) & 0xf];
109 dc[1] = hexch[(edid[i] ) & 0xf];
110 dc += 2;
111 }
112 *dc = 0;
113 str = eina_stringshare_add(edid_str);
114 free(edid_str);
115 }
116 free(edid);
117 }
118 return str;
67} 119}
68 120
69EINTERN int 121static Ecore_X_Randr_Output
70e_backlight_shutdown(void) 122_backlight_devices_randr_output_get(Ecore_X_Window root, const char *output, const char *edid)
71{ 123{
72 const char *s; 124 Ecore_X_Randr_Output *out;
73 125 int i, num = 0;
74 if (bl_anim) ecore_animator_del(bl_anim);
75 bl_anim = NULL;
76
77 if (e_config->backlight.mode != E_BACKLIGHT_MODE_NORMAL)
78 e_backlight_level_set(NULL, e_config->backlight.normal, 0.0);
79
80 EINA_LIST_FREE(bl_devs, s)
81 eina_stringshare_del(s);
82#ifdef HAVE_EEZE
83 if (bl_sysval) eina_stringshare_del(bl_sysval);
84 bl_sysval = NULL;
85 eeze_shutdown();
86#endif
87 126
88 return 1; 127 out = ecore_x_randr_window_outputs_get(root, &num);
128 if ((out) && (num > 0))
129 {
130 for (i = 0; i < num; i++)
131 {
132 char *name = ecore_x_randr_output_name_get(root, out[i], NULL);
133 if (!name) continue;
134 const char *edid_str = _backlight_devices_randr_out_edid_str_get(root, &(out[i]));
135 if (edid_str)
136 {
137 if ((!strcmp(output, name)) && (!strcmp(edid, edid_str)))
138 {
139 eina_stringshare_del(edid_str);
140 free(name);
141 return out[i];
142 }
143 eina_stringshare_del(edid_str);
144 }
145 free(name);
146 }
147 }
148 return 0;
89} 149}
150#endif
90 151
91E_API Eina_Bool 152static void
92e_backlight_exists(void) 153_backlight_devices_device_set(Backlight_Device *bd, double val)
93{ 154{
94 if (sysmode == MODE_NONE) return EINA_FALSE; 155 bd->val = val;
95 return EINA_TRUE; 156#ifndef HAVE_WAYLAND_ONLY
157 if (!strcmp(bd->dev, "randr"))
158 {
159 if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X) && (e_comp->root))
160 {
161 Ecore_X_Randr_Output o = _backlight_devices_randr_output_get(e_comp->root, bd->output, bd->edid);
162 if (o)
163 {
164 ecore_x_randr_output_backlight_level_set(e_comp->root, o, bd->val);
165 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
166 }
167 }
168 }
169 else
170#endif
171 if (!strncmp(bd->dev, "ddc:", 4))
172 {
173 // XXX: implement ddc support
174 }
175 else
176 {
177 e_system_send("bklight-set", "%s %i", bd->dev, (int)(bd->val * 1000.0));
178 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
179 }
96} 180}
97 181
98E_API void 182static E_Zone *
99e_backlight_update(void) 183_backlight_devices_device_zone_get(Backlight_Device *bd)
100{ 184{
101 if (bl_avail == EINA_FALSE) return; 185 char buf[1024];
186 Eina_List *l;
187 E_Zone *zone;
102 188
103 _e_backlight_update(); 189 snprintf(buf, sizeof(buf), "%s/%s", bd->output? bd->output: "", bd->edid ? bd->edid : "");
190 EINA_LIST_FOREACH(e_comp->zones, l, zone)
191 {
192 if (!strcmp(zone->randr2_id, buf)) return zone;
193 }
194 return NULL;
104} 195}
105 196
106E_API void 197static void
107e_backlight_level_set(E_Zone *zone, double val, double tim) 198_backlight_devices_device_update(Backlight_Device *bd)
108{ 199{
109 double bl_now; 200 if (!bd->dev) return;
110 // zone == NULL == everything 201#ifndef HAVE_WAYLAND_ONLY
111 // set backlight associated with zone to val over period of tim 202 if (!strcmp(bd->dev, "randr"))
112 // if tim == 0.0 - then do it instantnly, if time == -1 use some default
113 // transition time
114 if ((!e_comp->screen) || (!e_comp->screen->backlight_enabled)) return;
115 if (val < 0.0) val = 0.0;
116 else if (val > 1.0)
117 val = 1.0;
118 if ((fabs(val - e_bl_val) < DBL_EPSILON) && (!bl_anim)) return;
119 if (!zone) zone = e_zone_current_get();
120 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
121 bl_now = e_bl_val;
122
123 if (sysmode != MODE_RANDR)
124 e_bl_val = val;
125
126 if (fabs(tim) < DBL_EPSILON)
127 { 203 {
128 _e_backlight_set(val); 204 if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X) && (e_comp->root))
129 e_backlight_update(); 205 {
130 return; 206 Ecore_X_Randr_Output o = _backlight_devices_randr_output_get(e_comp->root, bd->output, bd->edid);
207 if (o)
208 {
209 double x_bl = ecore_x_randr_output_backlight_level_get(e_comp->root, o);
210 if ((x_bl >= 0.0) && (fabs(x_bl - bd->val) >= DBL_EPSILON))
211 {
212 bd->val = x_bl;
213 E_Zone *zone = _backlight_devices_device_zone_get(bd);
214 if (zone) zone->bl = bd->val;
215 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
216 }
217 }
218 }
131 } 219 }
132// if (e_config->backlight.mode != E_BACKLIGHT_MODE_NORMAL) return;
133 if (e_config->backlight.mode == E_BACKLIGHT_MODE_NORMAL)
134 tim = 0.5;
135 else 220 else
136 if (tim < 0.0) 221#endif
137 tim = e_config->backlight.transition; 222 if (!strncmp(bd->dev, "ddc:", 4))
223 {
224 // XXX: implement ddc support
225 }
226 else
227 {
228 e_system_handler_add("bklight-val", _backlight_system_get_cb, bd);
229 e_system_send("bklight-get", "%s", bd->dev);
230 }
231}
138 232
139 E_FREE_FUNC(bl_anim, ecore_animator_del); 233static void
140 bl_anim = ecore_animator_timeline_add(tim, _bl_anim, zone); 234_backlight_devices_update(void)
141 bl_animval = bl_now; 235{
142 bl_anim_toval = val; 236 Eina_List *l;
237 Backlight_Device *bd;
238
239 EINA_LIST_FOREACH(_devices, l, bd)
240 _backlight_devices_device_update(bd);
143} 241}
144 242
145E_API double 243static void
146e_backlight_level_get(E_Zone *zone EINA_UNUSED) 244_backlight_devices_pending_done(void)
147{ 245{
148 // zone == NULL == everything 246 _devices_pending_ops--;
149 return e_bl_val; 247 if (_devices_pending_ops > 0) return;
248 _backlight_devices_update();
150} 249}
151 250
152E_API void 251static E_Randr2_Screen *
153e_backlight_mode_set(E_Zone *zone, E_Backlight_Mode mode) 252_backlight_devices_screen_lid_get(void)
154{ 253{
155 E_Backlight_Mode pmode; 254 Eina_List *l;
156 255 E_Randr2_Screen *sc;
157 // zone == NULL == everything 256
158 if (e_config->backlight.mode == mode) return; 257 if (!e_randr2) return NULL;
159 if (eina_streq(ecore_evas_engine_name_get(e_comp->ee), "buffer") || 258 EINA_LIST_FOREACH(e_randr2->screens, l, sc)
160 strstr(ecore_evas_engine_name_get(e_comp->ee), "wayland"))
161 return;
162 pmode = e_config->backlight.mode;
163 e_config->backlight.mode = mode;
164 if (e_config->backlight.mode == E_BACKLIGHT_MODE_NORMAL)
165 {
166 e_backlight_level_set(zone, e_config->backlight.normal, -1.0);
167 }
168 else if (e_config->backlight.mode == E_BACKLIGHT_MODE_OFF)
169 { 259 {
170 e_backlight_level_set(zone, 0.0, -1.0); 260 if (sc->info.is_lid) return sc;
171 } 261 }
172 else if (e_config->backlight.mode == E_BACKLIGHT_MODE_DIM) 262 return NULL;
173 {
174 if ((pmode != E_BACKLIGHT_MODE_NORMAL) ||
175 ((pmode == E_BACKLIGHT_MODE_NORMAL) &&
176 (e_config->backlight.normal > e_config->backlight.dim)))
177 e_backlight_level_set(zone, e_config->backlight.dim, -1.0);
178 }
179 else if (e_config->backlight.mode == E_BACKLIGHT_MODE_MAX)
180 e_backlight_level_set(zone, 1.0, -1.0);
181} 263}
182 264
183E_API E_Backlight_Mode 265static Backlight_Device *
184e_backlight_mode_get(E_Zone *zone EINA_UNUSED) 266_backlight_devices_edid_find(const char *edid)
185{ 267{
186 // zone == NULL == everything 268 Eina_List *l;
187 return e_config->backlight.mode; 269 Backlight_Device *bd;
270
271 EINA_LIST_FOREACH(_devices, l, bd)
272 {
273 if ((bd->edid) && (edid) && (!strcmp(edid, bd->edid)))
274 return bd;
275 }
276 return NULL;
188} 277}
189 278
190E_API const Eina_List * 279static void
191e_backlight_devices_get(void) 280_backlight_devices_lid_register(const char *dev, Eina_Bool force)
192{ 281{
193 return bl_devs; 282 E_Randr2_Screen *sc = _backlight_devices_screen_lid_get();
283 Backlight_Device *bd;
284 if (!sc) return;
285 bd = _backlight_devices_edid_find(sc->info.edid);
286 if (!bd)
287 {
288 bd = calloc(1, sizeof(Backlight_Device));
289 if (!bd) return;
290 bd->edid = eina_stringshare_add(sc->info.edid);
291 bd->output = eina_stringshare_add(sc->info.name);
292 _devices = eina_list_append(_devices, bd);
293 }
294 if (bd->dev)
295 {
296 if (!strcmp(bd->dev, "randr")) return; // randr devices win
297 if (!strncmp(bd->dev, "ddc:", 4)) return; // ddc devices also beat these "sys" devices
298 }
299 // if bl device has a device assigned and we're not forcing a change
300 // then skip assigning this device to the backlight device
301 if ((bd->dev) && (!force)) return;
302 eina_stringshare_replace(&(bd->dev), dev);
194} 303}
195 304
196/* local subsystem functions */
197
198static void 305static void
199_e_backlight_update(void) 306_backlight_system_list_cb(void *data EINA_UNUSED, const char *params)
200{ 307{
201#ifndef HAVE_WAYLAND_ONLY 308 // params "dev flag dev flag ..."
202 double x_bl = -1.0; 309 const char *p = params, *s;
203 Ecore_X_Window root; 310 char dev[1024], flag, devnum = 0;
204 Ecore_X_Randr_Output *out;
205 int i, num = 0;
206 311
207 if (!e_comp) return; 312 e_system_handler_del("bklight-list", _backlight_system_list_cb, NULL);
208 root = e_comp->root; 313 EINA_LIST_FREE(bl_devs, s)
209 // try randr 314 eina_stringshare_del(s);
210 if (root && xbl_avail) 315#ifndef HAVE_WAYLAND_ONLY
316 if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X))
211 { 317 {
212 out = ecore_x_randr_window_outputs_get(root, &num); 318 if (ecore_x_randr_output_backlight_available())
213 if ((out) && (num > 0)) 319 bl_devs = eina_list_append(bl_devs, eina_stringshare_add("randr"));
320 }
321#endif
322 while ((p) && (*p))
323 {
324 if (sscanf(p, "%1023s", dev) == 1)
214 { 325 {
215 char *name; 326 p += strlen(dev);
216 Eina_Bool gotten = EINA_FALSE; 327 if (*p == ' ')
217
218 E_FREE_LIST(bl_devs, eina_stringshare_del);
219 for (i = 0; i < num; i++)
220 { 328 {
221 Eina_Stringshare *n; 329 p++;
222 330 flag = *p;
223 name = ecore_x_randr_output_name_get(root, out[i], NULL); 331 if (flag)
224 if (!name) continue;
225 n = eina_stringshare_add(name);
226 free(name);
227 bl_devs = eina_list_append(bl_devs, n);
228 if (!e_util_strcmp(n, e_config->backlight.sysdev))
229 { 332 {
230 x_bl = ecore_x_randr_output_backlight_level_get(root, out[i]); 333 bl_devs = eina_list_append
231 gotten = EINA_TRUE; 334 (bl_devs, eina_stringshare_add(dev));
335 if ((devnum == 0) || (flag == 'p') ||
336 (strstr(dev, "/drm/")) ||
337 (strstr(dev, ".video.")))
338 {
339 _backlight_devices_lid_register(dev, EINA_TRUE);
340 }
341 else
342 {
343 // XXX: what to do with other bl devices?
344 // for now just assign spare bl devices to screens that do not have one already
345 _backlight_devices_lid_register(dev, EINA_FALSE);
346 }
347 devnum++;
348 // XXX: find bed bl dev for screens not supporting randr
349 // note that this is a vallback and ddc should take precedence
350 // it matched up to a screen over this, but randr shoule be
351 // the top priority if found
232 } 352 }
353 else break;
354 p++;
355 if (*p != ' ') break;
356 p++;
357 if (*p == '\0') break;
233 } 358 }
234 if (!gotten) 359 else break;
235 x_bl = ecore_x_randr_output_backlight_level_get(root, out[0]);
236 } 360 }
237 free(out); 361 else break;
238 }
239 if (x_bl >= 0.0)
240 {
241 e_bl_val = x_bl;
242 sysmode = MODE_RANDR;
243 return;
244 }
245#endif
246#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__)
247 _bl_sys_find();
248 if (bl_sysval)
249 {
250 sysmode = MODE_SYS;
251#ifndef HAVE_WAYLAND_ONLY
252 xbl_avail = EINA_FALSE;
253#endif
254 _bl_sys_level_get();
255 return;
256 } 362 }
257#endif 363 _backlight_devices_pending_done();
258} 364}
259 365
260static void 366static void
261_e_backlight_set(double val) 367_backlight_devices_probe(void)
262{ 368{
263#ifdef HAVE_WAYLAND_ONLY 369 _backlight_devices_clear();
264 if (0) 370#ifndef HAVE_WAYLAND_ONLY
265 { 371 // pass 1: if in x look at all the randr outputs to see if they have some backlight
266 (void)val; 372 // property to swizzle then make the randr device the kind of device to use -
267 return; 373 // record this in our devices list
268 } 374 if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X))
269#else
270 if (val < 0.05) val = 0.05;
271 if (sysmode == MODE_RANDR)
272 { 375 {
273 Ecore_X_Window root; 376 Eina_Bool avail = ecore_x_randr_output_backlight_available();
274 Ecore_X_Randr_Output *out; 377 if ((avail) && (e_comp->root))
275 int num = 0, i;
276 char *name;
277
278 if (!e_comp) return;
279 root = e_comp->root;
280 out = ecore_x_randr_window_outputs_get(root, &num);
281 if ((out) && (num > 0))
282 { 378 {
283 Eina_Bool gotten = EINA_FALSE; 379 double x_bl;
284 if (e_config->backlight.sysdev) 380 Ecore_X_Window root = e_comp->root;
381 Ecore_X_Randr_Output *out;
382 int i, num = 0;
383
384 out = ecore_x_randr_window_outputs_get(root, &num);
385 if ((out) && (num > 0))
285 { 386 {
286 for (i = 0; i < num; i++) 387 for (i = 0; i < num; i++)
287 { 388 {
288 name = ecore_x_randr_output_name_get(root, out[i], NULL); 389 char *name = ecore_x_randr_output_name_get(root, out[i], NULL);
289 if (name) 390 if (!name) continue;
391 x_bl = ecore_x_randr_output_backlight_level_get(root, out[0]);
392 if (x_bl >= 0.0)
290 { 393 {
291 if (!strcmp(name, e_config->backlight.sysdev)) 394 Backlight_Device *bd = calloc(1, sizeof(Backlight_Device));
395 if (bd)
292 { 396 {
293 ecore_x_randr_output_backlight_level_set(root, out[i], val); 397 const char *edid_str = _backlight_devices_randr_out_edid_str_get(root, &(out[i]));
294 gotten = EINA_TRUE; 398
399 if (edid_str)
400 {
401 bd->dev = eina_stringshare_add("randr");
402 bd->output = eina_stringshare_add(name);
403 bd->edid = edid_str;
404 _devices = eina_list_append(_devices, bd);
405 }
406 else free(bd);
295 } 407 }
296 free(name);
297 } 408 }
409 free(name);
298 } 410 }
299 } 411 }
300 if (!gotten) 412 free(out);
301 {
302 for (i = 0; i < num; i++)
303 ecore_x_randr_output_backlight_level_set(root, out[i], val);
304 }
305 }
306 free(out);
307 }
308#endif
309#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__)
310 else if (sysmode == MODE_SYS)
311 {
312 if (bl_sysval)
313 {
314 _bl_sys_level_set(val);
315 } 413 }
316 } 414 }
317#endif 415#endif
416 // ask enlightenment_system to list backlight devices. this is async so we have
417 // to respond to the device listing later
418 _devices_pending_ops++;
419 e_system_handler_add("bklight-list", _backlight_system_list_cb, NULL);
420 e_system_send("bklight-refresh", NULL);
421 e_system_send("bklight-list", NULL);
422 // XXXX: add ddc to e_syystem and query that too
318} 423}
319 424
320static Eina_Bool 425static Eina_Bool
321_bl_anim(void *data EINA_UNUSED, double pos) 426_bl_anim(void *data, double pos)
322{ 427{
323 double v; 428 Backlight_Device *bd = data;
324 429
325 // FIXME: if zone is deleted while anim going... bad things. 430 // FIXME: if zone is deleted while anim going... bad things.
326 pos = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0); 431 pos = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
327 v = (bl_animval * (1.0 - pos)) + (bl_anim_toval * pos); 432 bd->val = (bd->from_val * (1.0 - pos)) + (bd->to_val * pos);
328 _e_backlight_set(v); 433 _backlight_devices_device_set(bd, bd->val);
329 if (pos >= 1.0) 434 if (pos >= 1.0)
330 { 435 {
331 bl_anim = NULL; 436 bd->anim = NULL;
332 e_backlight_update(); 437 _backlight_devices_device_update(bd);
333 return EINA_FALSE; 438 return EINA_FALSE;
334 } 439 }
335 return EINA_TRUE; 440 return EINA_TRUE;
336} 441}
337 442
338#ifdef HAVE_EEZE
339static void 443static void
340_bl_sys_change(const char *device, Eeze_Udev_Event event EINA_UNUSED, void *data EINA_UNUSED, Eeze_Udev_Watch *watch EINA_UNUSED) 444_cb_job_zone_change(void *data EINA_UNUSED)
341{ 445{
342 if (device == bl_sysval) 446 zone_change_job = NULL;
343 { 447 _backlight_devices_probe();
344 _bl_sys_level_get(); 448 e_backlight_update();
345 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
346 }
347 eina_stringshare_del(device);
348} 449}
349 450
350static void 451static Eina_Bool
351_bl_sys_find(void) 452_cb_handler_zone_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *info EINA_UNUSED)
352{ 453{
353 Eina_List *l, *devs, *pdevs = NULL; 454 if (zone_change_job) ecore_job_del(zone_change_job);
354 Eina_Bool use; 455 zone_change_job = ecore_job_add(_cb_job_zone_change, NULL);
355 const char *f, *s; 456 return EINA_TRUE;
356 int v;
357
358 devs = eeze_udev_find_by_filter("backlight", NULL, NULL);
359 if (!devs)
360 {
361 /* FIXME: need to make this more precise so we don't set keyboard LEDs or something */
362 devs = eeze_udev_find_by_filter("leds", NULL, NULL);
363 if (!devs) return;
364 }
365 if (eina_list_count(devs) > 1)
366 {
367 /* prefer backlights of type "firmware" where available */
368 EINA_LIST_FOREACH(devs, l, f)
369 {
370 use = eeze_udev_syspath_check_sysattr(f, "type", "firmware");
371 if (!use) continue;
372 s = eeze_udev_syspath_get_sysattr(f, "brightness");
373 if (!s) continue;
374 v = atoi(s);
375 eina_stringshare_del(s);
376 if (v < 0) continue;
377 pdevs = eina_list_append(pdevs, eina_stringshare_ref(f));
378 eina_stringshare_del(f);
379 l->data = NULL;
380 }
381 EINA_LIST_FOREACH(devs, l, f)
382 {
383 if (!l->data) continue;
384 s = eeze_udev_syspath_get_sysattr(f, "brightness");
385 if (!s) continue;
386 v = atoi(s);
387 eina_stringshare_del(s);
388 if (v < 0) continue;
389 pdevs = eina_list_append(pdevs, eina_stringshare_ref(f));
390 }
391 }
392 if (!pdevs)
393 {
394 /* add the other backlight or led's if none found */
395 EINA_LIST_FOREACH(devs, l, f)
396 {
397 use = EINA_FALSE;
398 s = eeze_udev_syspath_get_sysattr(f, "brightness");
399 if (!s) continue;
400 v = atoi(s);
401 eina_stringshare_del(s);
402 if (v < 0) continue;
403 pdevs = eina_list_append(pdevs, eina_stringshare_ref(f));
404 }
405 }
406 /* clear out original devs list now we've filtered */
407 E_FREE_LIST(devs, eina_stringshare_del);
408 /* clear out old configured bl sysval */
409 eina_stringshare_replace(&bl_sysval, NULL);
410 E_FREE_LIST(bl_devs, eina_stringshare_del);
411 /* if configured backlight is there - use it, or if not use first */
412 EINA_LIST_FOREACH(pdevs, l, f)
413 {
414 bl_devs = eina_list_append(bl_devs, eina_stringshare_add(f));
415 if (!bl_sysval)
416 {
417 if (!e_util_strcmp(e_config->backlight.sysdev, f))
418 bl_sysval = eina_stringshare_ref(f);
419 }
420 }
421 if (!bl_sysval)
422 {
423 EINA_LIST_FOREACH(pdevs, l, f)
424 {
425 if ((!strstr(f, "kbd")) && (!strstr(f, "mail")) && (!strstr(f, "input")))
426 {
427 bl_sysval = eina_stringshare_add(f);
428 break;
429 }
430 }
431 }
432 /* clear out preferred devs list */
433 E_FREE_LIST(pdevs, eina_stringshare_del);
434 eeze_udev_watch_add(EEZE_UDEV_TYPE_BACKLIGHT, EEZE_UDEV_EVENT_CHANGE, _bl_sys_change, NULL);
435} 457}
436 458
437static void 459EINTERN int
438_bl_sys_level_get(void) 460e_backlight_init(void)
439{ 461{
440 int maxval, val; 462 E_EVENT_BACKLIGHT_CHANGE = ecore_event_type_new();
441 const char *str; 463 _backlight_devices_probe();
442 464#define H(ev, cb) \
443 if (bl_anim) return; 465 handlers = eina_list_append(handlers, \
444 466 ecore_event_handler_add(ev, cb, NULL));
445 str = eeze_udev_syspath_get_sysattr(bl_sysval, "max_brightness"); 467 H(E_EVENT_ZONE_ADD, _cb_handler_zone_change);
446 if (!str) return; 468 H(E_EVENT_ZONE_DEL, _cb_handler_zone_change);
469 H(E_EVENT_ZONE_MOVE_RESIZE, _cb_handler_zone_change);
470 H(E_EVENT_ZONE_STOW, _cb_handler_zone_change);
471 H(E_EVENT_ZONE_UNSTOW, _cb_handler_zone_change);
472 e_backlight_update();
473 if (!getenv("E_RESTART"))
474 e_backlight_level_set(NULL, e_config->backlight.normal, 0.0);
475 return 1;
476}
447 477
448 maxval = atoi(str); 478EINTERN int
449 eina_stringshare_del(str); 479e_backlight_shutdown(void)
450 if (maxval < 0) maxval = 255; 480{
451 str = eeze_udev_syspath_get_sysattr(bl_sysval, "brightness"); 481 Ecore_Event_Handler *h;
452 if (!str) return; 482 const char *s;
453 483
454 val = atoi(str); 484 if (zone_change_job)
455 eina_stringshare_del(str);
456 if ((!maxval) && (!val))
457 { 485 {
458 e_bl_val = 0; 486 ecore_job_del(zone_change_job);
459 sysmode = MODE_NONE; 487 zone_change_job = NULL;
460 return;
461 } 488 }
462 if (!maxval) maxval = 255; 489 EINA_LIST_FREE(handlers, h)
463 if ((val >= 0) && (val <= maxval)) 490 ecore_event_handler_del(h);
464 e_bl_val = (double)val / (double)maxval; 491 EINA_LIST_FREE(bl_devs, s)
465// fprintf(stderr, "GET: %i/%i (%1.3f)\n", val, maxval, e_bl_val); 492 eina_stringshare_del(s);
493 _backlight_devices_clear();
494 return 1;
466} 495}
467#endif // HAVE_EEZE
468 496
469#if defined(HAVE_EEZE) || defined(__FreeBSD_kernel__) 497E_API Eina_Bool
470static void 498e_backlight_exists(void)
471_bl_sys_level_set(double val)
472{ 499{
473 e_system_send("bklight-set", "%s %i", bl_sysval, (int)(val * 1000.0)); 500 // XXX: properly check backlight devices
501 return EINA_TRUE;
474} 502}
475#endif // HAVE_EEZE || __FreeBSD_kernel__
476 503
477#ifdef __FreeBSD_kernel__ 504E_API void
478static void 505e_backlight_update(void)
479_bl_sys_find(void)
480{ 506{
481 int rc; 507 if (_devices_pending_ops > 0) _devices_zones_update = EINA_TRUE;
482 size_t mlen; 508 else _backlight_devices_update();
509}
483 510
484 if (!bl_avail) return; 511E_API void
485 if (bl_mib_len >= 0) return; 512e_backlight_level_set(E_Zone *zone, double val, double tim)
513{
514 Backlight_Device *bd;
515 double bl_now;
486 516
487 mlen = sizeof(bl_mib) / sizeof(bl_mib[0]); 517 if (!zone) // zone == NULL == everything
488 rc = sysctlnametomib(bl_acpi_sysctl, bl_mib, &mlen);
489 if (rc < 0)
490 { 518 {
491 if (errno == ENOENT) ERR("ACPI brightness sysctl '%s' not found, consider 'kldload acpi_video'", bl_acpi_sysctl); 519 Eina_List *l;
492 else ERR("sysctlnametomib(%s): %s(%d)", bl_acpi_sysctl, strerror(errno), errno);
493 520
494 bl_avail = EINA_FALSE; 521 if (!e_comp) return;
522 EINA_LIST_FOREACH(e_comp->zones, l, zone)
523 e_backlight_level_set(zone, val, tim);
495 return; 524 return;
496 } 525 }
497 bl_mib_len = (int)mlen; 526 bd = _backlight_devices_zone_device_find(zone);
498 sysmode = MODE_SYS; 527 if (!bd) return;
499 eina_stringshare_replace(&bl_sysval, bl_acpi_sysctl); 528 // set backlight associated with zone to val over period of tim
529 // if tim == 0.0 - then do it instantnly, if time == -1 use some default
530 // transition time
531 if ((!e_comp->screen) || (!e_comp->screen->backlight_enabled)) return;
532 if (val < 0.0) val = 0.0;
533 else if (val > 1.0) val = 1.0;
534 if ((fabs(val - zone->bl) < DBL_EPSILON) && (!bd->anim)) return;
535 bl_now = zone->bl;
536
537 zone->bl = val;
538
539 if (fabs(tim) < DBL_EPSILON)
540 {
541 _backlight_devices_device_set(bd, val);
542 _backlight_devices_device_update(bd);
543 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);
544 return;
545 }
546 if (zone->bl_mode == E_BACKLIGHT_MODE_NORMAL) tim = 0.5;
547 else if (tim < 0.0) tim = e_config->backlight.transition;
548
549 // XXX: store in bl device
550 E_FREE_FUNC(bd->anim, ecore_animator_del);
551 bd->anim = ecore_animator_timeline_add(tim, _bl_anim, bd);
552 bd->from_val = bl_now;
553 bd->to_val = val;
500} 554}
501 555
502static void 556E_API double
503_bl_sys_level_get(void) 557e_backlight_level_get(E_Zone *zone)
504{ 558{
505 int rc, brightness; 559 Backlight_Device *bd;
506 size_t oldlen; 560
561 if (!zone)
562 {
563 zone = e_zone_current_get();
564 if (!zone) return -1.0;
565 }
566 bd = _backlight_devices_zone_device_find(zone);
567 if (!bd) return -1.0;
568 zone->bl = bd->val;
569 return bd->val;
570}
507 571
508 if (!bl_avail) return; 572E_API void
509 if (bl_mib_len < 0) return; 573e_backlight_mode_set(E_Zone *zone, E_Backlight_Mode mode)
574{
575 E_Backlight_Mode pmode;
510 576
511 oldlen = sizeof(brightness); 577 if (!zone) // zone == NULL == everything
512 rc = sysctl(bl_mib, bl_mib_len, &brightness, &oldlen, NULL, 0);
513 if (rc < 0)
514 { 578 {
515 ERR("Could not retrieve ACPI brightness: %s(%d)", strerror(errno), errno); 579 Eina_List *l;
516 bl_avail = EINA_FALSE; 580
581 if (!e_comp) return;
582 EINA_LIST_FOREACH(e_comp->zones, l, zone)
583 e_backlight_mode_set(zone, mode);
517 return; 584 return;
518 } 585 }
519 if (oldlen != sizeof(brightness)) 586 if (zone->bl_mode == mode) return;
587 if (eina_streq(ecore_evas_engine_name_get(e_comp->ee), "buffer") ||
588 strstr(ecore_evas_engine_name_get(e_comp->ee), "wayland"))
589 return;
590 pmode = zone->bl_mode;
591 zone->bl_mode = mode;
592 if (zone->bl_mode == E_BACKLIGHT_MODE_NORMAL)
520 { 593 {
521 // This really should not happen. 594 e_backlight_level_set(zone, e_config->backlight.normal, -1.0);
522 ERR("!!! Brightness sysctl changed size !!!");
523 bl_avail = EINA_FALSE;
524 return;
525 } 595 }
526 if (brightness < 0 || brightness > 100) 596 else if (zone->bl_mode == E_BACKLIGHT_MODE_OFF)
527 { 597 {
528 // This really should not happen either. 598 e_backlight_level_set(zone, 0.0, -1.0);
529 ERR("!!! Brightness sysctl out of range !!!");
530 bl_avail = EINA_FALSE;
531 return;
532 } 599 }
533 e_bl_val = (double)brightness / 100.; 600 else if (zone->bl_mode == E_BACKLIGHT_MODE_DIM)
601 {
602 if ((pmode != E_BACKLIGHT_MODE_NORMAL) ||
603 ((pmode == E_BACKLIGHT_MODE_NORMAL) &&
604 (e_config->backlight.normal > e_config->backlight.dim)))
605 e_backlight_level_set(zone, e_config->backlight.dim, -1.0);
606 }
607 else if (zone->bl_mode == E_BACKLIGHT_MODE_MAX)
608 e_backlight_level_set(zone, 1.0, -1.0);
609}
610
611E_API E_Backlight_Mode
612e_backlight_mode_get(E_Zone *zone)
613{
614 if (!zone)
615 {
616 zone = e_zone_current_get();
617 if (!zone) return E_BACKLIGHT_MODE_NORMAL;
618 }
619 return zone->bl_mode;
620}
621
622E_API const Eina_List *
623e_backlight_devices_get(void)
624{
625 return bl_devs;
534} 626}
535#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 };
75static int screen_size_index = -1; 75static int screen_size_index = -1;
76 76
77static Ecore_X_Atom backlight_atom = 0; 77static Ecore_X_Atom backlight_atom = 0;
78extern double e_bl_val;
79 78
80static Ecore_Timer *mouse_in_fix_check_timer = NULL; 79static Ecore_Timer *mouse_in_fix_check_timer = NULL;
81 80
@@ -5293,17 +5292,8 @@ _e_comp_x_screensaver_notify_cb(void *data EINA_UNUSED, int type EINA_UNUSED, Ec
5293static Eina_Bool 5292static Eina_Bool
5294_e_comp_x_backlight_notify_cb(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Randr_Output_Property_Notify *ev) 5293_e_comp_x_backlight_notify_cb(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Randr_Output_Property_Notify *ev)
5295{ 5294{
5296 double x_bl;
5297
5298 if (ev->property != backlight_atom) return ECORE_CALLBACK_RENEW; 5295 if (ev->property != backlight_atom) return ECORE_CALLBACK_RENEW;
5299 x_bl = ecore_x_randr_output_backlight_level_get(0, ev->output); 5296 e_backlight_update();
5300
5301 if (x_bl >= 0.0)
5302 {
5303 if (fabs(e_bl_val - x_bl) < DBL_EPSILON)
5304 ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL);;
5305 e_bl_val = x_bl;
5306 }
5307 return ECORE_CALLBACK_RENEW; 5297 return ECORE_CALLBACK_RENEW;
5308} 5298}
5309 5299
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
372 double battery_timer; // GUI 372 double battery_timer; // GUI
373 const char *sysdev; // GUI 373 const char *sysdev; // GUI
374 unsigned char idle_dim; // GUI 374 unsigned char idle_dim; // GUI
375 E_Backlight_Mode mode; /* not saved, display-only */
376 } backlight; 375 } backlight;
377 376
378 struct 377 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
62 /* formerly E_Comp_Zone */ 62 /* formerly E_Comp_Zone */
63 Evas_Object *base; 63 Evas_Object *base;
64 Evas_Object *over; 64 Evas_Object *over;
65
66 E_Backlight_Mode bl_mode;
65 double bl; 67 double bl;
66 Eina_Bool bloff; 68 Eina_Bool bloff;
67 69