update for beta release
[framework/uifw/e17.git] / src / modules / syscon / e_syscon.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 /* local subsystem functions */
5 static Eina_Bool _cb_key_down(void *data, int type, void *event);
6 static Eina_Bool _cb_mouse_down(void *data, int type, void *event);
7 static Eina_Bool _cb_mouse_up(void *data, int type, void *event);
8 static Eina_Bool _cb_mouse_move(void *data, int type, void *event);
9 static Eina_Bool _cb_mouse_wheel(void *data, int type, void *event);
10 static void _cb_signal_close(void *data, Evas_Object *obj, const char *emission, const char *source);
11 static void _cb_signal_syscon(void *data, Evas_Object *obj, const char *emission, const char *source);
12 static void _cb_signal_action(void *data, Evas_Object *obj, const char *emission, const char *source);
13 static void _cb_signal_action_extra(void *data, Evas_Object *obj, const char *emission, const char *source);
14 static Eina_Bool _cb_timeout_defaction(void *data);
15
16 /* local subsystem globals */
17 static E_Popup *popup = NULL;
18 static Ecore_X_Window input_window = 0;
19 static const char *do_defact = NULL;
20 static Eina_List *handlers = NULL;
21 static Evas_Object *o_bg = NULL;
22 static Evas_Object *o_flow_main = NULL;
23 static Evas_Object *o_flow_secondary = NULL;
24 static Evas_Object *o_flow_extra = NULL;
25 static int inevas = 0;
26 static Ecore_Timer *deftimer = NULL;
27 static double show_time = 0.0;
28 static int act_count = 0;
29
30 /* externally accessible functions */
31 int
32 e_syscon_init(void)
33 {
34    return 1;
35 }
36
37 int
38 e_syscon_shutdown(void)
39 {
40    e_syscon_hide();
41    return 1;
42 }
43
44 int
45 e_syscon_show(E_Zone *zone, const char *defact)
46 {
47    Evas_Object *o, *o2;
48    Evas_Coord mw, mh;
49    int x, y, w, h, zx, zy, zw, zh;
50    int iw, ih;
51    Eina_List *l;
52    double t;
53
54    t = ecore_loop_time_get();
55    if (popup)
56      {
57         if ((t - show_time) > 0.5)
58           {
59              for (l = e_config->syscon.actions; l; l = l->next)
60                {
61                   E_Config_Syscon_Action *sca;
62                   E_Action *a;
63                   
64                   if (!(sca = l->data)) continue;
65                   if (!sca->action) continue;
66                   a = e_action_find(sca->action);
67                   if (!a) continue;
68                   if (sca->is_main == 2)
69                     {
70                        a->func.go(NULL, sca->params);
71                        e_syscon_hide();
72                        break;
73                     }
74                }
75           }
76         return 0;
77      }
78
79    input_window = ecore_x_window_input_new(zone->container->win, zone->x,
80                                            zone->y, zone->w, zone->h);
81    ecore_x_window_show(input_window);
82    if (!e_grabinput_get(input_window, 1, input_window))
83      {
84         ecore_x_window_free(input_window);
85         input_window = 0;
86         return 0;
87      }
88
89    popup = e_popup_new(zone, 0, 0, 1, 1);
90    if (!popup)
91      {
92         e_grabinput_release(input_window, input_window);
93         ecore_x_window_free(input_window);
94         input_window = 0;
95         return 0;
96      }
97    evas_event_freeze(popup->evas);
98    e_popup_layer_set(popup, 500);
99
100    handlers = eina_list_append
101      (handlers, ecore_event_handler_add
102       (ECORE_EVENT_KEY_DOWN, _cb_key_down, NULL));
103    handlers = eina_list_append
104      (handlers, ecore_event_handler_add
105       (ECORE_EVENT_MOUSE_BUTTON_DOWN, _cb_mouse_down, NULL));
106    handlers = eina_list_append
107      (handlers, ecore_event_handler_add
108       (ECORE_EVENT_MOUSE_BUTTON_UP, _cb_mouse_up, NULL));
109    handlers = eina_list_append
110      (handlers, ecore_event_handler_add
111       (ECORE_EVENT_MOUSE_MOVE, _cb_mouse_move, NULL));
112    handlers = eina_list_append
113      (handlers, ecore_event_handler_add
114       (ECORE_EVENT_MOUSE_WHEEL, _cb_mouse_wheel, NULL));
115
116    o = edje_object_add(popup->evas);
117    o_bg = o;
118    e_theme_edje_object_set(o, "base/theme/syscon",
119                            "e/widgets/syscon/main");
120    edje_object_part_text_set(o, "e.text.label", _("Cancel"));
121    edje_object_signal_callback_add(o, "e,action,close", "", 
122                                    _cb_signal_close, NULL);
123    edje_object_signal_callback_add(o, "e,action,syscon", "*", 
124                                    _cb_signal_syscon, NULL);
125
126    act_count = 0;
127    show_time = t;
128    
129    // main (default):
130    //  halt | suspend | desk_lock
131    // secondary (default):
132    //  reboot | hibernate | logout
133    // extra (example for illume):
134    //  home | close | kill
135
136
137    o = e_flowlayout_add(popup->evas);
138    o_flow_main = o;
139    e_flowlayout_orientation_set(o, 1);
140    e_flowlayout_flowdirection_set(o, 1, 1);
141    e_flowlayout_homogenous_set(o, 1);
142
143    o = e_flowlayout_add(popup->evas);
144    o_flow_secondary = o;
145    e_flowlayout_orientation_set(o, 1);
146    e_flowlayout_flowdirection_set(o, 1, 1);
147    e_flowlayout_homogenous_set(o, 1);
148
149    o = e_flowlayout_add(popup->evas);
150    o_flow_extra = o;
151    e_flowlayout_orientation_set(o, 1);
152    e_flowlayout_flowdirection_set(o, 1, 1);
153    e_flowlayout_homogenous_set(o, 1);
154
155    for (l = e_config->syscon.actions; l; l = l->next)
156      {
157         E_Config_Syscon_Action *sca;
158         char buf[1024];
159         E_Action *a;
160         int disabled;
161
162         if (!(sca = l->data)) continue;
163         if (!sca->action) continue;
164         a = e_action_find(sca->action);
165         if (!a) continue;
166         disabled = 0;
167         if ((!strcmp(sca->action, "logout")) &&
168             (!e_sys_action_possible_get(E_SYS_LOGOUT))) disabled = 1;
169         else if ((!strcmp(sca->action, "halt")) &&
170             (!e_sys_action_possible_get(E_SYS_HALT))) disabled = 1;
171         else if ((!strcmp(sca->action, "halt_now")) &&
172             (!e_sys_action_possible_get(E_SYS_HALT_NOW))) disabled = 1;
173         else if ((!strcmp(sca->action, "reboot")) &&
174             (!e_sys_action_possible_get(E_SYS_REBOOT))) disabled = 1;
175         else if ((!strcmp(sca->action, "suspend")) &&
176             (!e_sys_action_possible_get(E_SYS_SUSPEND))) disabled = 1;
177         else if ((!strcmp(sca->action, "hibernate")) &&
178             (!e_sys_action_possible_get(E_SYS_HIBERNATE))) disabled = 1;
179         o = edje_object_add(popup->evas);
180         edje_object_signal_callback_add(o, "e,action,click", "", 
181                                         _cb_signal_action, sca);
182         if (sca->button)
183           {
184              snprintf(buf, sizeof(buf), "e/widgets/syscon/item/%s",
185                       sca->button);
186              e_theme_edje_object_set(o, "base/theme/widgets", buf);
187           }
188         else
189           e_theme_edje_object_set(o, "base/theme/widgets",
190                                   "e/widgets/syscon/item/button");
191         edje_object_part_text_set(o, "e.text.label", 
192                                   _(e_action_predef_label_get(sca->action, sca->params)));
193         if (sca->icon)
194           {
195              o2 = e_icon_add(popup->evas);
196              e_util_icon_theme_set(o2, sca->icon);
197              edje_object_part_swallow(o, "e.swallow.icon", o2);
198              evas_object_show(o2);
199              if (disabled)
200                edje_object_signal_emit(o2, "e,state,disabled", "e");
201           }
202         if (disabled)
203           edje_object_signal_emit(o, "e,state,disabled", "e");
204         if (sca->is_main)
205           {
206              e_flowlayout_pack_end(o_flow_main, o);
207              iw = ih = e_config->syscon.main.icon_size * e_scale;
208           }
209         else
210           {
211              e_flowlayout_pack_end(o_flow_secondary, o);
212              iw = ih = e_config->syscon.secondary.icon_size * e_scale;
213           }
214         edje_object_message_signal_process(o);
215         edje_object_size_min_calc(o, &mw, &mh);
216         if (mw > iw) iw = mw;
217         if (mh > ih) ih = mh;
218         e_flowlayout_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5, 
219                                       iw, ih, iw, ih);
220         evas_object_show(o);
221      }
222
223    for (l = (Eina_List *)e_sys_con_extra_action_list_get(); l; l = l->next)
224      {
225         E_Sys_Con_Action *sca;
226         char buf[1024];
227         
228         sca = l->data;
229         o = edje_object_add(popup->evas);
230         edje_object_signal_callback_add(o, "e,action,click", "", _cb_signal_action_extra, sca);
231         if (sca->button_name)
232           {
233              snprintf(buf, sizeof(buf), "e/widgets/syscon/item/%s",
234                       sca->button_name);
235              e_theme_edje_object_set(o, "base/theme/widgets", buf);
236           }
237         else
238           e_theme_edje_object_set(o, "base/theme/widgets",
239                                   "e/widgets/syscon/item/button");
240         edje_object_part_text_set(o, "e.text.label", sca->label);
241         if (sca->icon_group)
242           {
243              o2 = edje_object_add(popup->evas);
244              e_util_edje_icon_set(o2, sca->icon_group);
245              edje_object_part_swallow(o, "e.swallow.icon", o2);
246              evas_object_show(o2);
247              if (sca->disabled)
248                edje_object_signal_emit(o2, "e,state,disabled", "e");
249           }
250         if (sca->disabled)
251           edje_object_signal_emit(o, "e,state,disabled", "e");
252         e_flowlayout_pack_end(o_flow_extra, o);
253         iw = ih = e_config->syscon.extra.icon_size * e_scale;
254         e_flowlayout_pack_options_set(o, 1, 1, 0, 0, 0.5, 0.5, 
255                                       iw, ih, iw, ih);
256         evas_object_show(o);
257      }
258
259    e_flowlayout_fill_set(o_flow_main, 1);
260    edje_object_part_swallow(o_bg, "e.swallow.main", o_flow_main);
261    e_flowlayout_fill_set(o_flow_secondary, 1);
262    edje_object_part_swallow(o_bg, "e.swallow.secondary", o_flow_secondary);
263    e_flowlayout_fill_set(o_flow_extra, 1);
264    edje_object_part_swallow(o_bg, "e.swallow.extra", o_flow_extra);
265
266    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
267    evas_object_resize(o_bg, zw, zh);
268    edje_object_calc_force(o_bg);
269
270    e_flowlayout_size_min_get(o_flow_main, &mw, &mh);
271    edje_extern_object_min_size_set(o_flow_main, mw, mh); 
272    edje_object_part_swallow(o_bg, "e.swallow.main", o_flow_main);
273    e_flowlayout_size_min_get(o_flow_secondary, &mw, &mh);
274    edje_extern_object_min_size_set(o_flow_secondary, mw, mh); 
275    edje_object_part_swallow(o_bg, "e.swallow.secondary", o_flow_secondary);
276    e_flowlayout_size_min_get(o_flow_extra, &mw, &mh);
277    edje_extern_object_min_size_set(o_flow_extra, mw, mh); 
278    edje_object_part_swallow(o_bg, "e.swallow.extra", o_flow_extra);
279
280    edje_object_size_min_calc(o_bg, &mw, &mh);
281
282    w = mw;
283    if (w > zw) w = zw;
284    x = zx - zone->x + (zw - w) / 2;
285    h = mh;
286    if (h > zh) h = zh;
287    y = zy - zone->y + (zh - h) / 2;
288
289    e_popup_move_resize(popup, x, y, w, h);
290    evas_object_move(o_bg, 0, 0);
291    evas_object_resize(o_bg, w, h);
292    evas_object_show(o_bg);
293    e_popup_edje_bg_object_set(popup, o_bg);
294
295    if (e_config->syscon.do_input)
296      {
297         deftimer = ecore_timer_add(e_config->syscon.timeout, 
298                                    _cb_timeout_defaction, NULL);
299         if (defact) do_defact = eina_stringshare_add(defact);
300      }
301
302    evas_event_thaw(popup->evas);
303    inevas = 0;
304    e_popup_show(popup);
305    return 1;
306 }
307
308 void
309 e_syscon_hide(void)
310 {
311    if (!popup) return;
312
313    if (deftimer)
314      {
315         ecore_timer_del(deftimer);
316         deftimer = NULL;
317      }
318    if (do_defact) eina_stringshare_del(do_defact);
319    do_defact = NULL;
320    while (handlers)
321      {
322         ecore_event_handler_del(handlers->data);
323         handlers = eina_list_remove_list(handlers, handlers);
324      }
325    e_popup_hide(popup);
326    e_object_del(E_OBJECT(popup));
327    popup = NULL;
328    e_grabinput_release(input_window, input_window);
329    ecore_x_window_free(input_window);
330    input_window = 0;
331 }
332
333 /* local subsystem functions */
334 static Eina_Bool
335 _cb_key_down(__UNUSED__ void *data, __UNUSED__ int type, void *event)
336 {
337    Ecore_Event_Key *ev;
338
339    ev = event;
340    if (ev->event_window != input_window) return ECORE_CALLBACK_PASS_ON;
341    if (!strcmp(ev->key, "Escape"))
342      e_syscon_hide();
343    else if (!strcmp(ev->key, "Up"))
344      {
345         // FIXME: implement focus and key control... eventually
346      }
347    else if (!strcmp(ev->key, "Down"))
348      {
349         // FIXME: implement focus and key control... eventually
350      }
351    else if (!strcmp(ev->key, "Left"))
352      {
353         // FIXME: implement focus and key control... eventually
354      }
355    else if (!strcmp(ev->key, "Right"))
356      {
357         // FIXME: implement focus and key control... eventually
358      }
359    else if (!strcmp(ev->key, "Tab"))
360      {
361         // FIXME: implement focus and key control... eventually
362      }
363    else if (!strcmp(ev->key, "Enter"))
364      {
365         // FIXME: implement focus and key control... eventually
366      }
367    else
368      {
369         E_Action *act;
370         double t;
371         
372         t = ecore_loop_time_get();
373         if (t - show_time > 0.5)
374           {
375              act = e_bindings_key_down_event_find(E_BINDING_CONTEXT_ANY, ev);
376              if ((act) && (act->name))
377                {
378                   if (!strcmp(act->name, "syscon"))
379                     {
380                        if (popup)
381                          {
382                             e_syscon_show(popup->zone, do_defact);
383                          }
384                     }
385                   else
386                     {
387                        Eina_List *l;
388                        
389                        for (l = e_config->syscon.actions; l; l = l->next)
390                          {
391                             E_Config_Syscon_Action *sca;
392                             
393                             if (!(sca = l->data)) continue;
394                             if (!sca->action) continue;
395                             if (!strcmp(sca->action, act->name))
396                               {
397                                  act_count++;
398                                  if (act_count > 2)
399                                    {
400                                       act->func.go(NULL, sca->params);
401                                       e_syscon_hide();
402                                       break;
403                                    }
404                               }
405                          }
406                     }
407                }
408           }
409      }
410
411    return ECORE_CALLBACK_PASS_ON;
412 }
413
414 static Eina_Bool
415 _cb_mouse_down(__UNUSED__ void *data, __UNUSED__ int type, void *event)
416 {
417    Ecore_Event_Mouse_Button *ev;
418    Evas_Button_Flags flags = EVAS_BUTTON_NONE;
419
420    ev = event;
421    if (ev->event_window != input_window) return ECORE_CALLBACK_PASS_ON;
422    if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
423    if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
424    if ((ev->x < popup->x) || (ev->x >= (popup->x + popup->w)) ||
425        (ev->y < popup->y) || (ev->y >= (popup->y + popup->h)))
426      {
427         e_syscon_hide();
428         return ECORE_CALLBACK_PASS_ON;
429      }
430    evas_event_feed_mouse_down(popup->evas, ev->buttons, flags, ev->timestamp, NULL);
431    return ECORE_CALLBACK_PASS_ON;
432 }
433
434 static Eina_Bool
435 _cb_mouse_up(__UNUSED__ void *data, __UNUSED__ int type, void *event)
436 {
437    Ecore_Event_Mouse_Button *ev;
438
439    ev = event;
440    if (ev->event_window != input_window) return ECORE_CALLBACK_PASS_ON;
441    evas_event_feed_mouse_up(popup->evas, ev->buttons, EVAS_BUTTON_NONE,
442                             ev->timestamp, NULL);
443    return ECORE_CALLBACK_PASS_ON;
444 }
445
446 static Eina_Bool
447 _cb_mouse_move(__UNUSED__ void *data, __UNUSED__ int type, void *event)
448 {
449    Ecore_Event_Mouse_Move *ev;
450
451    ev = event;
452    if (ev->event_window != input_window) return ECORE_CALLBACK_PASS_ON;
453    if (!inevas)
454      {
455         evas_event_feed_mouse_in(popup->evas, ev->timestamp, NULL);
456         inevas = 1;
457      }
458    evas_event_feed_mouse_move(popup->evas, ev->x - popup->x, ev->y - popup->y,
459                               ev->timestamp, NULL);
460    return ECORE_CALLBACK_PASS_ON;
461 }
462
463 static Eina_Bool
464 _cb_mouse_wheel(__UNUSED__ void *data, __UNUSED__ int type, void *event)
465 {
466    Ecore_Event_Mouse_Wheel *ev;
467
468    ev = event;
469    if (ev->event_window != input_window) return ECORE_CALLBACK_PASS_ON;
470    evas_event_feed_mouse_wheel(popup->evas, ev->direction, ev->z, 
471                                ev->timestamp, NULL);
472    return ECORE_CALLBACK_PASS_ON;
473 }
474
475 static void
476 _cb_signal_close(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
477 {
478    e_syscon_hide();
479 }
480
481 static void
482 _do_action_name(const char *action)
483 {
484    Eina_List *l;
485
486    for (l = e_config->syscon.actions; l; l = l->next)
487      {
488         E_Config_Syscon_Action *sca;
489         E_Action *a;
490
491         sca = l->data;
492         if (!sca->action) continue;
493         if (!strcmp(sca->action, action))
494           {
495              a = e_action_find(sca->action);
496              if (!a) break;
497              if (a) a->func.go(NULL, sca->params);
498              break;
499           }
500      }
501 }
502
503 static void
504 _cb_signal_syscon(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source)
505 {
506    e_syscon_hide();
507    _do_action_name(source);
508 }
509
510 static void
511 _cb_signal_action(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
512 {
513    E_Config_Syscon_Action *sca;
514    E_Action *a;
515
516    e_syscon_hide();
517    sca = data;
518    if (!sca) return;
519    a = e_action_find(sca->action);
520    if (!a) return;
521    a->func.go(NULL, sca->params);
522 }
523
524 static void
525 _cb_signal_action_extra(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
526 {
527    E_Sys_Con_Action *sca;
528   
529    e_syscon_hide();
530    sca = data;
531    if (!sca) return;
532    if (sca->func) sca->func((void *)sca->data);
533 }
534
535 static Eina_Bool
536 _cb_timeout_defaction(void *data __UNUSED__)
537 {
538    const char *defact = NULL;
539    deftimer = NULL;
540    if (!do_defact) return ECORE_CALLBACK_CANCEL;
541    defact = eina_stringshare_add(do_defact);
542    e_syscon_hide();
543    if (defact)
544      {
545         _do_action_name(defact);
546         eina_stringshare_del(defact);
547      }
548    return ECORE_CALLBACK_CANCEL;
549 }