Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / everything / evry_plug_windows.c
1 #include "e.h"
2 #include "evry_api.h"
3
4 #define BORDER_SHOW       1
5 #define BORDER_HIDE       2
6 #define BORDER_FULLSCREEN 3
7 #define BORDER_TODESK     4
8 #define BORDER_CLOSE      5
9
10 typedef struct _Plugin      Plugin;
11 typedef struct _Border_Item Border_Item;
12
13 struct _Plugin
14 {
15    Evry_Plugin base;
16    Eina_List  *borders;
17    Eina_List  *handlers;
18    const char *input;
19 };
20
21 struct _Border_Item
22 {
23    Evry_Item base;
24    E_Border *border;
25 };
26
27 static const Evry_API *evry = NULL;
28 static Evry_Module *evry_module = NULL;
29 static Evry_Plugin *_plug;
30 static Eina_List *_actions = NULL;
31
32 static Evas_Object *_icon_get(Evry_Item *it, Evas *e);
33
34 /***************************************************************************/
35
36 #define GET_BORDER(_bd, _it) Border_Item * _bd = (Border_Item *)_it;
37
38 static void
39 _border_item_free(Evry_Item *it)
40 {
41    GET_BORDER(bi, it);
42
43    e_object_unref(E_OBJECT(bi->border));
44
45    E_FREE(bi);
46 }
47
48 static int
49 _border_item_add(Plugin *p, E_Border *bd)
50 {
51    Border_Item *bi;
52    char buf[1024];
53
54    if (bd->client.netwm.state.skip_taskbar)
55      return 0;
56    if (bd->client.netwm.state.skip_pager)
57      return 0;
58
59    bi = EVRY_ITEM_NEW(Border_Item, p, e_border_name_get(bd),
60                       _icon_get, _border_item_free);
61
62    snprintf(buf, sizeof(buf), "%d:%d %s",
63             bd->desk->x, bd->desk->y,
64             (bd->desktop ? bd->desktop->name : ""));
65    EVRY_ITEM_DETAIL_SET(bi, buf);
66
67    bi->border = bd;
68    e_object_ref(E_OBJECT(bd));
69
70    p->borders = eina_list_append(p->borders, bi);
71
72    return 1;
73 }
74
75 static Eina_Bool
76 _cb_border_remove(void *data, __UNUSED__ int type, void *event)
77 {
78    E_Event_Border_Remove *ev = event;
79    Border_Item *bi;
80    Eina_List *l;
81    Plugin *p = data;
82
83    EINA_LIST_FOREACH (p->borders, l, bi)
84      if (bi->border == ev->border)
85        break;
86
87    if (!bi) return ECORE_CALLBACK_PASS_ON;
88
89    EVRY_PLUGIN_ITEMS_CLEAR(p);
90
91    p->borders = eina_list_remove(p->borders, bi);
92    EVRY_ITEM_FREE(bi);
93
94    EVRY_PLUGIN_ITEMS_ADD(p, p->borders, p->input, 1, 0);
95
96    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
97
98    return ECORE_CALLBACK_PASS_ON;
99 }
100
101 static Eina_Bool
102 _cb_border_add(void *data, __UNUSED__ int type, void *event)
103 {
104    E_Event_Border_Add *ev = event;
105    Plugin *p = data;
106
107    if (!_border_item_add(p, ev->border))
108      return ECORE_CALLBACK_PASS_ON;
109
110    EVRY_PLUGIN_ITEMS_CLEAR(p);
111
112    EVRY_PLUGIN_ITEMS_ADD(p, p->borders, p->input, 1, 0);
113
114    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
115
116    return ECORE_CALLBACK_PASS_ON;
117 }
118
119 static Evry_Plugin *
120 _begin(Evry_Plugin *plugin, const Evry_Item *item __UNUSED__)
121 {
122    Plugin *p;
123    E_Border *bd;
124    Eina_List *l;
125
126    EVRY_PLUGIN_INSTANCE(p, plugin);
127
128    p->handlers = eina_list_append
129        (p->handlers, ecore_event_handler_add
130          (E_EVENT_BORDER_REMOVE, _cb_border_remove, p));
131
132    p->handlers = eina_list_append
133        (p->handlers, ecore_event_handler_add
134          (E_EVENT_BORDER_ADD, _cb_border_add, p));
135
136    EINA_LIST_FOREACH (e_border_focus_stack_get(), l, bd)
137      _border_item_add(p, bd);
138
139    return EVRY_PLUGIN(p);
140 }
141
142 static void
143 _finish(Evry_Plugin *plugin)
144 {
145    Ecore_Event_Handler *h;
146    Border_Item *bi;
147
148    GET_PLUGIN(p, plugin);
149
150    IF_RELEASE(p->input);
151
152    EVRY_PLUGIN_ITEMS_CLEAR(p);
153
154    EINA_LIST_FREE (p->borders, bi)
155      EVRY_ITEM_FREE(bi);
156
157    EINA_LIST_FREE (p->handlers, h)
158      ecore_event_handler_del(h);
159
160    E_FREE(p);
161 }
162
163 static int
164 _fetch(Evry_Plugin *plugin, const char *input)
165 {
166    GET_PLUGIN(p, plugin);
167
168    EVRY_PLUGIN_ITEMS_CLEAR(p);
169
170    EVRY_PLUGIN_MIN_QUERY(p, input)
171    {
172       IF_RELEASE(p->input);
173
174       if (input)
175         p->input = eina_stringshare_add(input);
176
177       return EVRY_PLUGIN_ITEMS_ADD(p, p->borders, input, 1, 0);
178    }
179
180    return 0;
181 }
182
183 static Evas_Object *
184 _icon_get(Evry_Item *it, Evas *e)
185 {
186    GET_BORDER(bi, it);
187
188    Evas_Object *o = NULL;
189    E_Border *bd = bi->border;
190
191    if (bd->internal)
192      {
193         if (!bd->internal_icon)
194           {
195              o = e_icon_add(e);
196              e_util_icon_theme_set(o, "enlightenment");
197           }
198         else if (!bd->internal_icon_key)
199           {
200              char *ext;
201              ext = strrchr(bd->internal_icon, '.');
202              if ((ext) && ((!strcmp(ext, ".edj"))))
203                {
204                   o = edje_object_add(e);
205                   if (!edje_object_file_set(o, bd->internal_icon, "icon"))
206                     e_util_icon_theme_set(o, "enlightenment");
207                }
208              else if (ext)
209                {
210                   o = e_icon_add(e);
211                   e_icon_file_set(o, bd->internal_icon);
212                }
213              else
214                {
215                   o = e_icon_add(e);
216                   e_icon_scale_size_set(o, 128);
217                   if (!e_util_icon_theme_set(o, bd->internal_icon))
218                     e_util_icon_theme_set(o, "enlightenment");
219                }
220           }
221         else
222           {
223              o = edje_object_add(e);
224              edje_object_file_set(o, bd->internal_icon, bd->internal_icon_key);
225           }
226
227         return o;
228      }
229
230    if (bd->client.netwm.icons)
231      {
232         if (e_config->use_app_icon)
233           goto _use_netwm_icon;
234
235         if (bd->remember && (bd->remember->prop.icon_preference == E_ICON_PREF_NETWM))
236           goto _use_netwm_icon;
237      }
238
239    if (bd->desktop)
240      {
241         o = e_util_desktop_icon_add(bd->desktop, 128, e);
242         if (o) return o;
243      }
244
245 _use_netwm_icon:
246    if (bd->client.netwm.icons)
247      {
248         int i, size, tmp, found = 0;
249         o = e_icon_add(e);
250
251         size = bd->client.netwm.icons[0].width;
252
253         for (i = 1; i < bd->client.netwm.num_icons; i++)
254           {
255              if ((tmp = bd->client.netwm.icons[i].width) > size)
256                {
257                   size = tmp;
258                   found = i;
259                }
260           }
261
262         e_icon_data_set(o, bd->client.netwm.icons[found].data,
263                         bd->client.netwm.icons[found].width,
264                         bd->client.netwm.icons[found].height);
265         e_icon_alpha_set(o, 1);
266         return o;
267      }
268
269    o = e_border_icon_add(bd, e);
270    if (o) return o;
271
272    o = edje_object_add(e);
273    e_util_icon_theme_set(o, "unknown");
274
275    return o;
276 }
277
278 /***************************************************************************/
279
280 static int
281 _check_border(Evry_Action *act, const Evry_Item *it)
282 {
283    GET_BORDER(bi, it);
284
285    int action = EVRY_ITEM_DATA_INT_GET(act);
286    E_Border *bd = bi->border;
287    E_Zone *zone = e_util_zone_current_get(e_manager_current_get());
288
289    if (!bd)
290      {
291         ERR("no border");
292         return 0;
293      }
294
295    switch (action)
296      {
297       case BORDER_CLOSE:
298         if (bd->lock_close)
299           return 0;
300         break;
301
302       case BORDER_SHOW:
303         if (bd->lock_focus_in)
304           return 0;
305         break;
306
307       case BORDER_HIDE:
308         if (bd->lock_user_iconify)
309           return 0;
310         break;
311
312       case BORDER_FULLSCREEN:
313         if (!bd->lock_user_fullscreen)
314           return 0;
315         break;
316
317       case BORDER_TODESK:
318         if (bd->desk == (e_desk_current_get(zone)))
319           return 0;
320         break;
321      }
322
323    return 1;
324 }
325
326 static int
327 _act_border(Evry_Action *act)
328 {
329    GET_BORDER(bi, act->it1.item);
330
331    int action = EVRY_ITEM_DATA_INT_GET(act);
332    E_Border *bd = bi->border;
333    E_Zone *zone = e_util_zone_current_get(e_manager_current_get());
334    int focus = 0;
335
336    if (!bd)
337      {
338         ERR("no border");
339         return 0;
340      }
341
342    switch (action)
343      {
344       case BORDER_CLOSE:
345         e_border_act_close_begin(bd);
346         break;
347
348       case BORDER_SHOW:
349         if (bd->desk != (e_desk_current_get(zone)))
350           e_desk_show(bd->desk);
351         focus = 1;
352         break;
353
354       case BORDER_HIDE:
355         e_border_iconify(bd);
356         break;
357
358       case BORDER_FULLSCREEN:
359         if (!bd->fullscreen)
360           e_border_fullscreen(bd, E_FULLSCREEN_RESIZE);
361         else
362           e_border_unfullscreen(bd);
363         break;
364
365       case BORDER_TODESK:
366         if (bd->desk != (e_desk_current_get(zone)))
367           e_border_desk_set(bd, e_desk_current_get(zone));
368         focus = 1;
369         break;
370
371       default:
372         break;
373      }
374
375    if (focus)
376      {
377         if (bd->shaded)
378           e_border_unshade(bd, E_DIRECTION_UP);
379
380         if (bd->iconic)
381           e_border_uniconify(bd);
382         else
383           e_border_raise(bd);
384
385         if (!bd->lock_focus_out)
386           {
387              e_border_focus_set(bd, 1, 1);
388              e_border_focus_latest_set(bd);
389           }
390
391         if ((e_config->focus_policy != E_FOCUS_CLICK) ||
392             (e_config->winlist_warp_at_end) ||
393             (e_config->winlist_warp_while_selecting))
394           {
395              int warp_to_x = bd->x + (bd->w / 2);
396              if (warp_to_x < (bd->zone->x + 1))
397                warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
398              else if (warp_to_x >= (bd->zone->x + bd->zone->w - 1))
399                warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
400
401              int warp_to_y = bd->y + (bd->h / 2);
402              if (warp_to_y < (bd->zone->y + 1))
403                warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
404              else if (warp_to_y >= (bd->zone->y + bd->zone->h - 1))
405                warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
406
407              ecore_x_pointer_warp(bd->zone->container->win, warp_to_x, warp_to_y);
408           }
409         /* e_border_focus_set_with_pointer(bd); */
410      }
411
412    return 1;
413 }
414
415 static int
416 _plugins_init(const Evry_API *_api)
417 {
418    Evry_Action *act;
419
420    evry = _api;
421
422    if (!evry->api_version_check(EVRY_API_VERSION))
423      return EINA_FALSE;
424
425    _plug = EVRY_PLUGIN_BASE("Windows", "preferences-system-windows",
426                             EVRY_TYPE_BORDER, _begin, _finish, _fetch);
427    _plug->transient = EINA_TRUE;
428    evry->plugin_register(_plug, EVRY_PLUGIN_SUBJECT, 2);
429
430    act = EVRY_ACTION_NEW("Switch to Window",
431                          EVRY_TYPE_BORDER, 0, "go-next",
432                          _act_border, _check_border);
433    EVRY_ITEM_DATA_INT_SET(act, BORDER_SHOW);
434    evry->action_register(act, 1);
435
436    _actions = eina_list_append(_actions, act);
437
438    act = EVRY_ACTION_NEW("Iconify",
439                          EVRY_TYPE_BORDER, 0, "go-down",
440                          _act_border, _check_border);
441    EVRY_ITEM_DATA_INT_SET(act, BORDER_HIDE);
442    _actions = eina_list_append(_actions, act);
443    evry->action_register(act, 2);
444
445    act = EVRY_ACTION_NEW("Toggle Fullscreen",
446                          EVRY_TYPE_BORDER, 0, "view-fullscreen",
447                          _act_border, _check_border);
448    EVRY_ITEM_DATA_INT_SET(act, BORDER_FULLSCREEN);
449    _actions = eina_list_append(_actions, act);
450    evry->action_register(act, 4);
451
452    act = EVRY_ACTION_NEW("Close",
453                          EVRY_TYPE_BORDER, 0, "list-remove",
454                          _act_border, _check_border);
455    EVRY_ITEM_DATA_INT_SET(act, BORDER_CLOSE);
456    _actions = eina_list_append(_actions, act);
457    evry->action_register(act, 3);
458
459    act = EVRY_ACTION_NEW("Send to Desktop",
460                          EVRY_TYPE_BORDER, 0, "go-previous",
461                          _act_border, _check_border);
462    EVRY_ITEM_DATA_INT_SET(act, BORDER_TODESK);
463    _actions = eina_list_append(_actions, act);
464    evry->action_register(act, 3);
465
466    return EINA_TRUE;
467 }
468
469 static void
470 _plugins_shutdown(void)
471 {
472    Evry_Action *act;
473
474    EVRY_PLUGIN_FREE(_plug);
475
476    EINA_LIST_FREE (_actions, act)
477      EVRY_ACTION_FREE(act);
478 }
479
480 /***************************************************************************/
481
482 Eina_Bool
483 evry_plug_windows_init(E_Module *m __UNUSED__)
484 {
485    EVRY_MODULE_NEW(evry_module, evry, _plugins_init, _plugins_shutdown);
486
487    return EINA_TRUE;
488 }
489
490 void
491 evry_plug_windows_shutdown(void)
492 {
493    EVRY_MODULE_FREE(evry_module);
494 }
495
496 void
497 evry_plug_windows_save(void){}
498