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