1ef4acc32ee5062eaabea860bba3136cfb315dda
[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_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;
34
35 static const int E_LOGOUT_AUTO_TIME = 60;
36 static const int E_LOGOUT_WAIT_TIME = 15;
37
38 /* externally accessible functions */
39 EINTERN int
40 e_sys_init(void)
41 {
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);
47    return 1;
48 }
49
50 EINTERN int
51 e_sys_shutdown(void)
52 {
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;
60    return 1;
61 }
62
63 EAPI int
64 e_sys_action_possible_get(E_Sys_Action a)
65 {
66    switch (a)
67      {
68       case E_SYS_EXIT:
69       case E_SYS_RESTART:
70       case E_SYS_EXIT_NOW:
71         return 1;
72       case E_SYS_LOGOUT:
73         return 1;
74       case E_SYS_HALT:
75       case E_SYS_HALT_NOW:
76         return _e_sys_can_halt;
77       case E_SYS_REBOOT:
78         return _e_sys_can_reboot;
79       case E_SYS_SUSPEND:
80         return _e_sys_can_suspend;
81       case E_SYS_HIBERNATE:
82         return _e_sys_can_hibernate;
83       default:
84         return 0;
85      }
86    return 0;
87 }
88
89 EAPI int
90 e_sys_action_do(E_Sys_Action a, char *param)
91 {
92    int ret;
93
94    if (_e_sys_action_current != E_SYS_NONE)
95      {
96         _e_sys_current_action();
97         return 0;
98      }
99    switch (a)
100      {
101       case E_SYS_EXIT:
102       case E_SYS_RESTART:
103       case E_SYS_EXIT_NOW:
104       case E_SYS_LOGOUT:
105       case E_SYS_SUSPEND:
106       case E_SYS_HIBERNATE:
107       case E_SYS_HALT_NOW:
108         ret = _e_sys_action_do(a, param);
109         break;
110       case E_SYS_HALT:
111       case E_SYS_REBOOT:
112         if (!e_util_immortal_check()) _e_sys_logout_begin(a);
113         return 1;
114         break;
115       default:
116         return 0;
117      }
118    _e_sys_action_current = a;
119    return ret;
120 }
121
122 static Eina_List *extra_actions = NULL;
123
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),
129                                 const void *data)
130 {
131    E_Sys_Con_Action *sca;
132    
133    sca = E_NEW(E_Sys_Con_Action, 1);
134    if (label)
135      sca->label = eina_stringshare_add(label);
136    if (icon_group)
137      sca->icon_group = eina_stringshare_add(icon_group);
138    if (button_name)
139      sca->button_name = eina_stringshare_add(button_name);
140    sca->func = func;
141    sca->data = data;
142    extra_actions = eina_list_append(extra_actions, sca);
143    return sca;
144 }
145
146 EAPI void
147 e_sys_con_extra_action_unregister(E_Sys_Con_Action *sca)
148 {
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);
153    free(sca);
154 }
155
156 EAPI const Eina_List *
157 e_sys_con_extra_action_list_get(void)
158 {
159    return extra_actions;
160 }
161
162 /* local subsystem functions */
163 static Eina_Bool
164 _e_sys_cb_timer(void *data __UNUSED__)
165 {
166    /* exec out sys helper and ask it to test if we are allowed to do these
167     * things
168     */
169    char buf[4096];
170    
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;
181 }
182
183 static Eina_Bool
184 _e_sys_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
185 {
186    Ecore_Exe_Event_Del *ev;
187
188    ev = event;
189    if ((_e_sys_exe) && (ev->exe == _e_sys_exe))
190      {
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))
196           {
197              if (_e_sys_dialog)
198                {
199                   e_object_del(E_OBJECT(_e_sys_dialog));
200                   _e_sys_dialog = NULL;
201                }
202           }
203         _e_sys_action_current = E_SYS_NONE;
204         _e_sys_exe = NULL;
205         return ECORE_CALLBACK_RENEW;
206      }
207    if ((_e_sys_halt_check_exe) && (ev->exe == _e_sys_halt_check_exe))
208      {
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)
213           {
214              _e_sys_can_halt = 1;
215              _e_sys_halt_check_exe = NULL;
216           }
217      }
218    else if ((_e_sys_reboot_check_exe) && (ev->exe == _e_sys_reboot_check_exe))
219      {
220         e_init_status_set(_("System Check Done"));
221         if (ev->exit_code == 0)
222           {
223              _e_sys_can_reboot = 1;
224              _e_sys_reboot_check_exe = NULL;
225           }
226      }
227    else if ((_e_sys_suspend_check_exe) && (ev->exe == _e_sys_suspend_check_exe))
228      {
229         e_init_status_set(_("System Check Done"));
230         if (ev->exit_code == 0)
231           {
232              _e_sys_can_suspend = 1;
233              _e_sys_suspend_check_exe = NULL;
234           }
235      }
236    else if ((_e_sys_hibernate_check_exe) && (ev->exe == _e_sys_hibernate_check_exe))
237      {
238         e_init_status_set(_("System Check Done"));
239         if (ev->exit_code == 0)
240           {
241              _e_sys_can_hibernate = 1;
242              _e_sys_hibernate_check_exe = NULL;
243           }
244      }
245    return ECORE_CALLBACK_RENEW;
246 }
247
248 static void
249 _e_sys_cb_logout_logout(void *data __UNUSED__, E_Dialog *dia)
250 {
251    if (_e_sys_logout_timer)
252      {
253         ecore_timer_del(_e_sys_logout_timer);
254         _e_sys_logout_timer = NULL;
255      }
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;
260 }
261
262 static void
263 _e_sys_cb_logout_wait(void *data __UNUSED__, E_Dialog *dia)
264 {
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;
270 }
271
272 static void
273 _e_sys_cb_logout_abort(void *data __UNUSED__, E_Dialog *dia)
274 {
275    if (_e_sys_logout_timer)
276      {
277         ecore_timer_del(_e_sys_logout_timer);
278         _e_sys_logout_timer = NULL;
279      }
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;
285    if (_e_sys_dialog)
286      {
287         e_object_del(E_OBJECT(_e_sys_dialog));
288         _e_sys_dialog = NULL;
289      }
290 }
291
292 static void
293 _e_sys_logout_confirm_dialog_update(int remaining)
294 {
295    char txt[PATH_MAX];
296
297    if (!_e_sys_logout_confirm_dialog)
298      {
299         fputs("ERROR: updating logout confirm dialog, but none exists!\n",
300               stderr);
301         return;
302      }
303
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."),
311             remaining);
312
313    e_dialog_text_set(_e_sys_logout_confirm_dialog, txt);
314 }
315
316 static Eina_Bool
317 _e_sys_cb_logout_timer(void *data __UNUSED__)
318 {
319    Eina_List *l;
320    E_Border *bd;
321    int pending = 0;
322
323    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
324      {
325         if (!bd->internal) pending++;
326      }
327    if (pending == 0) goto after;
328    else if (_e_sys_logout_confirm_dialog)
329      {
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.
335          *
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.
340          */
341         if (remaining > 0)
342           {
343              _e_sys_logout_confirm_dialog_update(remaining);
344              return ECORE_CALLBACK_RENEW;
345           }
346         else
347           {
348              _e_sys_cb_logout_logout(NULL, _e_sys_logout_confirm_dialog);
349              return ECORE_CALLBACK_CANCEL;
350           }
351      }
352    else
353      {
354         /* it has taken 15 seconds of waiting and we still have apps that
355          * will not go away
356          */
357         double now = ecore_loop_time_get();
358         if ((now - _e_sys_logout_begin_time) > E_LOGOUT_WAIT_TIME)
359           {
360              E_Dialog *dia;
361
362              dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_logout_slow");
363              if (dia)
364                {
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);
374                   e_dialog_show(dia);
375                   _e_sys_logout_begin_time = now;
376                }
377              return ECORE_CALLBACK_RENEW;
378           }
379      }
380    return ECORE_CALLBACK_RENEW;
381    after:
382    _e_sys_logout_after();
383    _e_sys_logout_timer = NULL;
384    return ECORE_CALLBACK_CANCEL;
385 }
386
387 static void
388 _e_sys_logout_after(void)
389 {
390    if (_e_sys_dialog)
391      {
392         e_object_del(E_OBJECT(_e_sys_dialog));
393         _e_sys_dialog = NULL;
394      }
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;
398 }
399
400 static void
401 _e_sys_logout_begin(E_Sys_Action a_after)
402 {
403    Eina_List *l;
404    E_Border *bd;
405    E_Obj_Dialog *od;
406
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));
417    _e_sys_dialog = od;
418    _e_sys_action_after = a_after;
419    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
420      {
421         e_border_act_close_begin(bd);
422      }
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);
427 }
428
429 static void
430 _e_sys_current_action(void)
431 {
432    /* display dialog that currently an action is in progress */
433    E_Dialog *dia;
434
435    dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_action_busy");
436    if (!dia) return;
437
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)
441      {
442       case E_SYS_LOGOUT:
443         e_dialog_text_set(dia,
444                           _("Logging out.<br>"
445                             "You cannot perform other system actions<br>"
446                             "once a logout has begun.")
447                           );
448         break;
449       case E_SYS_HALT:
450       case E_SYS_HALT_NOW:
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.")
455                           );
456         break;
457       case E_SYS_REBOOT:
458         e_dialog_text_set(dia,
459                           _("Resetting.<br>"
460                             "You cannot do any other system actions<br>"
461                             "once a reboot has begun.")
462                           );
463         break;
464       case E_SYS_SUSPEND:
465         e_dialog_text_set(dia,
466                           _("Suspending.<br>"
467                             "Until suspend is complete you cannot perform<br>"
468                             "any other system actions.")
469                           );
470         break;
471       case E_SYS_HIBERNATE:
472         e_dialog_text_set(dia,
473                           _("Hibernating.<br>"
474                             "You cannot perform an other system actions<br>"
475                             "until this is complete.")
476                           );
477         break;
478       default:
479         e_dialog_text_set(dia,
480                           _("EEK! This should not happen")
481                           );
482         break;
483      }
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);
487    e_dialog_show(dia);
488 }
489
490 static void
491 _e_sys_action_failed(void)
492 {
493    /* display dialog that the current action failed */
494    E_Dialog *dia;
495
496    dia = e_dialog_new(e_container_current_get(e_manager_current_get()), "E", "_sys_error_action_failed");
497    if (!dia) return;
498
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)
502      {
503       case E_SYS_HALT:
504       case E_SYS_HALT_NOW:
505         e_dialog_text_set(dia,
506                           _("Power off failed.")
507                           );
508         break;
509       case E_SYS_REBOOT:
510         e_dialog_text_set(dia,
511                           _("Reset failed.")
512                           );
513         break;
514       case E_SYS_SUSPEND:
515         e_dialog_text_set(dia,
516                           _("Suspend failed.")
517                           );
518         break;
519       case E_SYS_HIBERNATE:
520         e_dialog_text_set(dia,
521                           _("Hibernate failed.")
522                           );
523         break;
524       default:
525         e_dialog_text_set(dia,
526                           _("EEK! This should not happen")
527                           );
528         break;
529      }
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);
533    e_dialog_show(dia);
534 }
535
536 static int
537 _e_sys_action_do(E_Sys_Action a, char *param __UNUSED__)
538 {
539    char buf[PATH_MAX];
540    E_Obj_Dialog *od;
541
542    switch (a)
543      {
544       case E_SYS_EXIT:
545         // XXX TODO: check for e_fm_op_registry entries and confirm
546         if (!e_util_immortal_check()) ecore_main_loop_quit();
547         break;
548       case E_SYS_RESTART:
549         // XXX TODO: check for e_fm_op_registry entries and confirm
550         if (!e_util_immortal_check())
551           {
552              restart = 1;
553              ecore_main_loop_quit();
554           }
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), "%s/enlightenment/utils/enlightenment_sys halt",
568                  e_prefix_lib_get());
569         if (_e_sys_exe)
570           {
571              _e_sys_current_action();
572              return 0;
573           }
574         else
575           {
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",
581                                             _("Power off.<br>"
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);
587              _e_sys_dialog = od;
588              /* FIXME: display halt status */
589           }
590         break;
591       case E_SYS_REBOOT:
592         /* shutdown -r now */
593         if (e_util_immortal_check()) return 0;
594         snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys reboot",
595                  e_prefix_lib_get());
596         if (_e_sys_exe)
597           {
598              _e_sys_current_action();
599              return 0;
600           }
601         else
602           {
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",
608                                             _("Resetting.<br>"
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);
614              _e_sys_dialog = od;
615              /* FIXME: display reboot status */
616           }
617         break;
618       case E_SYS_SUSPEND:
619         /* /etc/acpi/sleep.sh force */
620         snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys suspend",
621                  e_prefix_lib_get());
622         if (_e_sys_exe)
623           {
624              _e_sys_current_action();
625              return 0;
626           }
627         else
628           {
629              if (e_config->desklock_on_suspend) e_desklock_show();
630              
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",
636                                             _("Suspending.<br>"
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);
642              _e_sys_dialog = od;
643              /* FIXME: display suspend status */
644           }
645         break;
646       case E_SYS_HIBERNATE:
647         /* /etc/acpi/hibernate.sh force */
648         snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_sys hibernate",
649                  e_prefix_lib_get());
650         if (_e_sys_exe)
651           {
652              _e_sys_current_action();
653              return 0;
654           }
655         else
656           {
657              if (e_config->desklock_on_suspend) e_desklock_show();
658              
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",
664                                             _("Hibernating.<br>"
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));
669              _e_sys_dialog = od;
670              e_obj_dialog_cb_delete_set(od, _e_sys_dialog_cb_delete);
671              /* FIXME: display hibernate status */
672           }
673         break;
674       default:
675         return 0;
676      }
677    return 1;
678 }
679
680 static void 
681 _e_sys_dialog_cb_delete(E_Obj_Dialog *od __UNUSED__)
682 {
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;
687 }