3 /* local subsystem functions */
4 static Eina_Bool _e_sys_cb_timer(void *data);
5 static Eina_Bool _e_sys_cb_exit(void *data, int type, void *event);
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);
12 static void _e_sys_current_action(void);
13 static void _e_sys_action_failed(void);
14 static int _e_sys_action_do(E_Sys_Action a, char *param);
15 static void _e_sys_dialog_cb_delete(E_Obj_Dialog * od);
17 static Ecore_Event_Handler *_e_sys_exe_exit_handler = NULL;
18 static Ecore_Exe *_e_sys_halt_check_exe = NULL;
19 static Ecore_Exe *_e_sys_reboot_check_exe = NULL;
20 static Ecore_Exe *_e_sys_suspend_check_exe = NULL;
21 static Ecore_Exe *_e_sys_hibernate_check_exe = NULL;
22 static int _e_sys_can_halt = 0;
23 static int _e_sys_can_reboot = 0;
24 static int _e_sys_can_suspend = 0;
25 static int _e_sys_can_hibernate = 0;
27 static E_Sys_Action _e_sys_action_current = E_SYS_NONE;
28 static E_Sys_Action _e_sys_action_after = E_SYS_NONE;
29 static Ecore_Exe *_e_sys_exe = NULL;
30 static double _e_sys_logout_begin_time = 0.0;
31 static Ecore_Timer *_e_sys_logout_timer = NULL;
32 static E_Obj_Dialog *_e_sys_dialog = NULL;
33 static E_Dialog *_e_sys_logout_confirm_dialog = NULL;
35 static const int E_LOGOUT_AUTO_TIME = 60;
36 static const int E_LOGOUT_WAIT_TIME = 15;
38 /* externally accessible functions */
42 /* this is not optimal - but it does work cleanly */
43 _e_sys_exe_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
44 _e_sys_cb_exit, NULL);
45 /* delay this for 1.0 seconds while the rest of e starts up */
46 ecore_timer_add(1.0, _e_sys_cb_timer, NULL);
53 if (_e_sys_exe_exit_handler)
54 ecore_event_handler_del(_e_sys_exe_exit_handler);
55 _e_sys_exe_exit_handler = NULL;
56 _e_sys_halt_check_exe = NULL;
57 _e_sys_reboot_check_exe = NULL;
58 _e_sys_suspend_check_exe = NULL;
59 _e_sys_hibernate_check_exe = NULL;
64 e_sys_action_possible_get(E_Sys_Action a)
76 return _e_sys_can_halt;
78 return _e_sys_can_reboot;
80 return _e_sys_can_suspend;
82 return _e_sys_can_hibernate;
90 e_sys_action_do(E_Sys_Action a, char *param)
94 if (_e_sys_action_current != E_SYS_NONE)
96 _e_sys_current_action();
106 case E_SYS_HIBERNATE:
108 ret = _e_sys_action_do(a, param);
112 if (!e_util_immortal_check()) _e_sys_logout_begin(a);
118 _e_sys_action_current = a;
122 static Eina_List *extra_actions = NULL;
124 EAPI E_Sys_Con_Action *
125 e_sys_con_extra_action_register(const char *label,
126 const char *icon_group,
127 const char *button_name,
128 void (*func) (void *data),
131 E_Sys_Con_Action *sca;
133 sca = E_NEW(E_Sys_Con_Action, 1);
135 sca->label = eina_stringshare_add(label);
137 sca->icon_group = eina_stringshare_add(icon_group);
139 sca->button_name = eina_stringshare_add(button_name);
142 extra_actions = eina_list_append(extra_actions, sca);
147 e_sys_con_extra_action_unregister(E_Sys_Con_Action *sca)
149 extra_actions = eina_list_remove(extra_actions, sca);
150 if (sca->label) eina_stringshare_del(sca->label);
151 if (sca->icon_group) eina_stringshare_del(sca->icon_group);
152 if (sca->button_name) eina_stringshare_del(sca->button_name);
156 EAPI const Eina_List *
157 e_sys_con_extra_action_list_get(void)
159 return extra_actions;
162 /* local subsystem functions */
164 _e_sys_cb_timer(void *data __UNUSED__)
166 /* exec out sys helper and ask it to test if we are allowed to do these
171 e_init_status_set(_("Checking System Permissions"));
172 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys -t halt", e_prefix_lib_get());
173 _e_sys_halt_check_exe = ecore_exe_run(buf, NULL);
174 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys -t reboot", e_prefix_lib_get());
175 _e_sys_reboot_check_exe = ecore_exe_run(buf, NULL);
176 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys -t suspend", e_prefix_lib_get());
177 _e_sys_suspend_check_exe = ecore_exe_run(buf, NULL);
178 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys -t hibernate", e_prefix_lib_get());
179 _e_sys_hibernate_check_exe = ecore_exe_run(buf, NULL);
180 return ECORE_CALLBACK_CANCEL;
184 _e_sys_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
186 Ecore_Exe_Event_Del *ev;
189 if ((_e_sys_exe) && (ev->exe == _e_sys_exe))
191 if (ev->exit_code != 0) _e_sys_action_failed();
192 if (((_e_sys_action_current != E_SYS_HALT) &&
193 (_e_sys_action_current != E_SYS_HALT_NOW) &&
194 (_e_sys_action_current != E_SYS_REBOOT)) ||
195 (ev->exit_code != 0))
199 e_object_del(E_OBJECT(_e_sys_dialog));
200 _e_sys_dialog = NULL;
203 _e_sys_action_current = E_SYS_NONE;
205 return ECORE_CALLBACK_RENEW;
207 if ((_e_sys_halt_check_exe) && (ev->exe == _e_sys_halt_check_exe))
209 e_init_status_set(_("System Check Done"));
210 /* exit_code: 0 == OK, 5 == suid root removed, 7 == group id error
211 * 10 == permission denied, 20 == action undefined */
212 if (ev->exit_code == 0)
215 _e_sys_halt_check_exe = NULL;
218 else if ((_e_sys_reboot_check_exe) && (ev->exe == _e_sys_reboot_check_exe))
220 e_init_status_set(_("System Check Done"));
221 if (ev->exit_code == 0)
223 _e_sys_can_reboot = 1;
224 _e_sys_reboot_check_exe = NULL;
227 else if ((_e_sys_suspend_check_exe) && (ev->exe == _e_sys_suspend_check_exe))
229 e_init_status_set(_("System Check Done"));
230 if (ev->exit_code == 0)
232 _e_sys_can_suspend = 1;
233 _e_sys_suspend_check_exe = NULL;
236 else if ((_e_sys_hibernate_check_exe) && (ev->exe == _e_sys_hibernate_check_exe))
238 e_init_status_set(_("System Check Done"));
239 if (ev->exit_code == 0)
241 _e_sys_can_hibernate = 1;
242 _e_sys_hibernate_check_exe = NULL;
245 return ECORE_CALLBACK_RENEW;
249 _e_sys_cb_logout_logout(void *data __UNUSED__, E_Dialog *dia)
251 if (_e_sys_logout_timer)
253 ecore_timer_del(_e_sys_logout_timer);
254 _e_sys_logout_timer = NULL;
256 _e_sys_logout_begin_time = 0.0;
257 _e_sys_logout_after();
258 e_object_del(E_OBJECT(dia));
259 _e_sys_logout_confirm_dialog = NULL;
263 _e_sys_cb_logout_wait(void *data __UNUSED__, E_Dialog *dia)
265 if (_e_sys_logout_timer) ecore_timer_del(_e_sys_logout_timer);
266 _e_sys_logout_timer = ecore_timer_add(0.5, _e_sys_cb_logout_timer, NULL);
267 _e_sys_logout_begin_time = ecore_time_get();
268 e_object_del(E_OBJECT(dia));
269 _e_sys_logout_confirm_dialog = NULL;
273 _e_sys_cb_logout_abort(void *data __UNUSED__, E_Dialog *dia)
275 if (_e_sys_logout_timer)
277 ecore_timer_del(_e_sys_logout_timer);
278 _e_sys_logout_timer = NULL;
280 _e_sys_logout_begin_time = 0.0;
281 e_object_del(E_OBJECT(dia));
282 _e_sys_logout_confirm_dialog = NULL;
283 _e_sys_action_current = E_SYS_NONE;
284 _e_sys_action_after = E_SYS_NONE;
287 e_object_del(E_OBJECT(_e_sys_dialog));
288 _e_sys_dialog = NULL;
293 _e_sys_logout_confirm_dialog_update(int remaining)
297 if (!_e_sys_logout_confirm_dialog)
299 fputs("ERROR: updating logout confirm dialog, but none exists!\n",
304 snprintf(txt, sizeof(txt),
305 _("Logout is taking too long.<br>"
306 "Some applications refuse to close.<br>"
307 "Do you want to finish the logout<br>"
308 "anyway without closing these<br>"
309 "applications first?<br><br>"
310 "Auto logout in %d seconds."),
313 e_dialog_text_set(_e_sys_logout_confirm_dialog, txt);
317 _e_sys_cb_logout_timer(void *data __UNUSED__)
323 EINA_LIST_FOREACH(e_border_client_list(), l, bd)
325 if (!bd->internal) pending++;
327 if (pending == 0) goto after;
328 else if (_e_sys_logout_confirm_dialog)
330 int remaining = E_LOGOUT_AUTO_TIME -
331 round(ecore_loop_time_get() - _e_sys_logout_begin_time);
332 /* it has taken 60 (E_LOGOUT_AUTO_TIME) seconds of waiting the
333 * confirm dialog and we still have apps that will not go
334 * away. Do the action as user may be far away or forgot it.
336 * NOTE: this is the behavior for many operating systems and I
337 * guess the reason is people that hit "shutdown" and
338 * put their laptops in their backpacks in the hope
339 * everything will be turned off properly.
343 _e_sys_logout_confirm_dialog_update(remaining);
344 return ECORE_CALLBACK_RENEW;
348 _e_sys_cb_logout_logout(NULL, _e_sys_logout_confirm_dialog);
349 return ECORE_CALLBACK_CANCEL;
354 /* it has taken 15 seconds of waiting and we still have apps that
357 double now = ecore_loop_time_get();
358 if ((now - _e_sys_logout_begin_time) > E_LOGOUT_WAIT_TIME)
362 dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_logout_slow");
365 _e_sys_logout_confirm_dialog = dia;
366 e_dialog_title_set(dia, _("Logout problems"));
367 e_dialog_icon_set(dia, "system-log-out", 64);
368 e_dialog_button_add(dia, _("Logout now"), NULL, _e_sys_cb_logout_logout, NULL);
369 e_dialog_button_add(dia, _("Wait longer"), NULL, _e_sys_cb_logout_wait, NULL);
370 e_dialog_button_add(dia, _("Cancel Logout"), NULL, _e_sys_cb_logout_abort, NULL);
371 e_dialog_button_focus_num(dia, 1);
372 _e_sys_logout_confirm_dialog_update(E_LOGOUT_AUTO_TIME);
373 e_win_centered_set(dia->win, 1);
375 _e_sys_logout_begin_time = now;
377 return ECORE_CALLBACK_RENEW;
380 return ECORE_CALLBACK_RENEW;
382 _e_sys_logout_after();
383 _e_sys_logout_timer = NULL;
384 return ECORE_CALLBACK_CANCEL;
388 _e_sys_logout_after(void)
392 e_object_del(E_OBJECT(_e_sys_dialog));
393 _e_sys_dialog = NULL;
395 _e_sys_action_current = _e_sys_action_after;
396 _e_sys_action_do(_e_sys_action_after, NULL);
397 _e_sys_action_after = E_SYS_NONE;
401 _e_sys_logout_begin(E_Sys_Action a_after)
407 /* start logout - at end do the a_after action */
408 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
409 _("Logout in progress"), "E", "_sys_logout");
410 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/logout");
411 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
412 _("Logout in progress.<br>"
413 "<hilight>Please wait.</hilight>"));
414 e_obj_dialog_show(od);
415 e_obj_dialog_icon_set(od, "system-log-out");
416 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
418 _e_sys_action_after = a_after;
419 EINA_LIST_FOREACH(e_border_client_list(), l, bd)
421 e_border_act_close_begin(bd);
423 /* and poll to see if all pending windows are gone yet every 0.5 sec */
424 _e_sys_logout_begin_time = ecore_time_get();
425 if (_e_sys_logout_timer) ecore_timer_del(_e_sys_logout_timer);
426 _e_sys_logout_timer = ecore_timer_add(0.5, _e_sys_cb_logout_timer, NULL);
430 _e_sys_current_action(void)
432 /* display dialog that currently an action is in progress */
435 dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_action_busy");
438 e_dialog_title_set(dia, _("Enlightenment is busy with another request"));
439 e_dialog_icon_set(dia, "enlightenment/sys", 64);
440 switch (_e_sys_action_current)
443 e_dialog_text_set(dia,
445 "You cannot perform other system actions<br>"
446 "once a logout has begun.")
451 e_dialog_text_set(dia,
452 _("Powering off.<br>"
453 "You cannot do any other system actions<br>"
454 "once a shutdown has been started.")
458 e_dialog_text_set(dia,
460 "You cannot do any other system actions<br>"
461 "once a reboot has begun.")
465 e_dialog_text_set(dia,
467 "Until suspend is complete you cannot perform<br>"
468 "any other system actions.")
471 case E_SYS_HIBERNATE:
472 e_dialog_text_set(dia,
474 "You cannot perform an other system actions<br>"
475 "until this is complete.")
479 e_dialog_text_set(dia,
480 _("EEK! This should not happen")
484 e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
485 e_dialog_button_focus_num(dia, 0);
486 e_win_centered_set(dia->win, 1);
491 _e_sys_action_failed(void)
493 /* display dialog that the current action failed */
496 dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_action_failed");
499 e_dialog_title_set(dia, _("Enlightenment is busy with another request"));
500 e_dialog_icon_set(dia, "enlightenment/sys", 64);
501 switch (_e_sys_action_current)
505 e_dialog_text_set(dia,
506 _("Power off failed.")
510 e_dialog_text_set(dia,
515 e_dialog_text_set(dia,
519 case E_SYS_HIBERNATE:
520 e_dialog_text_set(dia,
521 _("Hibernate failed.")
525 e_dialog_text_set(dia,
526 _("EEK! This should not happen")
530 e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
531 e_dialog_button_focus_num(dia, 0);
532 e_win_centered_set(dia->win, 1);
537 _e_sys_action_do(E_Sys_Action a, char *param __UNUSED__)
545 // XXX TODO: check for e_fm_op_registry entries and confirm
546 if (!e_util_immortal_check()) ecore_main_loop_quit();
549 // XXX TODO: check for e_fm_op_registry entries and confirm
550 if (!e_util_immortal_check())
553 ecore_main_loop_quit();
560 // XXX TODO: check for e_fm_op_registry entries and confirm
561 _e_sys_logout_begin(E_SYS_EXIT);
565 /* shutdown -h now */
566 if (e_util_immortal_check()) return 0;
567 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys halt",
571 _e_sys_current_action();
576 _e_sys_exe = ecore_exe_run(buf, NULL);
577 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
578 _("Power off"), "E", "_sys_halt");
579 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/halt");
580 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
582 "<hilight>Please wait.</hilight>"));
583 e_obj_dialog_show(od);
584 e_obj_dialog_icon_set(od, "system-shutdown");
585 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
586 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
588 /* FIXME: display halt status */
592 /* shutdown -r now */
593 if (e_util_immortal_check()) return 0;
594 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys reboot",
598 _e_sys_current_action();
603 _e_sys_exe = ecore_exe_run(buf, NULL);
604 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
605 _("Resetting"), "E", "_sys_reboot");
606 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/reboot");
607 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
609 "<hilight>Please wait.</hilight>"));
610 e_obj_dialog_show(od);
611 e_obj_dialog_icon_set(od, "system-restart");
612 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
613 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
615 /* FIXME: display reboot status */
619 /* /etc/acpi/sleep.sh force */
620 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys suspend",
624 _e_sys_current_action();
629 if (e_config->desklock_on_suspend) e_desklock_show();
631 _e_sys_exe = ecore_exe_run(buf, NULL);
632 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
633 _("Suspending"), "E", "_sys_suspend");
634 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/suspend");
635 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
637 "<hilight>Please wait.</hilight>"));
638 e_obj_dialog_show(od);
639 e_obj_dialog_icon_set(od, "system-suspend");
640 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
641 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
643 /* FIXME: display suspend status */
646 case E_SYS_HIBERNATE:
647 /* /etc/acpi/hibernate.sh force */
648 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys hibernate",
652 _e_sys_current_action();
657 if (e_config->desklock_on_suspend) e_desklock_show();
659 _e_sys_exe = ecore_exe_run(buf, NULL);
660 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
661 _("Hibernating"), "E", "_sys_hibernate");
662 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/hibernate");
663 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
665 "<hilight>Please wait.</hilight>"));
666 e_obj_dialog_show(od);
667 e_obj_dialog_icon_set(od, "system-suspend-hibernate");
668 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
670 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
671 /* FIXME: display hibernate status */
681 _e_sys_dialog_cb_delete(E_Obj_Dialog *od __UNUSED__)
683 /* If we don't NULL out the _e_sys_dialog, then the
684 * ECORE_EXE_EVENT_DEL callback will trigger and segv if the window
685 * is deleted in some other way. */
686 _e_sys_dialog = NULL;