1 #include "e.h"
2 
3 #define ACTION_TIMEOUT 30.0
4 
5 /* local subsystem functions */
6 static void      _e_sys_cb_logout_logout(void *data, E_Dialog *dia);
7 static void      _e_sys_cb_logout_wait(void *data, E_Dialog *dia);
8 static void      _e_sys_cb_logout_abort(void *data, E_Dialog *dia);
9 static Eina_Bool _e_sys_cb_logout_timer(void *data);
10 static void      _e_sys_logout_after(void);
11 static void      _e_sys_logout_begin(E_Sys_Action a_after, Eina_Bool raw);
12 static void      _e_sys_current_action(void);
13 static int       _e_sys_action_do(E_Sys_Action a, char *param, Eina_Bool raw);
14 
15 static int _e_sys_can_halt = 0;
16 static int _e_sys_can_reboot = 0;
17 static int _e_sys_can_suspend = 0;
18 static int _e_sys_can_hibernate = 0;
19 
20 static E_Sys_Action _e_sys_action_current = E_SYS_NONE;
21 static E_Sys_Action _e_sys_action_after = E_SYS_NONE;
22 static Eina_Bool _e_sys_action_after_raw = EINA_FALSE;
23 static double _e_sys_begin_time = 0.0;
24 static double _e_sys_logout_begin_time = 0.0;
25 static Ecore_Timer *_e_sys_logout_timer = NULL;
26 static E_Dialog *_e_sys_logout_confirm_dialog = NULL;
27 static Ecore_Timer *_e_sys_susp_hib_check_timer = NULL;
28 static double _e_sys_susp_hib_check_last_tick = 0.0;
29 static Ecore_Timer *_e_sys_phantom_wake_check_timer = NULL;
30 static Ecore_Timer *_e_sys_resume_delay_timer = NULL;
31 static Eina_Bool _e_sys_suspended = EINA_FALSE;
32 
33 static Ecore_Event_Handler *_e_sys_acpi_handler = NULL;
34 
35 static void _e_sys_systemd_handle_inhibit(void);
36 static void _e_sys_systemd_poweroff(void);
37 static void _e_sys_systemd_reboot(void);
38 static void _e_sys_systemd_suspend(void);
39 static void _e_sys_systemd_hibernate(void);
40 static void _e_sys_systemd_exists_cb(void *data, const Eldbus_Message *m, Eldbus_Pending *p);
41 
42 static Eina_Bool systemd_works = EINA_FALSE;
43 static int _e_sys_systemd_inhibit_fd = -1;
44 
45 static const int E_LOGOUT_AUTO_TIME = 60.0;
46 static const int E_LOGOUT_WAIT_TIME = 3.0;
47 
48 static Ecore_Timer *action_timeout = NULL;
49 
50 static Eldbus_Proxy *login1_manger_proxy = NULL;
51 
52 static int _e_sys_comp_waiting = 0;
53 
54 static Ecore_Timer *_e_sys_screensaver_unignore_timer = NULL;
55 
56 static double resume_backlight;
57 
58 static Ecore_Timer *_e_sys_suspend_delay_timer = NULL;
59 static Ecore_Timer *_e_sys_hibernate_delay_timer = NULL;
60 static Ecore_Timer *_e_sys_halt_reboot_timer = NULL;
61 
62 static Eina_Bool on_the_way_out = EINA_FALSE;
63 
64 E_API int E_EVENT_SYS_SUSPEND = -1;
65 E_API int E_EVENT_SYS_HIBERNATE = -1;
66 E_API int E_EVENT_SYS_RESUME = -1;
67 
68 static Eina_Bool
_e_sys_comp_done2_cb(void * data)69 _e_sys_comp_done2_cb(void *data)
70 {
71    printf("SSS: _e_sys_comp_done2_cb %p\n", data);
72    e_sys_action_raw_do((E_Sys_Action)(long)data, NULL);
73    return EINA_FALSE;
74 }
75 
76 static void
_e_sys_comp_done_cb(void * data,Evas_Object * obj,const char * sig,const char * src)77 _e_sys_comp_done_cb(void *data, Evas_Object *obj, const char *sig, const char *src)
78 {
79    if (_e_sys_comp_waiting == 1) _e_sys_comp_waiting--;
80    edje_object_signal_callback_del(obj, sig, src, _e_sys_comp_done_cb);
81    if (_e_sys_screensaver_unignore_timer)
82      {
83         ecore_timer_del(_e_sys_screensaver_unignore_timer);
84         _e_sys_screensaver_unignore_timer = NULL;
85      }
86    e_screensaver_ignore();
87    ecore_evas_manual_render_set(e_comp->ee, EINA_TRUE);
88 #ifndef HAVE_WAYLAND_ONLY
89    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
90      {
91         if (_e_sys_action_after != E_SYS_RESTART)
92           {
93              ecore_x_screensaver_suspend();
94              ecore_x_dpms_force(EINA_TRUE);
95           }
96      }
97 #endif
98 #ifdef HAVE_WAYLAND
99    if (e_comp->comp_type != E_PIXMAP_TYPE_X)
100      {
101         if (e_comp->screen && e_comp->screen->dpms)
102           e_comp->screen->dpms(3);
103      }
104 #endif
105    if (_e_sys_action_after != E_SYS_RESTART)
106      {
107         edje_freeze();
108         ecore_timer_add(0.5, _e_sys_comp_done2_cb, data);
109      }
110    else
111      {
112         ecore_timer_add(0.3, _e_sys_comp_done2_cb, data);
113      }
114    E_FREE_FUNC(action_timeout, ecore_timer_del);
115 }
116 
117 static Eina_Bool
_e_sys_comp_action_timeout(void * data)118 _e_sys_comp_action_timeout(void *data)
119 {
120    const Eina_List *l;
121    E_Zone *zone;
122    E_Sys_Action a = (long)(intptr_t)data;
123    const char *sig = NULL;
124 
125    if (_e_sys_comp_waiting == 1) _e_sys_comp_waiting--;
126    switch (a)
127      {
128       case E_SYS_RESTART:
129         sig = "e,state,sys,logout,done";
130         break;
131       case E_SYS_LOGOUT:
132         sig = "e,state,sys,logout,done";
133         break;
134       case E_SYS_HALT:
135         sig = "e,state,sys,halt,done";
136         break;
137       case E_SYS_REBOOT:
138         sig = "e,state,sys,reboot,done";
139         break;
140       case E_SYS_SUSPEND:
141         sig = "e,state,sys,suspend,done";
142         break;
143       case E_SYS_HIBERNATE:
144         sig = "e,state,sys,hibernate,done";
145         break;
146       default:
147         break;
148      }
149    E_FREE_FUNC(action_timeout, ecore_timer_del);
150    if (sig)
151      {
152         EINA_LIST_FOREACH(e_comp->zones, l, zone)
153           edje_object_signal_callback_del(zone->over, sig, "e", _e_sys_comp_done_cb);
154      }
155    e_sys_action_raw_do(a, NULL);
156    return EINA_FALSE;
157 }
158 
159 static void
_e_sys_comp_zones_fade(E_Sys_Action a,const char * sig,Eina_Bool out)160 _e_sys_comp_zones_fade(E_Sys_Action a, const char *sig, Eina_Bool out)
161 {
162    const Eina_List *l;
163    E_Zone *zone;
164    EINA_LIST_FOREACH(e_comp->zones, l, zone)
165      {
166         // XXX:
167         // don't fade backlight if we are exiting or logging out
168         // in future detect if e is the login manager and then
169         // we can assume it can manage backlight right anyway... then disable
170         // this if below when that happens
171         if ((a != E_SYS_EXIT) &&  (a != E_SYS_EXIT_NOW) && (a != E_SYS_LOGOUT))
172           e_zone_fade_handle(zone, out, 0.5);
173         edje_object_signal_emit(zone->base, sig, "e");
174         edje_object_signal_emit(zone->over, sig, "e");
175      }
176 }
177 
178 static void
_e_sys_comp_emit_cb_wait(E_Sys_Action a,const char * sig,const char * rep,Eina_Bool nocomp_push)179 _e_sys_comp_emit_cb_wait(E_Sys_Action a, const char *sig, const char *rep, Eina_Bool nocomp_push)
180 {
181    E_Zone *zone;
182 
183    if (_e_sys_comp_waiting == 0) _e_sys_comp_waiting++;
184    if (nocomp_push) e_comp_override_add();
185    else e_comp_override_timed_pop();
186 
187    _e_sys_comp_zones_fade(a, sig, nocomp_push);
188 #ifndef HAVE_WAYLAND_ONLY
189    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
190      _e_comp_x_screensaver_on();
191 #endif
192 #ifdef HAVE_WAYLAND
193    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
194      _e_comp_wl_screensaver_on();
195 #endif
196 
197    if (rep)
198      {
199         zone = eina_list_data_get(e_comp->zones);
200         if (zone) edje_object_signal_callback_add(zone->over, rep, "e", _e_sys_comp_done_cb, (void *)(long)a);
201         if (action_timeout) ecore_timer_del(action_timeout);
202         action_timeout = ecore_timer_loop_add(ACTION_TIMEOUT, (Ecore_Task_Cb)_e_sys_comp_action_timeout, (intptr_t*)(long)a);
203      }
204 }
205 
206 static void
_e_sys_comp_suspend(void)207 _e_sys_comp_suspend(void)
208 {
209    resume_backlight = e_config->backlight.normal;
210    _e_sys_comp_emit_cb_wait(E_SYS_SUSPEND, "e,state,sys,suspend", "e,state,sys,suspend,done", EINA_TRUE);
211 }
212 
213 static void
_e_sys_comp_hibernate(void)214 _e_sys_comp_hibernate(void)
215 {
216    resume_backlight = e_config->backlight.normal;
217    _e_sys_comp_emit_cb_wait(E_SYS_HIBERNATE, "e,state,sys,hibernate", "e,state,sys,hibernate,done", EINA_TRUE);
218 }
219 
220 static void
_e_sys_comp_reboot(void)221 _e_sys_comp_reboot(void)
222 {
223    _e_sys_comp_emit_cb_wait(E_SYS_REBOOT, "e,state,sys,reboot", "e,state,sys,reboot,done", EINA_TRUE);
224 }
225 
226 static void
_e_sys_comp_shutdown(void)227 _e_sys_comp_shutdown(void)
228 {
229    _e_sys_comp_emit_cb_wait(E_SYS_HALT, "e,state,sys,halt", "e,state,sys,halt,done", EINA_TRUE);
230 }
231 
232 static void
_e_sys_comp_logout(void)233 _e_sys_comp_logout(void)
234 {
235    _e_sys_comp_emit_cb_wait(E_SYS_LOGOUT, "e,state,sys,logout", "e,state,sys,logout,done", EINA_TRUE);
236 }
237 
238 static void
_e_sys_comp_restart(void)239 _e_sys_comp_restart(void)
240 {
241    E_Zone *zone;
242 
243    resume_backlight = e_config->backlight.normal;
244    zone = eina_list_data_get(e_comp->zones);
245    if ((zone) && (edje_object_data_get(zone->over, "restarted")))
246      _e_sys_comp_emit_cb_wait(E_SYS_RESTART, "e,state,sys,restart", "e,state,sys,restart,done", EINA_TRUE);
247    else
248      _e_sys_comp_emit_cb_wait(E_SYS_RESTART, "e,state,sys,logout", "e,state,sys,logout,done", EINA_TRUE);
249 }
250 
251 static Eina_Bool
_e_sys_screensaver_unignore_delay(void * data EINA_UNUSED)252 _e_sys_screensaver_unignore_delay(void *data EINA_UNUSED)
253 {
254    _e_sys_screensaver_unignore_timer = NULL;
255    e_screensaver_unignore();
256    return EINA_FALSE;
257 }
258 
259 static Eina_Bool
_e_sys_phantom_wake_check_cb(void * data EINA_UNUSED)260 _e_sys_phantom_wake_check_cb(void *data EINA_UNUSED)
261 {
262    E_Action *act = e_action_find("suspend_smart");
263 
264    _e_sys_phantom_wake_check_timer = NULL;
265    if ((e_acpi_lid_is_closed()) && (act))
266      {
267         ERR("Phantom wake/resume while lid still closed? Suspending again");
268         if (act->func.go) act->func.go(E_OBJECT(e_zone_current_get()), NULL);
269      }
270    return EINA_FALSE;
271 }
272 
273 static Eina_Bool
_e_sys_comp_resume2(void * data EINA_UNUSED)274 _e_sys_comp_resume2(void *data EINA_UNUSED)
275 {
276    Eina_List *l;
277    E_Zone *zone;
278 
279    _e_sys_action_current = E_SYS_NONE;
280 #ifndef HAVE_WAYLAND_ONLY
281    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
282      _e_comp_x_screensaver_off();
283 #endif
284 #ifdef HAVE_WAYLAND
285    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
286      _e_comp_wl_screensaver_off();
287 #endif
288    EINA_LIST_FOREACH(e_comp->zones, l, zone)
289      e_backlight_level_set(zone, resume_backlight, -1.0);
290    _e_sys_comp_zones_fade(E_SYS_SUSPEND, "e,state,sys,resume", EINA_FALSE);
291    if (e_acpi_lid_is_closed())
292      {
293         if (_e_sys_phantom_wake_check_timer)
294           ecore_timer_del(_e_sys_phantom_wake_check_timer);
295         _e_sys_phantom_wake_check_timer =
296           ecore_timer_add(1.0, _e_sys_phantom_wake_check_cb, NULL);
297      }
298    printf("SSS: sys resume2 @ %1.8f\n", ecore_time_get());
299    return EINA_FALSE;
300 }
301 
302 static void
_e_sys_comp_resume(void)303 _e_sys_comp_resume(void)
304 {
305    printf("SSS: sys resume ... \n");
306    edje_thaw();
307    ecore_evas_manual_render_set(e_comp->ee, EINA_FALSE);
308    evas_damage_rectangle_add(e_comp->evas, 0, 0, e_comp->w, e_comp->h);
309 #ifndef HAVE_WAYLAND_ONLY
310    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
311      {
312         ecore_x_dpms_force(EINA_FALSE);
313         ecore_x_screensaver_resume();
314         ecore_x_screensaver_reset();
315      }
316 #endif
317 #ifdef HAVE_WAYLAND
318    if (e_comp->comp_type != E_PIXMAP_TYPE_X)
319      {
320         if (e_comp->screen && e_comp->screen->dpms)
321           e_comp->screen->dpms(0);
322      }
323 #endif
324    e_screensaver_deactivate();
325    if (_e_sys_screensaver_unignore_timer)
326      ecore_timer_del(_e_sys_screensaver_unignore_timer);
327    _e_sys_screensaver_unignore_timer =
328      ecore_timer_add(0.3, _e_sys_screensaver_unignore_delay, NULL);
329    ecore_timer_add(0.6, _e_sys_comp_resume2, NULL);
330    printf("SSS: sys resume @ %1.8f\n", ecore_time_get());
331 }
332 
333 static void
_e_sys_systemd_signal_prepare_shutdown(void * data EINA_UNUSED,const Eldbus_Message * msg)334 _e_sys_systemd_signal_prepare_shutdown(void *data EINA_UNUSED, const Eldbus_Message *msg)
335 {
336    EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
337    Eina_Bool b = EINA_FALSE;
338 
339    if (!eldbus_message_arguments_get(msg, "b", &b)) return;
340    printf("SSS: systemd said to prepare for shutdown! bool=%i @%1.8f\n", (int)b, ecore_time_get());
341    if (b)
342      {
343         if (!e_sys_on_the_way_out_get()) e_sys_action_do(E_SYS_LOGOUT, NULL);
344      }
345 }
346 
347 static void
_e_sys_systemd_signal_prepare_sleep(void * data EINA_UNUSED,const Eldbus_Message * msg)348 _e_sys_systemd_signal_prepare_sleep(void *data EINA_UNUSED, const Eldbus_Message *msg)
349 {
350    EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
351    Eina_Bool b = EINA_FALSE;
352 
353    if (!eldbus_message_arguments_get(msg, "b", &b)) return;
354    // b == 1 -> suspending
355    // b == 0 -> resuming
356    printf("SSS: systemd said to prepare for sleep! bool=%i @%1.8f\n", (int)b, ecore_time_get());
357    if (b == EINA_FALSE)
358      {
359         if (_e_sys_suspended)
360           {
361              _e_sys_suspended = EINA_FALSE;
362              ecore_event_add(E_EVENT_SYS_RESUME, NULL, NULL, NULL);
363              _e_sys_comp_resume();
364           }
365      }
366    else
367      {
368         _e_sys_suspended = EINA_TRUE;
369         if (e_config->desklock_on_suspend)
370           {
371              if (!e_desklock_state_get())
372                {
373                   // XXX: this desklock - ensure its instant
374                   e_desklock_show(EINA_TRUE);
375                }
376           }
377      }
378 }
379 
380 /* externally accessible functions */
381 EINTERN int
e_sys_init(void)382 e_sys_init(void)
383 {
384    Eldbus_Connection *conn;
385    Eldbus_Object *obj;
386 
387    conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
388    obj = eldbus_object_get(conn, "org.freedesktop.login1",
389                            "/org/freedesktop/login1");
390    login1_manger_proxy = eldbus_proxy_get(obj,
391                                           "org.freedesktop.login1.Manager");
392    eldbus_proxy_signal_handler_add(login1_manger_proxy, "PrepareForShutdown",
393                                    _e_sys_systemd_signal_prepare_shutdown,
394                                    NULL);
395    eldbus_proxy_signal_handler_add(login1_manger_proxy, "PrepareForSleep",
396                                    _e_sys_systemd_signal_prepare_sleep,
397                                    NULL);
398    eldbus_name_owner_get(conn, "org.freedesktop.login1",
399                          _e_sys_systemd_exists_cb, NULL);
400    _e_sys_systemd_handle_inhibit();
401 
402    E_EVENT_SYS_SUSPEND = ecore_event_type_new();
403    E_EVENT_SYS_HIBERNATE = ecore_event_type_new();
404    E_EVENT_SYS_RESUME = ecore_event_type_new();
405    return 1;
406 }
407 
408 EINTERN int
e_sys_shutdown(void)409 e_sys_shutdown(void)
410 {
411    if (_e_sys_halt_reboot_timer)
412      ecore_timer_del(_e_sys_halt_reboot_timer);
413    if (_e_sys_suspend_delay_timer)
414      ecore_timer_del(_e_sys_suspend_delay_timer);
415    if (_e_sys_hibernate_delay_timer)
416      ecore_timer_del(_e_sys_hibernate_delay_timer);
417    if (_e_sys_resume_delay_timer)
418      ecore_timer_del(_e_sys_resume_delay_timer);
419    if (_e_sys_screensaver_unignore_timer)
420      ecore_timer_del(_e_sys_screensaver_unignore_timer);
421    if (_e_sys_acpi_handler)
422      ecore_event_handler_del(_e_sys_acpi_handler);
423    _e_sys_halt_reboot_timer = NULL;
424    _e_sys_suspend_delay_timer = NULL;
425    _e_sys_hibernate_delay_timer = NULL;
426    _e_sys_resume_delay_timer = NULL;
427    _e_sys_screensaver_unignore_timer = NULL;
428    _e_sys_acpi_handler = NULL;
429    if (login1_manger_proxy)
430      {
431          Eldbus_Connection *conn;
432          Eldbus_Object *obj;
433 
434          obj = eldbus_proxy_object_get(login1_manger_proxy);
435          conn = eldbus_object_connection_get(obj);
436          eldbus_proxy_unref(login1_manger_proxy);
437          eldbus_object_unref(obj);
438          eldbus_connection_unref(conn);
439          login1_manger_proxy = NULL;
440      }
441    if (_e_sys_systemd_inhibit_fd >= 0)
442      {
443         close(_e_sys_systemd_inhibit_fd);
444         _e_sys_systemd_inhibit_fd = -1;
445      }
446    return 1;
447 }
448 
449 E_API int
e_sys_action_possible_get(E_Sys_Action a)450 e_sys_action_possible_get(E_Sys_Action a)
451 {
452    switch (a)
453      {
454       case E_SYS_EXIT:
455       case E_SYS_RESTART:
456       case E_SYS_EXIT_NOW:
457         return 1;
458 
459       case E_SYS_LOGOUT:
460         return 1;
461 
462       case E_SYS_HALT:
463       case E_SYS_HALT_NOW:
464         return _e_sys_can_halt;
465 
466       case E_SYS_REBOOT:
467         return _e_sys_can_reboot;
468 
469       case E_SYS_SUSPEND:
470         return _e_sys_can_suspend;
471 
472       case E_SYS_HIBERNATE:
473         return _e_sys_can_hibernate;
474 
475       default:
476         return 0;
477      }
478    return 0;
479 }
480 
481 E_API int
e_sys_action_do(E_Sys_Action a,char * param)482 e_sys_action_do(E_Sys_Action a, char *param)
483 {
484    int ret = 0;
485 
486    if (_e_sys_action_current != E_SYS_NONE)
487      {
488         _e_sys_current_action();
489         return 0;
490      }
491    e_config_save_flush();
492    switch (a)
493      {
494       case E_SYS_EXIT:
495       case E_SYS_RESTART:
496       case E_SYS_EXIT_NOW:
497       case E_SYS_LOGOUT:
498       case E_SYS_HALT_NOW:
499         on_the_way_out = EINA_TRUE;
500         EINA_FALLTHROUGH;
501 
502       case E_SYS_SUSPEND:
503       case E_SYS_HIBERNATE:
504         ret = _e_sys_action_do(a, param, EINA_FALSE);
505         break;
506 
507       case E_SYS_HALT:
508       case E_SYS_REBOOT:
509         on_the_way_out = EINA_TRUE;
510         if (!e_util_immortal_check())
511           ret = _e_sys_action_do(a, param, EINA_FALSE);
512         break;
513 
514       default:
515         break;
516      }
517 
518    printf("SSS: e_sys_ction_do ret=%i a=%i\n", ret, _e_sys_action_current);
519    if (ret) _e_sys_action_current = a;
520    else _e_sys_action_current = E_SYS_NONE;
521 
522    return ret;
523 }
524 
525 E_API int
e_sys_action_raw_do(E_Sys_Action a,char * param)526 e_sys_action_raw_do(E_Sys_Action a, char *param)
527 {
528    int ret = 0;
529 
530    e_config_save_flush();
531    if (_e_sys_action_current != E_SYS_NONE)
532      {
533         _e_sys_current_action();
534         return 0;
535      }
536 
537    ret = _e_sys_action_do(a, param, EINA_TRUE);
538 
539    printf("SSS: e_sys_ction_raw_do ret=%i a=%i\n", ret, _e_sys_action_current);
540    if (ret) _e_sys_action_current = a;
541    else _e_sys_action_current = E_SYS_NONE;
542 
543    return ret;
544 }
545 
546 static Eina_List *extra_actions = NULL;
547 
548 E_API E_Sys_Con_Action *
e_sys_con_extra_action_register(const char * label,const char * icon_group,const char * button_name,void (* func)(void * data),const void * data)549 e_sys_con_extra_action_register(const char *label,
550                                 const char *icon_group,
551                                 const char *button_name,
552                                 void (*func)(void *data),
553                                 const void *data)
554 {
555    E_Sys_Con_Action *sca;
556 
557    sca = E_NEW(E_Sys_Con_Action, 1);
558    if (label)
559      sca->label = eina_stringshare_add(label);
560    if (icon_group)
561      sca->icon_group = eina_stringshare_add(icon_group);
562    if (button_name)
563      sca->button_name = eina_stringshare_add(button_name);
564    sca->func = func;
565    sca->data = data;
566    extra_actions = eina_list_append(extra_actions, sca);
567    return sca;
568 }
569 
570 E_API void
e_sys_con_extra_action_unregister(E_Sys_Con_Action * sca)571 e_sys_con_extra_action_unregister(E_Sys_Con_Action *sca)
572 {
573    extra_actions = eina_list_remove(extra_actions, sca);
574    if (sca->label) eina_stringshare_del(sca->label);
575    if (sca->icon_group) eina_stringshare_del(sca->icon_group);
576    if (sca->button_name) eina_stringshare_del(sca->button_name);
577    free(sca);
578 }
579 
580 E_API const Eina_List *
e_sys_con_extra_action_list_get(void)581 e_sys_con_extra_action_list_get(void)
582 {
583    return extra_actions;
584 }
585 
586 E_API Eina_Bool
e_sys_on_the_way_out_get(void)587 e_sys_on_the_way_out_get(void)
588 {
589    return on_the_way_out;
590 }
591 
592 static void
_e_sys_systemd_inhibit_cb(void * data EINA_UNUSED,const Eldbus_Message * m,Eldbus_Pending * p EINA_UNUSED)593 _e_sys_systemd_inhibit_cb(void *data EINA_UNUSED, const Eldbus_Message *m, Eldbus_Pending *p EINA_UNUSED)
594 {
595    int fd = -1;
596    if (eldbus_message_error_get(m, NULL, NULL)) return;
597    if (!eldbus_message_arguments_get(m, "h", &fd))
598      _e_sys_systemd_inhibit_fd = fd;
599 }
600 
601 static void
_e_sys_systemd_handle_inhibit(void)602 _e_sys_systemd_handle_inhibit(void)
603 {
604    Eldbus_Message *m;
605 
606    if (!login1_manger_proxy) return;
607    if (!(m = eldbus_proxy_method_call_new(login1_manger_proxy, "Inhibit")))
608      return;
609    eldbus_message_arguments_append
610      (m, "ssss",
611          "handle-power-key:"
612          "handle-suspend-key:"
613          "handle-hibernate-key:"
614          "handle-lid-switch", // what
615          "Enlightenment", // who (string)
616          "Normal Execution", // why (string)
617          "block");
618    eldbus_proxy_send(login1_manger_proxy, m, _e_sys_systemd_inhibit_cb, NULL, -1);
619 }
620 
621 static void
_e_sys_systemd_check_cb(void * data,const Eldbus_Message * m,Eldbus_Pending * p EINA_UNUSED)622 _e_sys_systemd_check_cb(void *data, const Eldbus_Message *m, Eldbus_Pending *p EINA_UNUSED)
623 {
624    int *dest = data;
625    char *s = NULL;
626    if (!eldbus_message_arguments_get(m, "s", &s)) return;
627    if (!s) return;
628    if (!strcmp(s, "yes")) *dest = 1;
629    else *dest = 0;
630 }
631 
632 static void
_e_sys_systemd_check(void)633 _e_sys_systemd_check(void)
634 {
635    if (!login1_manger_proxy) return;
636    if (!eldbus_proxy_call(login1_manger_proxy, "CanPowerOff",
637                           _e_sys_systemd_check_cb, &_e_sys_can_halt, -1, ""))
638      return;
639    if (!eldbus_proxy_call(login1_manger_proxy, "CanReboot",
640                           _e_sys_systemd_check_cb, &_e_sys_can_reboot, -1, ""))
641      return;
642    if (!eldbus_proxy_call(login1_manger_proxy, "CanSuspend",
643                           _e_sys_systemd_check_cb, &_e_sys_can_suspend, -1, ""))
644      return;
645    if (!eldbus_proxy_call(login1_manger_proxy, "CanHibernate",
646                           _e_sys_systemd_check_cb, &_e_sys_can_hibernate, -1, ""))
647      return;
648 }
649 
650 static void
_e_sys_systemd_exists_cb(void * data EINA_UNUSED,const Eldbus_Message * m,Eldbus_Pending * p EINA_UNUSED)651 _e_sys_systemd_exists_cb(void *data EINA_UNUSED, const Eldbus_Message *m, Eldbus_Pending *p EINA_UNUSED)
652 {
653    const char *id = NULL;
654 
655    if (eldbus_message_error_get(m, NULL, NULL)) goto fail;
656    if (!eldbus_message_arguments_get(m, "s", &id)) goto fail;
657    if ((!id) || (id[0] != ':')) goto fail;
658    systemd_works = EINA_TRUE;
659    _e_sys_systemd_check();
660    return;
661 fail:
662    systemd_works = EINA_FALSE;
663    // just pretend to do everything in this case
664    _e_sys_can_halt = 1;
665    _e_sys_can_reboot = 1;
666    _e_sys_can_suspend = 1;
667    _e_sys_can_hibernate = 1;
668 }
669 
670 static void
_e_sys_systemd_poweroff(void)671 _e_sys_systemd_poweroff(void)
672 {
673    eldbus_proxy_call(login1_manger_proxy, "PowerOff", NULL, NULL, -1, "b", 0);
674 }
675 
676 static void
_e_sys_systemd_reboot(void)677 _e_sys_systemd_reboot(void)
678 {
679    eldbus_proxy_call(login1_manger_proxy, "Reboot", NULL, NULL, -1, "b", 0);
680 }
681 
682 static void
_e_sys_systemd_suspend(void)683 _e_sys_systemd_suspend(void)
684 {
685    eldbus_proxy_call(login1_manger_proxy, "Suspend", NULL, NULL, -1, "b", 0);
686 }
687 
688 static void
_e_sys_systemd_hibernate(void)689 _e_sys_systemd_hibernate(void)
690 {
691    eldbus_proxy_call(login1_manger_proxy, "Hibernate", NULL, NULL, -1, "b", 0);
692 }
693 
694 static Eina_Bool
_e_sys_resume_delay(void * d EINA_UNUSED)695 _e_sys_resume_delay(void *d EINA_UNUSED)
696 {
697    printf("SSS: hib check resume delay...\n");
698    _e_sys_resume_delay_timer = NULL;
699    if (_e_sys_suspended)
700      {
701         printf("SSS: suspended to false\n");
702         _e_sys_suspended = EINA_FALSE;
703         ecore_event_add(E_EVENT_SYS_RESUME, NULL, NULL, NULL);
704         _e_sys_comp_resume();
705      }
706    return EINA_FALSE;
707 }
708 
709 static Eina_Bool
_e_sys_susp_hib_check_timer_cb(void * data EINA_UNUSED)710 _e_sys_susp_hib_check_timer_cb(void *data EINA_UNUSED)
711 {
712    double t = ecore_time_unix_get();
713 
714    printf("SSS: hib check @%1.8f (unix %1.8f, delt %1.8f)\n", ecore_time_get(), t, t -  _e_sys_susp_hib_check_last_tick);
715    if ((t - _e_sys_susp_hib_check_last_tick) > 0.5)
716      {
717         printf("SSS: hib check long gap\n");
718         _e_sys_susp_hib_check_timer = NULL;
719         if (_e_sys_resume_delay_timer)
720           ecore_timer_del(_e_sys_resume_delay_timer);
721         _e_sys_resume_delay_timer =
722           ecore_timer_add(0.2, _e_sys_resume_delay, NULL);
723         return EINA_FALSE;
724      }
725    _e_sys_susp_hib_check_last_tick = t;
726    return EINA_TRUE;
727 }
728 
729 static void
_e_sys_susp_hib_check(void)730 _e_sys_susp_hib_check(void)
731 {
732    if (_e_sys_susp_hib_check_timer)
733      ecore_timer_del(_e_sys_susp_hib_check_timer);
734    _e_sys_susp_hib_check_last_tick = ecore_time_unix_get();
735    _e_sys_susp_hib_check_timer =
736      ecore_timer_loop_add(0.1, _e_sys_susp_hib_check_timer_cb, NULL);
737    printf("SSS: hib check begin @%1.8f (unix %1.8f)\n", ecore_time_get(), _e_sys_susp_hib_check_last_tick);
738 }
739 
740 /* local subsystem functions */
741 static void
_e_sys_cb_logout_logout(void * data EINA_UNUSED,E_Dialog * dia)742 _e_sys_cb_logout_logout(void *data EINA_UNUSED, E_Dialog *dia)
743 {
744    if (_e_sys_logout_timer)
745      {
746         ecore_timer_del(_e_sys_logout_timer);
747         _e_sys_logout_timer = NULL;
748      }
749    _e_sys_logout_begin_time = 0.0;
750    _e_sys_logout_after();
751    e_object_del(E_OBJECT(dia));
752    _e_sys_logout_confirm_dialog = NULL;
753 }
754 
755 static void
_e_sys_cb_logout_wait(void * data EINA_UNUSED,E_Dialog * dia)756 _e_sys_cb_logout_wait(void *data EINA_UNUSED, E_Dialog *dia)
757 {
758    if (_e_sys_logout_timer) ecore_timer_del(_e_sys_logout_timer);
759    _e_sys_logout_timer = ecore_timer_loop_add(0.5, _e_sys_cb_logout_timer, NULL);
760    _e_sys_logout_begin_time = ecore_time_get();
761    e_object_del(E_OBJECT(dia));
762    _e_sys_logout_confirm_dialog = NULL;
763 }
764 
765 static void
_e_sys_cb_logout_abort(void * data EINA_UNUSED,E_Dialog * dia)766 _e_sys_cb_logout_abort(void *data EINA_UNUSED, E_Dialog *dia)
767 {
768    if (_e_sys_logout_timer)
769      {
770         ecore_timer_del(_e_sys_logout_timer);
771         _e_sys_logout_timer = NULL;
772      }
773    _e_sys_logout_begin_time = 0.0;
774    e_object_del(E_OBJECT(dia));
775    _e_sys_logout_confirm_dialog = NULL;
776    _e_sys_action_current = E_SYS_NONE;
777    _e_sys_action_after = E_SYS_NONE;
778    _e_sys_action_after_raw = EINA_FALSE;
779 }
780 
781 static void
_e_sys_logout_confirm_dialog_update(int remaining)782 _e_sys_logout_confirm_dialog_update(int remaining)
783 {
784    char txt[4096];
785 
786    if (!_e_sys_logout_confirm_dialog)
787      {
788         fputs("ERROR: updating logout confirm dialog, but none exists!\n",
789               stderr);
790         return;
791      }
792 
793    snprintf(txt, sizeof(txt),
794             _("Logout is taking too long.<ps/>"
795               "Some applications refuse to close.<ps/>"
796               "Do you want to finish the logout<ps/>"
797               "anyway without closing these<ps/>"
798               "applications first?<ps/><ps/>"
799               "Auto logout in %d seconds."), remaining);
800 
801    e_dialog_text_set(_e_sys_logout_confirm_dialog, txt);
802 }
803 
804 static Eina_Bool
_e_sys_cb_logout_timer(void * data EINA_UNUSED)805 _e_sys_cb_logout_timer(void *data EINA_UNUSED)
806 {
807    E_Client *ec;
808    int pending = 0;
809 
810    E_CLIENT_FOREACH(ec)
811      {
812         if (e_client_util_ignored_get(ec)) continue;
813         if (!ec->internal) pending++;
814      }
815    if (pending == 0) goto after;
816    else if (_e_sys_logout_confirm_dialog)
817      {
818         int remaining = E_LOGOUT_AUTO_TIME -
819           round(ecore_loop_time_get() - _e_sys_logout_begin_time);
820         /* it has taken 60 (E_LOGOUT_AUTO_TIME) seconds of waiting the
821          * confirm dialog and we still have apps that will not go
822          * away. Do the action as user may be far away or forgot it.
823          *
824          * NOTE: this is the behavior for many operating systems and I
825          *       guess the reason is people that hit "shutdown" and
826          *       put their laptops in their backpacks in the hope
827          *       everything will be turned off properly.
828          */
829         if (remaining > 0)
830           {
831              _e_sys_logout_confirm_dialog_update(remaining);
832              return ECORE_CALLBACK_RENEW;
833           }
834         else
835           {
836              _e_sys_cb_logout_logout(NULL, _e_sys_logout_confirm_dialog);
837              return ECORE_CALLBACK_CANCEL;
838           }
839      }
840    else
841      {
842         // it has taken E_LOGOUT_WAIT_TIME seconds of waiting and we still
843         // have apps that will not go away
844         double now = ecore_loop_time_get();
845         if ((now - _e_sys_logout_begin_time) > E_LOGOUT_WAIT_TIME)
846           {
847              E_Dialog *dia;
848 
849              dia = e_dialog_new(NULL, "E", "_sys_error_logout_slow");
850              if (dia)
851                {
852                   _e_sys_logout_confirm_dialog = dia;
853                   e_dialog_title_set(dia, _("Logout problems"));
854                   e_dialog_icon_set(dia, "system-log-out", 64);
855                   _e_sys_logout_confirm_dialog_update(E_LOGOUT_AUTO_TIME);
856                   e_dialog_button_add(dia, _("Logout now"), NULL,
857                                       _e_sys_cb_logout_logout, NULL);
858                   e_dialog_button_add(dia, _("Wait longer"), NULL,
859                                       _e_sys_cb_logout_wait, NULL);
860                   e_dialog_button_add(dia, _("Cancel Logout"), NULL,
861                                       _e_sys_cb_logout_abort, NULL);
862                   e_dialog_button_focus_num(dia, 1);
863                   elm_win_center(dia->win, 1, 1);
864                   e_win_no_remember_set(dia->win, 1);
865                   e_dialog_show(dia);
866                   _e_sys_logout_begin_time = now;
867                   resume_backlight = e_config->backlight.normal;
868                }
869              _e_sys_comp_resume();
870              return ECORE_CALLBACK_RENEW;
871           }
872      }
873    return ECORE_CALLBACK_RENEW;
874 after:
875    switch (_e_sys_action_after)
876      {
877       case E_SYS_EXIT:
878         _e_sys_comp_logout();
879         break;
880       case E_SYS_HALT:
881       case E_SYS_HALT_NOW:
882         _e_sys_comp_shutdown();
883         break;
884       case E_SYS_REBOOT:
885         _e_sys_comp_reboot();
886         break;
887       default: break;
888      }
889    _e_sys_logout_timer = NULL;
890    return ECORE_CALLBACK_CANCEL;
891 }
892 
893 static void
_e_sys_logout_after(void)894 _e_sys_logout_after(void)
895 {
896    printf("SSS: sys action after %i\n", _e_sys_action_after);
897    _e_sys_action_current = _e_sys_action_after;
898    _e_sys_action_do(_e_sys_action_after, NULL, _e_sys_action_after_raw);
899    _e_sys_action_after = E_SYS_NONE;
900    _e_sys_action_after_raw = EINA_FALSE;
901 }
902 
903 static void
_e_sys_logout_begin(E_Sys_Action a_after,Eina_Bool raw)904 _e_sys_logout_begin(E_Sys_Action a_after, Eina_Bool raw)
905 {
906    const Eina_List *l, *ll;
907    E_Client *ec;
908 
909    stopping = 1;
910    /* start logout - at end do the a_after action */
911    _e_sys_action_after = a_after;
912    _e_sys_action_after_raw = raw;
913    EINA_LIST_FOREACH_SAFE(e_comp->clients, l, ll, ec)
914      {
915         e_client_act_close_begin(ec);
916      }
917    /* and poll to see if all pending windows are gone yet every 0.5 sec */
918    _e_sys_logout_begin_time = ecore_time_get();
919    if (_e_sys_logout_timer) ecore_timer_del(_e_sys_logout_timer);
920    _e_sys_logout_timer = ecore_timer_loop_add(0.5, _e_sys_cb_logout_timer, NULL);
921 }
922 
923 static void
_e_sys_restart_begin(E_Sys_Action a_after,Eina_Bool raw)924 _e_sys_restart_begin(E_Sys_Action a_after, Eina_Bool raw)
925 {
926    _e_sys_action_after = a_after;
927    _e_sys_action_after_raw = raw;
928 }
929 
930 static void
_e_sys_current_action(void)931 _e_sys_current_action(void)
932 {
933    /* display dialog that currently an action is in progress */
934    E_Dialog *dia;
935 
936    dia = e_dialog_new(NULL,
937                       "E", "_sys_error_action_busy");
938    if (!dia) return;
939 
940    e_dialog_title_set(dia, _("Enlightenment is busy with another request"));
941    e_dialog_icon_set(dia, "enlightenment/sys", 64);
942    switch (_e_sys_action_current)
943      {
944       case E_SYS_LOGOUT:
945         e_dialog_text_set(dia, _("Logging out.<ps/>"
946                                  "You cannot perform other system actions<ps/>"
947                                  "once a logout has begun."));
948         break;
949 
950       case E_SYS_HALT:
951       case E_SYS_HALT_NOW:
952         e_dialog_text_set(dia, _("Powering off.<ps/>"
953                                  "You cannot perform any other system actions<ps/>"
954                                  "once a shutdown has been started."));
955         break;
956 
957       case E_SYS_REBOOT:
958         e_dialog_text_set(dia, _("Resetting.<ps/>"
959                                  "You cannot perform any other system actions<ps/>"
960                                  "once a reboot has begun."));
961         break;
962 
963       case E_SYS_SUSPEND:
964         e_dialog_text_set(dia, _("Suspending.<ps/>"
965                                  "You cannot perform any other system actions<ps/>"
966                                  "until suspend is complete."));
967         break;
968 
969       case E_SYS_HIBERNATE:
970         e_dialog_text_set(dia, _("Hibernating.<ps/>"
971                                  "You cannot perform any other system actions<ps/>"
972                                  "until hibernation is complete."));
973         break;
974 
975       default:
976         e_dialog_text_set(dia, _("EEK! This should not happen"));
977         break;
978      }
979    e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
980    e_dialog_button_focus_num(dia, 0);
981    elm_win_center(dia->win, 1, 1);
982    e_win_no_remember_set(dia->win, 1);
983    e_dialog_show(dia);
984 }
985 
986 static Eina_Bool
_e_sys_cb_acpi_event(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)987 _e_sys_cb_acpi_event(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
988 {
989    E_Event_Acpi *ev = event;
990 
991    if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE)
992      {
993         if (((ev->type == E_ACPI_TYPE_LID) &&
994              (ev->status == E_ACPI_LID_OPEN)) ||
995             (ev->type == E_ACPI_TYPE_POWER) ||
996             (ev->type == E_ACPI_TYPE_SLEEP))
997           {
998              if (_e_sys_acpi_handler)
999                {
1000                   ecore_event_handler_del(_e_sys_acpi_handler);
1001                   _e_sys_acpi_handler = NULL;
1002                }
1003              e_powersave_mode_unforce();
1004              ecore_timer_add(1.0, _e_sys_resume_delay, NULL);
1005              // XXX: need some way of, at the system level, restoring
1006              // system and devices back to running normally
1007           }
1008      }
1009    return ECORE_CALLBACK_PASS_ON;
1010 }
1011 
1012 static Eina_Bool
_e_sys_suspend_delay(void * data EINA_UNUSED)1013 _e_sys_suspend_delay(void *data EINA_UNUSED)
1014 {
1015    _e_sys_suspend_delay_timer = NULL;
1016    _e_sys_begin_time = ecore_time_get();
1017    if (e_config->suspend_connected_standby == 0)
1018      {
1019         if (systemd_works) _e_sys_systemd_suspend();
1020         else
1021           {
1022              _e_sys_susp_hib_check();
1023              e_system_send("power-suspend", NULL);
1024           }
1025      }
1026    else
1027      {
1028         if (_e_sys_acpi_handler)
1029         ecore_event_handler_del(_e_sys_acpi_handler);
1030         _e_sys_acpi_handler =
1031         ecore_event_handler_add(E_EVENT_ACPI,
1032                                 _e_sys_cb_acpi_event,
1033                                 NULL);
1034         e_powersave_mode_force(E_POWERSAVE_MODE_FREEZE);
1035         // XXX: need some system way of forcing the system into a very low
1036         // power level with as many devices suspended as possible. below is
1037         // a simple "freeze the cpu/kernel" which is not what we want actually
1038         //   sleep 2 && echo freeze | sudo tee /sys/power/state
1039      }
1040    return EINA_FALSE;
1041 }
1042 
1043 static Eina_Bool
_e_sys_hibernate_delay(void * data EINA_UNUSED)1044 _e_sys_hibernate_delay(void *data EINA_UNUSED)
1045 {
1046    _e_sys_hibernate_delay_timer = NULL;
1047    _e_sys_begin_time = ecore_time_get();
1048    if (systemd_works) _e_sys_systemd_hibernate();
1049    else
1050      {
1051         _e_sys_susp_hib_check();
1052         e_system_send("power-hibernate", NULL);
1053      }
1054    return EINA_FALSE;
1055 }
1056 
1057 static Eina_Bool
_e_sys_halt_reboot(void * data EINA_UNUSED)1058 _e_sys_halt_reboot(void *data EINA_UNUSED)
1059 {
1060    _e_sys_halt_reboot_timer = NULL;
1061    ecore_main_loop_quit();
1062    return EINA_FALSE;
1063 }
1064 
1065 static int
_e_sys_action_do(E_Sys_Action a,char * param EINA_UNUSED,Eina_Bool raw)1066 _e_sys_action_do(E_Sys_Action a, char *param EINA_UNUSED, Eina_Bool raw)
1067 {
1068    int ret = 0;
1069 
1070    switch (a)
1071      {
1072       case E_SYS_EXIT:
1073         // XXX TODO: check for e_fm_op_registry entries and confirm
1074         if (!e_util_immortal_check())
1075           {
1076              e_fm2_die();
1077              ecore_main_loop_quit();
1078              ret = 1;
1079           }
1080         else
1081           return 0;
1082         break;
1083 
1084       case E_SYS_RESTART:
1085         // XXX TODO: check for e_fm_op_registry entries and confirm
1086         // FIXME: we don't share out immortal info to restarted e. :(
1087 //	if (!e_util_immortal_check())
1088         if (raw)
1089           {
1090              e_fm2_die();
1091              restart = 1;
1092              ecore_main_loop_quit();
1093              ret = 1;
1094           }
1095         else
1096           {
1097              _e_sys_restart_begin(E_SYS_RESTART, raw);
1098              _e_sys_comp_restart();
1099              return 0;
1100           }
1101 //        else
1102 //          return 0;
1103       break;
1104 
1105       case E_SYS_EXIT_NOW:
1106         exit(0);
1107         break;
1108 
1109       case E_SYS_LOGOUT:
1110         // XXX TODO: check for e_fm_op_registry entries and confirm
1111         if (raw)
1112           {
1113              e_fm2_die();
1114              _e_sys_logout_after();
1115           }
1116         else if (!_e_sys_comp_waiting)
1117           {
1118              _e_sys_logout_begin(E_SYS_EXIT, raw);
1119           }
1120         break;
1121 
1122       case E_SYS_HALT:
1123       case E_SYS_HALT_NOW:
1124         /* shutdown -h now */
1125         if (e_util_immortal_check()) return 0;
1126         e_fm2_die();
1127         if (!_e_sys_comp_waiting)
1128           {
1129              if (raw)
1130                {
1131                   printf("SSS: do actual halt...\n");
1132                   _e_sys_begin_time = ecore_time_get();
1133                   if (systemd_works)
1134                     {
1135                        printf("SSS: tell systemd to halt...\n");
1136                        _e_sys_systemd_poweroff();
1137                     }
1138                   else
1139                     {
1140                        printf("SSS: tell e system service to halt...\n");
1141                        e_system_send("power-halt", NULL);
1142                     }
1143                   if (!_e_sys_halt_reboot_timer)
1144                     _e_sys_halt_reboot_timer = ecore_timer_add
1145                       (1.0, _e_sys_halt_reboot, NULL);
1146                   ret = 1;
1147                }
1148              else
1149                {
1150                   printf("SSS: begin halt...\n");
1151                   ret = 0;
1152                   _e_sys_begin_time = ecore_time_get();
1153                   _e_sys_logout_begin(a, EINA_TRUE);
1154                }
1155              /* FIXME: display halt status */
1156           }
1157         break;
1158 
1159       case E_SYS_REBOOT:
1160         /* shutdown -r now */
1161         if (e_util_immortal_check()) return 0;
1162         e_fm2_die();
1163         if (!_e_sys_comp_waiting)
1164           {
1165              if (raw)
1166                {
1167                   printf("SSS: do actual reboot...\n");
1168                   _e_sys_begin_time = ecore_time_get();
1169                   if (systemd_works)
1170                     {
1171                        printf("SSS: tell systemd to reboot...\n");
1172                        _e_sys_systemd_reboot();
1173                     }
1174                   else
1175                     {
1176                        printf("SSS: tell e system service to reboot...\n");
1177                        e_system_send("power-reboot", NULL);
1178                     }
1179                   if (!_e_sys_halt_reboot_timer)
1180                     _e_sys_halt_reboot_timer = ecore_timer_add
1181                       (1.0, _e_sys_halt_reboot, NULL);
1182                   ret = 1;
1183                }
1184              else
1185                {
1186                   printf("SSS: begin reboot...\n");
1187                   ret = 0;
1188                   _e_sys_begin_time = ecore_time_get();
1189                   _e_sys_logout_begin(a, EINA_TRUE);
1190                }
1191           }
1192         break;
1193 
1194       case E_SYS_SUSPEND:
1195         /* /etc/acpi/sleep.sh force */
1196         if (!_e_sys_comp_waiting)
1197           {
1198              if (_e_sys_phantom_wake_check_timer)
1199                ecore_timer_del(_e_sys_phantom_wake_check_timer);
1200              _e_sys_phantom_wake_check_timer = NULL;
1201              if (raw)
1202                {
1203                   _e_sys_suspended = EINA_TRUE;
1204                   if (e_config->desklock_on_suspend)
1205                   // XXX: this desklock - ensure its instant
1206                     e_desklock_show(EINA_TRUE);
1207                   if (_e_sys_suspend_delay_timer)
1208                     ecore_timer_del(_e_sys_suspend_delay_timer);
1209                   if (e_config->suspend_connected_standby == 0) ret = 1;
1210                   // XXX: make timer shorter if desklock is instant
1211                   _e_sys_suspend_delay_timer =
1212                     ecore_timer_add(0.5, _e_sys_suspend_delay, NULL);
1213                }
1214              else
1215                {
1216                   ecore_event_add(E_EVENT_SYS_SUSPEND, NULL, NULL, NULL);
1217                   _e_sys_comp_suspend();
1218                   return 0;
1219                }
1220              /* FIXME: display suspend status */
1221           }
1222         break;
1223 
1224       case E_SYS_HIBERNATE:
1225         /* /etc/acpi/hibernate.sh force */
1226         if (!_e_sys_comp_waiting)
1227           {
1228              if (_e_sys_phantom_wake_check_timer)
1229                ecore_timer_del(_e_sys_phantom_wake_check_timer);
1230              _e_sys_phantom_wake_check_timer = NULL;
1231              if (raw)
1232                {
1233                   _e_sys_suspended = EINA_TRUE;
1234                   if (e_config->desklock_on_suspend)
1235                   // XXX: this desklock - ensure its instant
1236                     e_desklock_show(EINA_TRUE);
1237                   if (_e_sys_hibernate_delay_timer)
1238                     ecore_timer_del(_e_sys_hibernate_delay_timer);
1239                   ret = 1;
1240                   // XXX: make timer shorter if desklock is instant
1241                   _e_sys_hibernate_delay_timer =
1242                     ecore_timer_add(0.5, _e_sys_hibernate_delay, NULL);
1243                }
1244              else
1245                {
1246                   ecore_event_add(E_EVENT_SYS_HIBERNATE, NULL, NULL, NULL);
1247                   _e_sys_comp_hibernate();
1248                   return 0;
1249                }
1250              /* FIXME: display hibernate status */
1251           }
1252         break;
1253 
1254       default:
1255         return 0;
1256      }
1257    return ret;
1258 }
1259