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