Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / illume-softkey / e_mod_sft_win.c
1 #include "e.h"
2 #include "e_mod_main.h"
3 #include "e_mod_config.h"
4 #include "e_mod_sft_win.h"
5
6 /* local function prototypes */
7 static void _e_mod_sft_win_cb_free(Sft_Win *swin);
8 static Eina_Bool _e_mod_sft_win_cb_win_prop(void *data, int type __UNUSED__, void *event);
9 static Eina_Bool _e_mod_sft_win_cb_zone_resize(void *data, int type __UNUSED__, void *event);
10 static void _e_mod_sft_win_cb_resize(E_Win *win);
11 static void _e_mod_sft_win_create_default_buttons(Sft_Win *swin);
12 static void _e_mod_sft_win_create_extra_buttons(Sft_Win *swin);
13 static void _e_mod_sft_win_cb_close(void *data, void *data2 __UNUSED__);
14 static void _e_mod_sft_win_cb_back(void *data, void *data2 __UNUSED__);
15 static void _e_mod_sft_win_cb_forward(void *data, void *data2 __UNUSED__);
16 static void _e_mod_sft_win_cb_win_pos(void *data, void *data2 __UNUSED__);
17 static void _e_mod_sft_win_pos_toggle_top(Sft_Win *swin);
18 static void _e_mod_sft_win_pos_toggle_left(Sft_Win *swin);
19 static E_Border *_e_mod_sft_win_border_get(E_Zone *zone, int x, int y);
20
21 Sft_Win *
22 e_mod_sft_win_new(E_Zone *zone) 
23 {
24    Sft_Win *swin;
25    Ecore_X_Window_State states[2];
26    Evas_Coord mw = 0, mh = 0;
27    
28    /* create our new softkey window object */
29    swin = E_OBJECT_ALLOC(Sft_Win, SFT_WIN_TYPE, _e_mod_sft_win_cb_free);
30    if (!swin) return NULL;
31
32    swin->zone = zone;
33    
34    /* hook into property change so we can adjust w/ e_scale */
35    swin->hdls = 
36      eina_list_append(swin->hdls, 
37                       ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, 
38                                               _e_mod_sft_win_cb_win_prop, swin));
39
40    /* hook into zone resize so we can adjust min width */
41    swin->hdls = 
42      eina_list_append(swin->hdls, 
43                       ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE, 
44                                               _e_mod_sft_win_cb_zone_resize, 
45                                               swin));
46
47    /* create new window */
48    swin->win = e_win_new(zone->container);
49    swin->win->data = swin;
50
51    /* set some properties on the window */
52    e_win_title_set(swin->win, _("Illume Softkey"));
53    e_win_name_class_set(swin->win, "Illume-Softkey", "Illume-Softkey");
54    e_win_no_remember_set(swin->win, EINA_TRUE);
55
56    /* hook into window resize so we can resize our objects */
57    e_win_resize_callback_set(swin->win, _e_mod_sft_win_cb_resize);
58
59    /* set this window to not show in taskbar or pager */
60    states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
61    states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
62    ecore_x_netwm_window_state_set(swin->win->evas_win, states, 2);
63
64    /* set this window to not accept or take focus */
65    ecore_x_icccm_hints_set(swin->win->evas_win, 0, 0, 0, 0, 0, 0, 0);
66
67    /* create our base object */
68    swin->o_base = edje_object_add(swin->win->evas);
69    if (!e_theme_edje_object_set(swin->o_base, 
70                                 "base/theme/modules/illume-softkey", 
71                                 "modules/illume-softkey/window")) 
72      {
73         char buff[PATH_MAX];
74
75         snprintf(buff, sizeof(buff), 
76                  "%s/e-module-illume-softkey.edj", _sft_mod_dir);
77         edje_object_file_set(swin->o_base, buff, 
78                              "modules/illume-softkey/window");
79      }
80    evas_object_move(swin->o_base, 0, 0);
81    evas_object_show(swin->o_base);
82
83    /* create default buttons */
84    _e_mod_sft_win_create_default_buttons(swin);
85
86    /* create default buttons */
87    _e_mod_sft_win_create_extra_buttons(swin);
88
89    edje_object_size_min_calc(swin->o_base, &mw, &mh);
90    
91    /* set minimum size of this window */
92    e_win_size_min_set(swin->win, zone->w, mh);
93
94    /* position and resize this window */
95    e_win_move_resize(swin->win, zone->x, 
96                      (zone->y + zone->h - (il_sft_cfg->height * e_scale)), 
97                      zone->w, mh);
98
99    /* show the window */
100    e_win_show(swin->win);
101
102    e_border_zone_set(swin->win->border, zone);
103    swin->win->border->user_skip_winlist = 1;
104
105    swin->win->border->lock_focus_in = 1;
106    swin->win->border->lock_focus_out = 1;
107
108    /* set this window to be a dock window. This needs to be done after show 
109     * as E will sometimes reset the window type */
110    ecore_x_netwm_window_type_set(swin->win->evas_win, ECORE_X_WINDOW_TYPE_DOCK);
111
112    /* tell conformant apps our position and size */
113    ecore_x_e_illume_softkey_geometry_set(zone->black_win, 
114                                          zone->x, 
115                                          (zone->h - (il_sft_cfg->height * e_scale)), 
116                                          zone->w, 
117                                          (il_sft_cfg->height * e_scale));
118
119    return swin;
120 }
121
122 /* local functions */
123 static void 
124 _e_mod_sft_win_cb_free(Sft_Win *swin) 
125 {
126    Ecore_Event_Handler *hdl;
127    const Evas_Object *box;
128
129    /* delete the event handlers */
130    EINA_LIST_FREE(swin->hdls, hdl)
131      ecore_event_handler_del(hdl);
132
133    if ((box = edje_object_part_object_get(swin->o_base, "e.box.buttons"))) 
134      {
135         Evas_Object *btn;
136
137         /* delete the buttons */
138         EINA_LIST_FREE(swin->btns, btn) 
139           {
140              edje_object_part_box_remove(swin->o_base, "e.box.buttons", btn);
141              evas_object_del(btn);
142           }
143      }
144    if ((box = edje_object_part_object_get(swin->o_base, "e.box.extra_buttons"))) 
145      {
146         Evas_Object *btn;
147
148         /* delete the buttons */
149         EINA_LIST_FREE(swin->extra_btns, btn) 
150           {
151              edje_object_part_box_remove(swin->o_base, 
152                                          "e.box.extra_buttons", btn);
153              evas_object_del(btn);
154           }
155      }
156
157    /* delete the objects */
158    if (swin->o_base) evas_object_del(swin->o_base);
159    swin->o_base = NULL;
160
161    /* delete the window */
162    if (swin->win) e_object_del(E_OBJECT(swin->win));
163    swin->win = NULL;
164
165    /* tell conformant apps our position and size */
166    ecore_x_e_illume_softkey_geometry_set(swin->zone->black_win, 0, 0, 0, 0);
167
168    /* free the allocated object */
169    E_FREE(swin);
170 }
171
172 static Eina_Bool
173 _e_mod_sft_win_cb_win_prop(void *data, int type __UNUSED__, void *event) 
174 {
175    Sft_Win *swin;
176    Ecore_X_Event_Window_Property *ev;
177
178    ev = event;
179
180    if (!(swin = data)) return ECORE_CALLBACK_PASS_ON;
181    if (ev->win != swin->win->container->manager->root) 
182      return ECORE_CALLBACK_PASS_ON;
183    if (ev->atom != ATM_ENLIGHTENMENT_SCALE) return ECORE_CALLBACK_PASS_ON;
184
185    /* set minimum size of this window */
186    e_win_size_min_set(swin->win, swin->zone->w, (il_sft_cfg->height * e_scale));
187
188    /* NB: Not sure why, but we need to tell this border to fetch icccm 
189     * size position hints now :( (NOTE: This was not needed a few days ago) 
190     * If we do not do this, than softkey does not change w/ scale anymore */
191    swin->win->border->client.icccm.fetch.size_pos_hints = 1;
192
193    /* resize this window */
194    e_win_resize(swin->win, swin->zone->w, (il_sft_cfg->height * e_scale));
195
196    /* tell conformant apps our position and size */
197    ecore_x_e_illume_softkey_geometry_set(swin->zone->black_win, 
198                                          swin->win->x, swin->win->y, 
199                                          swin->win->w, 
200                                          (il_sft_cfg->height * e_scale));
201    return ECORE_CALLBACK_PASS_ON;
202 }
203
204 static Eina_Bool
205 _e_mod_sft_win_cb_zone_resize(void *data, int type __UNUSED__, void *event) 
206 {
207    Sft_Win *swin;
208    E_Event_Zone_Move_Resize *ev;
209
210    ev = event;
211    if (!(swin = data)) return ECORE_CALLBACK_PASS_ON;
212    if (ev->zone != swin->zone) return ECORE_CALLBACK_PASS_ON;
213
214    /* set minimum size of this window */
215    e_win_size_min_set(swin->win, ev->zone->w, (il_sft_cfg->height * e_scale));
216
217    return ECORE_CALLBACK_PASS_ON;
218 }
219
220 static void 
221 _e_mod_sft_win_cb_resize(E_Win *win) 
222 {
223    Sft_Win *swin;
224    Evas_Object *btn;
225    const Evas_Object *box;
226    Eina_List *l;
227    int mw, mh;
228
229    if (!(swin = win->data)) return;
230
231    /* adjust button(s) size for e_scale */
232    EINA_LIST_FOREACH(swin->btns, l, btn) 
233      {
234         e_widget_size_min_get(btn, &mw, &mh);
235         evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale));
236         evas_object_resize(btn, (mw * e_scale), (mh * e_scale));
237      }
238
239    /* adjust box size for content */
240    if ((box = edje_object_part_object_get(swin->o_base, "e.box.buttons"))) 
241      {
242         evas_object_size_hint_min_get((Evas_Object *)box, &mw, &mh);
243         evas_object_resize((Evas_Object *)box, mw, mh);
244      }
245
246    mw = mh = 0;
247    /* adjust button(s) size for e_scale */
248    EINA_LIST_FOREACH(swin->extra_btns, l, btn) 
249      {
250         e_widget_size_min_get(btn, &mw, &mh);
251         evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale));
252         evas_object_resize(btn, (mw * e_scale), (mh * e_scale));
253      }
254
255    /* adjust box size for content */
256    if ((box = edje_object_part_object_get(swin->o_base, "e.box.extra_buttons"))) 
257      {
258         evas_object_size_hint_min_get((Evas_Object *)box, &mw, &mh);
259         evas_object_resize((Evas_Object *)box, mw, mh);
260      }
261
262    /* resize the base object */
263    if (swin->o_base) evas_object_resize(swin->o_base, win->w, win->h);
264 }
265
266 static void 
267 _e_mod_sft_win_create_default_buttons(Sft_Win *swin) 
268 {
269    Evas_Object *btn;
270    int mw, mh;
271
272    /* create back button */
273    btn = e_widget_button_add(swin->win->evas, _("Back"), "go-previous", 
274                              _e_mod_sft_win_cb_back, swin, NULL);
275    e_widget_size_min_get(btn, &mw, &mh);
276    evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale));
277
278    /* NB: this show is required when packing e_widgets into an edje box else
279     * the widgets do not receive any events */
280    evas_object_show(btn);
281
282    /* add button to box */
283    edje_object_part_box_append(swin->o_base, "e.box.buttons", btn);
284
285    /* add button to our list */
286    swin->btns = eina_list_append(swin->btns, btn);
287
288    /* create forward button */
289    btn = e_widget_button_add(swin->win->evas, _("Forward"), "go-next", 
290                              _e_mod_sft_win_cb_forward, swin, NULL);
291    e_widget_size_min_get(btn, &mw, &mh);
292    evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale));
293
294    /* NB: this show is required when packing e_widgets into an edje box else
295     * the widgets do not receive any events */
296    evas_object_show(btn);
297
298    /* add button to box */
299    edje_object_part_box_append(swin->o_base, "e.box.buttons", btn);
300
301    /* add button to our list */
302    swin->btns = eina_list_append(swin->btns, btn);
303    /* create close button */
304    btn = e_widget_button_add(swin->win->evas, _("Close"), "application-exit", 
305                              _e_mod_sft_win_cb_close, swin, NULL);
306    e_widget_size_min_get(btn, &mw, &mh);
307    evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale));
308
309    /* NB: this show is required when packing e_widgets into an edje box else
310     * the widgets do not receive any events */
311    evas_object_show(btn);
312
313    /* add button to box */
314    edje_object_part_box_append(swin->o_base, "e.box.buttons", btn);
315
316    /* add button to our list */
317    swin->btns = eina_list_append(swin->btns, btn);
318 }
319
320 static void 
321 _e_mod_sft_win_create_extra_buttons(Sft_Win *swin) 
322 {
323    Evas_Object *btn;
324    int mw, mh;
325
326    /* create window toggle button */
327    btn = e_widget_button_add(swin->win->evas, _("Switch"), "view-refresh", 
328                              _e_mod_sft_win_cb_win_pos, swin, NULL);
329    e_widget_size_min_get(btn, &mw, &mh);
330    evas_object_size_hint_min_set(btn, (mw * e_scale), (mh * e_scale));
331
332    /* NB: this show is required when packing e_widgets into an edje box else
333     * the widgets do not receive any events */
334    evas_object_show(btn);
335
336    /* add button to box */
337    edje_object_part_box_append(swin->o_base, "e.box.extra_buttons", btn);
338
339    /* add button to our list */
340    swin->extra_btns = eina_list_append(swin->extra_btns, btn);
341 }
342
343 static void 
344 _e_mod_sft_win_cb_close(void *data, void *data2 __UNUSED__) 
345 {
346    Sft_Win *swin;
347
348    if (!(swin = data)) return;
349    ecore_x_e_illume_close_send(swin->zone->black_win);
350 }
351
352 static void 
353 _e_mod_sft_win_cb_back(void *data, void *data2 __UNUSED__) 
354 {
355    Sft_Win *swin;
356
357    if (!(swin = data)) return;
358    ecore_x_e_illume_focus_back_send(swin->zone->black_win);
359 }
360
361 static void 
362 _e_mod_sft_win_cb_forward(void *data, void *data2 __UNUSED__) 
363 {
364    Sft_Win *swin;
365
366    if (!(swin = data)) return;
367    ecore_x_e_illume_focus_forward_send(swin->zone->black_win);
368 }
369
370 static void 
371 _e_mod_sft_win_cb_win_pos(void *data, void *data2 __UNUSED__) 
372 {
373    Sft_Win *swin;
374    Ecore_X_Illume_Mode mode;
375
376    if (!(swin = data)) return;
377    mode = ecore_x_e_illume_mode_get(swin->zone->black_win);
378    switch (mode) 
379      {
380       case ECORE_X_ILLUME_MODE_UNKNOWN:
381       case ECORE_X_ILLUME_MODE_SINGLE:
382         break;
383       case ECORE_X_ILLUME_MODE_DUAL_TOP:
384         _e_mod_sft_win_pos_toggle_top(swin);
385         break;
386       case ECORE_X_ILLUME_MODE_DUAL_LEFT:
387         _e_mod_sft_win_pos_toggle_left(swin);
388         break;
389      }
390 }
391
392 static void 
393 _e_mod_sft_win_pos_toggle_top(Sft_Win *swin) 
394 {
395    E_Border *t, *b;
396    int y, h, tpos, bpos;
397
398    if (!swin) return;
399    if (!ecore_x_e_illume_indicator_geometry_get(swin->zone->black_win, 
400                                                 NULL, &y, NULL, &h)) 
401      y = 0;
402
403    if (y > 0) 
404      {
405         tpos = 0;
406         bpos = (y + h);
407      }
408    else 
409      {
410         tpos = (y + h);
411         bpos = (swin->zone->h / 2);
412      }
413
414    t = _e_mod_sft_win_border_get(swin->zone, swin->zone->x, tpos);
415    b = _e_mod_sft_win_border_get(swin->zone, swin->zone->x, bpos);
416
417    if (t) e_border_move(t, t->x, bpos);
418    if (b) e_border_move(b, b->x, tpos);
419 }
420
421 static void 
422 _e_mod_sft_win_pos_toggle_left(Sft_Win *swin) 
423 {
424    E_Border *l, *r;
425    int h, lpos, rpos;
426
427    if (!swin) return;
428
429    if (!ecore_x_e_illume_indicator_geometry_get(swin->zone->black_win, 
430                                                 NULL, NULL, NULL, &h)) 
431      h = 0;
432
433    lpos = 0;
434    rpos = (swin->zone->w / 2);
435
436    l = _e_mod_sft_win_border_get(swin->zone, lpos, h);
437    r = _e_mod_sft_win_border_get(swin->zone, rpos, h);
438
439    if (l) e_border_move(l, rpos, l->y);
440    if (r) e_border_move(r, lpos, r->y);
441 }
442
443 static E_Border *
444 _e_mod_sft_win_border_get(E_Zone *zone, int x, int y) 
445 {
446    Eina_List *l;
447    E_Border *bd;
448
449    if (!zone) return NULL;
450    EINA_LIST_REVERSE_FOREACH(e_border_client_list(), l, bd) 
451      {
452         if (bd->zone != zone) continue;
453         if (!bd->visible) continue;
454         if ((bd->x != x) || (bd->y != y)) continue;
455         if (bd->client.illume.quickpanel.quickpanel) continue;
456
457         return bd;
458      }
459    return NULL;
460 }