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