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_begin_time = 0.0;
31 static double _e_sys_logout_begin_time = 0.0;
32 static Ecore_Timer *_e_sys_logout_timer = NULL;
33 static E_Obj_Dialog *_e_sys_dialog = NULL;
34 static E_Dialog *_e_sys_logout_confirm_dialog = NULL;
36 static const int E_LOGOUT_AUTO_TIME = 60;
37 static const int E_LOGOUT_WAIT_TIME = 15;
39 /* externally accessible functions */
43 /* this is not optimal - but it does work cleanly */
44 _e_sys_exe_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
45 _e_sys_cb_exit, NULL);
46 /* delay this for 1.0 seconds while the rest of e starts up */
47 ecore_timer_add(1.0, _e_sys_cb_timer, NULL);
54 if (_e_sys_exe_exit_handler)
55 ecore_event_handler_del(_e_sys_exe_exit_handler);
56 _e_sys_exe_exit_handler = NULL;
57 _e_sys_halt_check_exe = NULL;
58 _e_sys_reboot_check_exe = NULL;
59 _e_sys_suspend_check_exe = NULL;
60 _e_sys_hibernate_check_exe = NULL;
65 e_sys_action_possible_get(E_Sys_Action a)
77 return _e_sys_can_halt;
79 return _e_sys_can_reboot;
81 return _e_sys_can_suspend;
83 return _e_sys_can_hibernate;
91 e_sys_action_do(E_Sys_Action a, char *param)
95 if (_e_sys_action_current != E_SYS_NONE)
97 _e_sys_current_action();
107 case E_SYS_HIBERNATE:
109 ret = _e_sys_action_do(a, param);
113 if (!e_util_immortal_check()) _e_sys_logout_begin(a);
120 if (ret) _e_sys_action_current = a;
121 else _e_sys_action_current = E_SYS_NONE;
126 static Eina_List *extra_actions = NULL;
128 EAPI E_Sys_Con_Action *
129 e_sys_con_extra_action_register(const char *label,
130 const char *icon_group,
131 const char *button_name,
132 void (*func) (void *data),
135 E_Sys_Con_Action *sca;
137 sca = E_NEW(E_Sys_Con_Action, 1);
139 sca->label = eina_stringshare_add(label);
141 sca->icon_group = eina_stringshare_add(icon_group);
143 sca->button_name = eina_stringshare_add(button_name);
146 extra_actions = eina_list_append(extra_actions, sca);
151 e_sys_con_extra_action_unregister(E_Sys_Con_Action *sca)
153 extra_actions = eina_list_remove(extra_actions, sca);
154 if (sca->label) eina_stringshare_del(sca->label);
155 if (sca->icon_group) eina_stringshare_del(sca->icon_group);
156 if (sca->button_name) eina_stringshare_del(sca->button_name);
160 EAPI const Eina_List *
161 e_sys_con_extra_action_list_get(void)
163 return extra_actions;
166 /* local subsystem functions */
168 _e_sys_cb_timer(void *data __UNUSED__)
170 /* exec out sys helper and ask it to test if we are allowed to do these
175 e_init_status_set(_("Checking System Permissions"));
176 snprintf(buf, sizeof(buf),
177 "%s/enlightenment/utils/enlightenment_sys -t halt",
179 _e_sys_halt_check_exe = ecore_exe_run(buf, NULL);
180 snprintf(buf, sizeof(buf),
181 "%s/enlightenment/utils/enlightenment_sys -t reboot",
183 _e_sys_reboot_check_exe = ecore_exe_run(buf, NULL);
184 snprintf(buf, sizeof(buf),
185 "%s/enlightenment/utils/enlightenment_sys -t suspend",
187 _e_sys_suspend_check_exe = ecore_exe_run(buf, NULL);
188 snprintf(buf, sizeof(buf),
189 "%s/enlightenment/utils/enlightenment_sys -t hibernate",
191 _e_sys_hibernate_check_exe = ecore_exe_run(buf, NULL);
192 return ECORE_CALLBACK_CANCEL;
196 _e_sys_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
198 Ecore_Exe_Event_Del *ev;
201 if ((_e_sys_exe) && (ev->exe == _e_sys_exe))
203 if (ev->exit_code != 0) _e_sys_action_failed();
204 if (((_e_sys_action_current != E_SYS_HALT) &&
205 (_e_sys_action_current != E_SYS_HALT_NOW) &&
206 (_e_sys_action_current != E_SYS_REBOOT)) ||
207 (ev->exit_code != 0))
211 e_object_del(E_OBJECT(_e_sys_dialog));
212 _e_sys_dialog = NULL;
215 _e_sys_action_current = E_SYS_NONE;
217 return ECORE_CALLBACK_RENEW;
219 if ((_e_sys_halt_check_exe) && (ev->exe == _e_sys_halt_check_exe))
221 e_init_status_set(_("System Check Done"));
222 /* exit_code: 0 == OK, 5 == suid root removed, 7 == group id error
223 * 10 == permission denied, 20 == action undefined */
224 if (ev->exit_code == 0)
227 _e_sys_halt_check_exe = NULL;
230 else if ((_e_sys_reboot_check_exe) && (ev->exe == _e_sys_reboot_check_exe))
232 e_init_status_set(_("System Check Done"));
233 if (ev->exit_code == 0)
235 _e_sys_can_reboot = 1;
236 _e_sys_reboot_check_exe = NULL;
239 else if ((_e_sys_suspend_check_exe) && (ev->exe == _e_sys_suspend_check_exe))
241 e_init_status_set(_("System Check Done"));
242 if (ev->exit_code == 0)
244 _e_sys_can_suspend = 1;
245 _e_sys_suspend_check_exe = NULL;
248 else if ((_e_sys_hibernate_check_exe) && (ev->exe == _e_sys_hibernate_check_exe))
250 e_init_status_set(_("System Check Done"));
251 if (ev->exit_code == 0)
253 _e_sys_can_hibernate = 1;
254 _e_sys_hibernate_check_exe = NULL;
257 return ECORE_CALLBACK_RENEW;
261 _e_sys_cb_logout_logout(void *data __UNUSED__, E_Dialog *dia)
263 if (_e_sys_logout_timer)
265 ecore_timer_del(_e_sys_logout_timer);
266 _e_sys_logout_timer = NULL;
268 _e_sys_logout_begin_time = 0.0;
269 _e_sys_logout_after();
270 e_object_del(E_OBJECT(dia));
271 _e_sys_logout_confirm_dialog = NULL;
275 _e_sys_cb_logout_wait(void *data __UNUSED__, E_Dialog *dia)
277 if (_e_sys_logout_timer) ecore_timer_del(_e_sys_logout_timer);
278 _e_sys_logout_timer = ecore_timer_add(0.5, _e_sys_cb_logout_timer, NULL);
279 _e_sys_logout_begin_time = ecore_time_get();
280 e_object_del(E_OBJECT(dia));
281 _e_sys_logout_confirm_dialog = NULL;
285 _e_sys_cb_logout_abort(void *data __UNUSED__, E_Dialog *dia)
287 if (_e_sys_logout_timer)
289 ecore_timer_del(_e_sys_logout_timer);
290 _e_sys_logout_timer = NULL;
292 _e_sys_logout_begin_time = 0.0;
293 e_object_del(E_OBJECT(dia));
294 _e_sys_logout_confirm_dialog = NULL;
295 _e_sys_action_current = E_SYS_NONE;
296 _e_sys_action_after = E_SYS_NONE;
299 e_object_del(E_OBJECT(_e_sys_dialog));
300 _e_sys_dialog = NULL;
305 _e_sys_logout_confirm_dialog_update(int remaining)
309 if (!_e_sys_logout_confirm_dialog)
311 fputs("ERROR: updating logout confirm dialog, but none exists!\n",
316 snprintf(txt, sizeof(txt),
317 _("Logout is taking too long.<br>"
318 "Some applications refuse to close.<br>"
319 "Do you want to finish the logout<br>"
320 "anyway without closing these<br>"
321 "applications first?<br><br>"
322 "Auto logout in %d seconds."), remaining);
324 e_dialog_text_set(_e_sys_logout_confirm_dialog, txt);
328 _e_sys_cb_logout_timer(void *data __UNUSED__)
334 EINA_LIST_FOREACH(e_border_client_list(), l, bd)
336 if (!bd->internal) pending++;
338 if (pending == 0) goto after;
339 else if (_e_sys_logout_confirm_dialog)
341 int remaining = E_LOGOUT_AUTO_TIME -
342 round(ecore_loop_time_get() - _e_sys_logout_begin_time);
343 /* it has taken 60 (E_LOGOUT_AUTO_TIME) seconds of waiting the
344 * confirm dialog and we still have apps that will not go
345 * away. Do the action as user may be far away or forgot it.
347 * NOTE: this is the behavior for many operating systems and I
348 * guess the reason is people that hit "shutdown" and
349 * put their laptops in their backpacks in the hope
350 * everything will be turned off properly.
354 _e_sys_logout_confirm_dialog_update(remaining);
355 return ECORE_CALLBACK_RENEW;
359 _e_sys_cb_logout_logout(NULL, _e_sys_logout_confirm_dialog);
360 return ECORE_CALLBACK_CANCEL;
365 /* it has taken 15 seconds of waiting and we still have apps that
368 double now = ecore_loop_time_get();
369 if ((now - _e_sys_logout_begin_time) > E_LOGOUT_WAIT_TIME)
373 dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_logout_slow");
376 _e_sys_logout_confirm_dialog = dia;
377 e_dialog_title_set(dia, _("Logout problems"));
378 e_dialog_icon_set(dia, "system-log-out", 64);
379 e_dialog_button_add(dia, _("Logout now"), NULL,
380 _e_sys_cb_logout_logout, NULL);
381 e_dialog_button_add(dia, _("Wait longer"), NULL,
382 _e_sys_cb_logout_wait, NULL);
383 e_dialog_button_add(dia, _("Cancel Logout"), NULL,
384 _e_sys_cb_logout_abort, NULL);
385 e_dialog_button_focus_num(dia, 1);
386 _e_sys_logout_confirm_dialog_update(E_LOGOUT_AUTO_TIME);
387 e_win_centered_set(dia->win, 1);
389 _e_sys_logout_begin_time = now;
391 return ECORE_CALLBACK_RENEW;
394 return ECORE_CALLBACK_RENEW;
396 _e_sys_logout_after();
397 _e_sys_logout_timer = NULL;
398 return ECORE_CALLBACK_CANCEL;
402 _e_sys_logout_after(void)
406 e_object_del(E_OBJECT(_e_sys_dialog));
407 _e_sys_dialog = NULL;
409 _e_sys_action_current = _e_sys_action_after;
410 _e_sys_action_do(_e_sys_action_after, NULL);
411 _e_sys_action_after = E_SYS_NONE;
415 _e_sys_logout_begin(E_Sys_Action a_after)
421 /* start logout - at end do the a_after action */
422 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
423 _("Logout in progress"), "E", "_sys_logout");
424 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/logout");
425 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
426 _("Logout in progress.<br>"
427 "<hilight>Please wait.</hilight>"));
428 e_obj_dialog_show(od);
429 e_obj_dialog_icon_set(od, "system-log-out");
430 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
432 _e_sys_action_after = a_after;
433 EINA_LIST_FOREACH(e_border_client_list(), l, bd)
435 e_border_act_close_begin(bd);
437 /* and poll to see if all pending windows are gone yet every 0.5 sec */
438 _e_sys_logout_begin_time = ecore_time_get();
439 if (_e_sys_logout_timer) ecore_timer_del(_e_sys_logout_timer);
440 _e_sys_logout_timer = ecore_timer_add(0.5, _e_sys_cb_logout_timer, NULL);
444 _e_sys_current_action(void)
446 /* display dialog that currently an action is in progress */
449 dia = e_dialog_new(e_container_current_get(e_manager_current_get()),
450 "E", "_sys_error_action_busy");
453 e_dialog_title_set(dia, _("Enlightenment is busy with another request"));
454 e_dialog_icon_set(dia, "enlightenment/sys", 64);
455 switch (_e_sys_action_current)
458 e_dialog_text_set(dia, _("Logging out.<br>"
459 "You cannot perform other system actions<br>"
460 "once a logout has begun."));
464 e_dialog_text_set(dia, _("Powering off.<br>"
465 "You cannot do any other system actions<br>"
466 "once a shutdown has been started."));
469 e_dialog_text_set(dia, _("Resetting.<br>"
470 "You cannot do any other system actions<br>"
471 "once a reboot has begun."));
474 e_dialog_text_set(dia, _("Suspending.<br>"
475 "Until suspend is complete you cannot perform<br>"
476 "any other system actions."));
478 case E_SYS_HIBERNATE:
479 e_dialog_text_set(dia, _("Hibernating.<br>"
480 "You cannot perform any other system actions<br>"
481 "until this is complete."));
484 e_dialog_text_set(dia, _("EEK! This should not happen"));
487 e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
488 e_dialog_button_focus_num(dia, 0);
489 e_win_centered_set(dia->win, 1);
494 _e_sys_action_failed(void)
496 /* display dialog that the current action failed */
499 dia = e_dialog_new(e_container_current_get(e_manager_current_get()),
500 "E", "_sys_error_action_failed");
503 e_dialog_title_set(dia, _("Enlightenment is busy with another request"));
504 e_dialog_icon_set(dia, "enlightenment/sys", 64);
505 switch (_e_sys_action_current)
509 e_dialog_text_set(dia, _("Power off failed."));
512 e_dialog_text_set(dia, _("Reset failed."));
515 e_dialog_text_set(dia, _("Suspend failed."));
517 case E_SYS_HIBERNATE:
518 e_dialog_text_set(dia, _("Hibernate failed."));
521 e_dialog_text_set(dia, _("EEK! This should not happen"));
524 e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
525 e_dialog_button_focus_num(dia, 0);
526 e_win_centered_set(dia->win, 1);
531 _e_sys_action_do(E_Sys_Action a, char *param __UNUSED__)
539 // XXX TODO: check for e_fm_op_registry entries and confirm
540 if (!e_util_immortal_check())
541 ecore_main_loop_quit();
546 // XXX TODO: check for e_fm_op_registry entries and confirm
547 // FIXME: we dont share out immortal info to restarted e. :(
548 // if (!e_util_immortal_check())
551 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),
568 "%s/enlightenment/utils/enlightenment_sys halt",
572 if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
573 _e_sys_current_action();
578 _e_sys_begin_time = ecore_time_get();
579 _e_sys_exe = ecore_exe_run(buf, NULL);
580 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
581 _("Power off"), "E", "_sys_halt");
582 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/halt");
583 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
585 "<hilight>Please wait.</hilight>"));
586 e_obj_dialog_show(od);
587 e_obj_dialog_icon_set(od, "system-shutdown");
588 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
589 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
591 /* FIXME: display halt status */
595 /* shutdown -r now */
596 if (e_util_immortal_check()) return 0;
597 snprintf(buf, sizeof(buf),
598 "%s/enlightenment/utils/enlightenment_sys reboot",
602 if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
603 _e_sys_current_action();
608 _e_sys_begin_time = ecore_time_get();
609 _e_sys_exe = ecore_exe_run(buf, NULL);
610 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
611 _("Resetting"), "E", "_sys_reboot");
612 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/reboot");
613 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
615 "<hilight>Please wait.</hilight>"));
616 e_obj_dialog_show(od);
617 e_obj_dialog_icon_set(od, "system-restart");
618 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
619 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
621 /* FIXME: display reboot status */
625 /* /etc/acpi/sleep.sh force */
626 snprintf(buf, sizeof(buf),
627 "%s/enlightenment/utils/enlightenment_sys suspend",
631 if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
632 _e_sys_current_action();
637 if (e_config->desklock_on_suspend) e_desklock_show();
639 _e_sys_begin_time = ecore_time_get();
640 _e_sys_exe = ecore_exe_run(buf, NULL);
641 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
642 _("Suspending"), "E", "_sys_suspend");
643 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/suspend");
644 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
646 "<hilight>Please wait.</hilight>"));
647 e_obj_dialog_show(od);
648 e_obj_dialog_icon_set(od, "system-suspend");
649 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
650 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
652 /* FIXME: display suspend status */
655 case E_SYS_HIBERNATE:
656 /* /etc/acpi/hibernate.sh force */
657 snprintf(buf, sizeof(buf),
658 "%s/enlightenment/utils/enlightenment_sys hibernate",
662 if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
663 _e_sys_current_action();
668 if (e_config->desklock_on_suspend) e_desklock_show();
670 _e_sys_begin_time = ecore_time_get();
671 _e_sys_exe = ecore_exe_run(buf, NULL);
672 od = e_obj_dialog_new(e_container_current_get(e_manager_current_get()),
673 _("Hibernating"), "E", "_sys_hibernate");
674 e_obj_dialog_obj_theme_set(od, "base/theme/sys", "e/sys/hibernate");
675 e_obj_dialog_obj_part_text_set(od, "e.textblock.message",
677 "<hilight>Please wait.</hilight>"));
678 e_obj_dialog_show(od);
679 e_obj_dialog_icon_set(od, "system-suspend-hibernate");
680 if (_e_sys_dialog) e_object_del(E_OBJECT(_e_sys_dialog));
682 e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
683 /* FIXME: display hibernate status */
693 _e_sys_dialog_cb_delete(E_Obj_Dialog *od __UNUSED__)
695 /* If we don't NULL out the _e_sys_dialog, then the
696 * ECORE_EXE_EVENT_DEL callback will trigger and segv if the window
697 * is deleted in some other way. */
698 _e_sys_dialog = NULL;