update for beta release
[framework/uifw/e17.git] / src / bin / e_sys.c
1 #include "e.h"
2
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);
16
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;
26
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;
35
36 static const int E_LOGOUT_AUTO_TIME = 60;
37 static const int E_LOGOUT_WAIT_TIME = 15;
38
39 /* externally accessible functions */
40 EINTERN int
41 e_sys_init(void)
42 {
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);
48    return 1;
49 }
50
51 EINTERN int
52 e_sys_shutdown(void)
53 {
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;
61    return 1;
62 }
63
64 EAPI int
65 e_sys_action_possible_get(E_Sys_Action a)
66 {
67    switch (a)
68      {
69       case E_SYS_EXIT:
70       case E_SYS_RESTART:
71       case E_SYS_EXIT_NOW:
72         return 1;
73       case E_SYS_LOGOUT:
74         return 1;
75       case E_SYS_HALT:
76       case E_SYS_HALT_NOW:
77         return _e_sys_can_halt;
78       case E_SYS_REBOOT:
79         return _e_sys_can_reboot;
80       case E_SYS_SUSPEND:
81         return _e_sys_can_suspend;
82       case E_SYS_HIBERNATE:
83         return _e_sys_can_hibernate;
84       default:
85         return 0;
86      }
87    return 0;
88 }
89
90 EAPI int
91 e_sys_action_do(E_Sys_Action a, char *param)
92 {
93    int ret = 0;
94
95    if (_e_sys_action_current != E_SYS_NONE)
96      {
97         _e_sys_current_action();
98         return 0;
99      }
100    switch (a)
101      {
102       case E_SYS_EXIT:
103       case E_SYS_RESTART:
104       case E_SYS_EXIT_NOW:
105       case E_SYS_LOGOUT:
106       case E_SYS_SUSPEND:
107       case E_SYS_HIBERNATE:
108       case E_SYS_HALT_NOW:
109         ret = _e_sys_action_do(a, param);
110         break;
111       case E_SYS_HALT:
112       case E_SYS_REBOOT:
113         if (!e_util_immortal_check()) _e_sys_logout_begin(a);
114         return 1;
115         break;
116       default:
117         break;
118      }
119
120    if (ret) _e_sys_action_current = a;
121    else _e_sys_action_current = E_SYS_NONE;
122
123    return ret;
124 }
125
126 static Eina_List *extra_actions = NULL;
127
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),
133                                 const void *data)
134 {
135    E_Sys_Con_Action *sca;
136    
137    sca = E_NEW(E_Sys_Con_Action, 1);
138    if (label)
139      sca->label = eina_stringshare_add(label);
140    if (icon_group)
141      sca->icon_group = eina_stringshare_add(icon_group);
142    if (button_name)
143      sca->button_name = eina_stringshare_add(button_name);
144    sca->func = func;
145    sca->data = data;
146    extra_actions = eina_list_append(extra_actions, sca);
147    return sca;
148 }
149
150 EAPI void
151 e_sys_con_extra_action_unregister(E_Sys_Con_Action *sca)
152 {
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);
157    free(sca);
158 }
159
160 EAPI const Eina_List *
161 e_sys_con_extra_action_list_get(void)
162 {
163    return extra_actions;
164 }
165
166 /* local subsystem functions */
167 static Eina_Bool
168 _e_sys_cb_timer(void *data __UNUSED__)
169 {
170    /* exec out sys helper and ask it to test if we are allowed to do these
171     * things
172     */
173    char buf[4096];
174    
175    e_init_status_set(_("Checking System Permissions"));
176    snprintf(buf, sizeof(buf), 
177             "%s/enlightenment/utils/enlightenment_sys -t halt", 
178             e_prefix_lib_get());
179    _e_sys_halt_check_exe = ecore_exe_run(buf, NULL);
180    snprintf(buf, sizeof(buf), 
181             "%s/enlightenment/utils/enlightenment_sys -t reboot", 
182             e_prefix_lib_get());
183    _e_sys_reboot_check_exe = ecore_exe_run(buf, NULL);
184    snprintf(buf, sizeof(buf), 
185             "%s/enlightenment/utils/enlightenment_sys -t suspend", 
186             e_prefix_lib_get());
187    _e_sys_suspend_check_exe = ecore_exe_run(buf, NULL);
188    snprintf(buf, sizeof(buf), 
189             "%s/enlightenment/utils/enlightenment_sys -t hibernate", 
190             e_prefix_lib_get());
191    _e_sys_hibernate_check_exe = ecore_exe_run(buf, NULL);
192    return ECORE_CALLBACK_CANCEL;
193 }
194
195 static Eina_Bool
196 _e_sys_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
197 {
198    Ecore_Exe_Event_Del *ev;
199
200    ev = event;
201    if ((_e_sys_exe) && (ev->exe == _e_sys_exe))
202      {
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))
208           {
209              if (_e_sys_dialog)
210                {
211                   e_object_del(E_OBJECT(_e_sys_dialog));
212                   _e_sys_dialog = NULL;
213                }
214           }
215         _e_sys_action_current = E_SYS_NONE;
216         _e_sys_exe = NULL;
217         return ECORE_CALLBACK_RENEW;
218      }
219    if ((_e_sys_halt_check_exe) && (ev->exe == _e_sys_halt_check_exe))
220      {
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)
225           {
226              _e_sys_can_halt = 1;
227              _e_sys_halt_check_exe = NULL;
228           }
229      }
230    else if ((_e_sys_reboot_check_exe) && (ev->exe == _e_sys_reboot_check_exe))
231      {
232         e_init_status_set(_("System Check Done"));
233         if (ev->exit_code == 0)
234           {
235              _e_sys_can_reboot = 1;
236              _e_sys_reboot_check_exe = NULL;
237           }
238      }
239    else if ((_e_sys_suspend_check_exe) && (ev->exe == _e_sys_suspend_check_exe))
240      {
241         e_init_status_set(_("System Check Done"));
242         if (ev->exit_code == 0)
243           {
244              _e_sys_can_suspend = 1;
245              _e_sys_suspend_check_exe = NULL;
246           }
247      }
248    else if ((_e_sys_hibernate_check_exe) && (ev->exe == _e_sys_hibernate_check_exe))
249      {
250         e_init_status_set(_("System Check Done"));
251         if (ev->exit_code == 0)
252           {
253              _e_sys_can_hibernate = 1;
254              _e_sys_hibernate_check_exe = NULL;
255           }
256      }
257    return ECORE_CALLBACK_RENEW;
258 }
259
260 static void
261 _e_sys_cb_logout_logout(void *data __UNUSED__, E_Dialog *dia)
262 {
263    if (_e_sys_logout_timer)
264      {
265         ecore_timer_del(_e_sys_logout_timer);
266         _e_sys_logout_timer = NULL;
267      }
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;
272 }
273
274 static void
275 _e_sys_cb_logout_wait(void *data __UNUSED__, E_Dialog *dia)
276 {
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;
282 }
283
284 static void
285 _e_sys_cb_logout_abort(void *data __UNUSED__, E_Dialog *dia)
286 {
287    if (_e_sys_logout_timer)
288      {
289         ecore_timer_del(_e_sys_logout_timer);
290         _e_sys_logout_timer = NULL;
291      }
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;
297    if (_e_sys_dialog)
298      {
299         e_object_del(E_OBJECT(_e_sys_dialog));
300         _e_sys_dialog = NULL;
301      }
302 }
303
304 static void
305 _e_sys_logout_confirm_dialog_update(int remaining)
306 {
307    char txt[PATH_MAX];
308
309    if (!_e_sys_logout_confirm_dialog)
310      {
311         fputs("ERROR: updating logout confirm dialog, but none exists!\n",
312               stderr);
313         return;
314      }
315
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);
323
324    e_dialog_text_set(_e_sys_logout_confirm_dialog, txt);
325 }
326
327 static Eina_Bool
328 _e_sys_cb_logout_timer(void *data __UNUSED__)
329 {
330    Eina_List *l;
331    E_Border *bd;
332    int pending = 0;
333
334    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
335      {
336         if (!bd->internal) pending++;
337      }
338    if (pending == 0) goto after;
339    else if (_e_sys_logout_confirm_dialog)
340      {
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.
346          *
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.
351          */
352         if (remaining > 0)
353           {
354              _e_sys_logout_confirm_dialog_update(remaining);
355              return ECORE_CALLBACK_RENEW;
356           }
357         else
358           {
359              _e_sys_cb_logout_logout(NULL, _e_sys_logout_confirm_dialog);
360              return ECORE_CALLBACK_CANCEL;
361           }
362      }
363    else
364      {
365         /* it has taken 15 seconds of waiting and we still have apps that
366          * will not go away
367          */
368         double now = ecore_loop_time_get();
369         if ((now - _e_sys_logout_begin_time) > E_LOGOUT_WAIT_TIME)
370           {
371              E_Dialog *dia;
372
373              dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_logout_slow");
374              if (dia)
375                {
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);
388                   e_dialog_show(dia);
389                   _e_sys_logout_begin_time = now;
390                }
391              return ECORE_CALLBACK_RENEW;
392           }
393      }
394    return ECORE_CALLBACK_RENEW;
395    after:
396    _e_sys_logout_after();
397    _e_sys_logout_timer = NULL;
398    return ECORE_CALLBACK_CANCEL;
399 }
400
401 static void
402 _e_sys_logout_after(void)
403 {
404    if (_e_sys_dialog)
405      {
406         e_object_del(E_OBJECT(_e_sys_dialog));
407         _e_sys_dialog = NULL;
408      }
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;
412 }
413
414 static void
415 _e_sys_logout_begin(E_Sys_Action a_after)
416 {
417    Eina_List *l;
418    E_Border *bd;
419    E_Obj_Dialog *od;
420
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));
431    _e_sys_dialog = od;
432    _e_sys_action_after = a_after;
433    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
434      {
435         e_border_act_close_begin(bd);
436      }
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);
441 }
442
443 static void
444 _e_sys_current_action(void)
445 {
446    /* display dialog that currently an action is in progress */
447    E_Dialog *dia;
448
449    dia = e_dialog_new(e_container_current_get(e_manager_current_get()), 
450                       "E", "_sys_error_action_busy");
451    if (!dia) return;
452
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)
456      {
457       case E_SYS_LOGOUT:
458         e_dialog_text_set(dia, _("Logging out.<br>"
459                                  "You cannot perform other system actions<br>"
460                                  "once a logout has begun."));
461         break;
462       case E_SYS_HALT:
463       case E_SYS_HALT_NOW:
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."));
467         break;
468       case E_SYS_REBOOT:
469         e_dialog_text_set(dia, _("Resetting.<br>"
470                                  "You cannot do any other system actions<br>"
471                                  "once a reboot has begun."));
472         break;
473       case E_SYS_SUSPEND:
474         e_dialog_text_set(dia, _("Suspending.<br>"
475                                  "Until suspend is complete you cannot perform<br>"
476                                  "any other system actions."));
477         break;
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."));
482         break;
483       default:
484         e_dialog_text_set(dia, _("EEK! This should not happen"));
485         break;
486      }
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);
490    e_dialog_show(dia);
491 }
492
493 static void
494 _e_sys_action_failed(void)
495 {
496    /* display dialog that the current action failed */
497    E_Dialog *dia;
498
499    dia = e_dialog_new(e_container_current_get(e_manager_current_get()), 
500                       "E", "_sys_error_action_failed");
501    if (!dia) return;
502
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)
506      {
507       case E_SYS_HALT:
508       case E_SYS_HALT_NOW:
509         e_dialog_text_set(dia, _("Power off failed."));
510         break;
511       case E_SYS_REBOOT:
512         e_dialog_text_set(dia, _("Reset failed."));
513         break;
514       case E_SYS_SUSPEND:
515         e_dialog_text_set(dia, _("Suspend failed."));
516         break;
517       case E_SYS_HIBERNATE:
518         e_dialog_text_set(dia, _("Hibernate failed."));
519         break;
520       default:
521         e_dialog_text_set(dia, _("EEK! This should not happen"));
522         break;
523      }
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);
527    e_dialog_show(dia);
528 }
529
530 static int
531 _e_sys_action_do(E_Sys_Action a, char *param __UNUSED__)
532 {
533    char buf[PATH_MAX];
534    E_Obj_Dialog *od;
535
536    switch (a)
537      {
538       case E_SYS_EXIT:
539         // XXX TODO: check for e_fm_op_registry entries and confirm
540         if (!e_util_immortal_check()) 
541           ecore_main_loop_quit();
542         else 
543           return 0;
544         break;
545       case E_SYS_RESTART:
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())
549           {
550              restart = 1;
551              ecore_main_loop_quit();
552           }
553 //        else
554 //          return 0;
555         break;
556       case E_SYS_EXIT_NOW:
557         exit(0);
558         break;
559       case E_SYS_LOGOUT:
560         // XXX TODO: check for e_fm_op_registry entries and confirm
561         _e_sys_logout_begin(E_SYS_EXIT);
562         break;
563       case E_SYS_HALT:
564       case E_SYS_HALT_NOW:
565         /* shutdown -h now */
566         if (e_util_immortal_check()) return 0;
567         snprintf(buf, sizeof(buf), 
568                  "%s/enlightenment/utils/enlightenment_sys halt", 
569                  e_prefix_lib_get());
570         if (_e_sys_exe)
571           {
572              if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
573                 _e_sys_current_action();
574              return 0;
575           }
576         else
577           {
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",
584                                             _("Power off.<br>"
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);
590              _e_sys_dialog = od;
591              /* FIXME: display halt status */
592           }
593         break;
594       case E_SYS_REBOOT:
595         /* shutdown -r now */
596         if (e_util_immortal_check()) return 0;
597         snprintf(buf, sizeof(buf), 
598                  "%s/enlightenment/utils/enlightenment_sys reboot",
599                  e_prefix_lib_get());
600         if (_e_sys_exe)
601           {
602              if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
603                 _e_sys_current_action();
604              return 0;
605           }
606         else
607           {
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",
614                                             _("Resetting.<br>"
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);
620              _e_sys_dialog = od;
621              /* FIXME: display reboot status */
622           }
623         break;
624       case E_SYS_SUSPEND:
625         /* /etc/acpi/sleep.sh force */
626         snprintf(buf, sizeof(buf), 
627                  "%s/enlightenment/utils/enlightenment_sys suspend",
628                  e_prefix_lib_get());
629         if (_e_sys_exe)
630           {
631              if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
632                 _e_sys_current_action();
633              return 0;
634           }
635         else
636           {
637              if (e_config->desklock_on_suspend) e_desklock_show();
638              
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",
645                                             _("Suspending.<br>"
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);
651              _e_sys_dialog = od;
652              /* FIXME: display suspend status */
653           }
654         break;
655       case E_SYS_HIBERNATE:
656         /* /etc/acpi/hibernate.sh force */
657         snprintf(buf, sizeof(buf), 
658                  "%s/enlightenment/utils/enlightenment_sys hibernate",
659                  e_prefix_lib_get());
660         if (_e_sys_exe)
661           {
662              if ((ecore_time_get() - _e_sys_begin_time) > 2.0)
663                 _e_sys_current_action();
664              return 0;
665           }
666         else
667           {
668              if (e_config->desklock_on_suspend) e_desklock_show();
669              
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",
676                                             _("Hibernating.<br>"
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));
681              _e_sys_dialog = od;
682              e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
683              /* FIXME: display hibernate status */
684           }
685         break;
686       default:
687         return 0;
688      }
689    return 1;
690 }
691
692 static void 
693 _e_sys_dialog_cb_delete(E_Obj_Dialog *od __UNUSED__)
694 {
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;
699 }