Merged with devel
[platform/core/uifw/e17-extra-modules.git] / comp-tizen / src / e_mod_comp_effect_win_rotation.c
1 #include "e_mod_comp_shared_types.h"
2 #include "e_mod_comp.h"
3 #include "e_mod_comp_atoms.h"
4 #include "e_mod_comp_debug.h"
5 #include "e_mod_comp_effect_win_rotation.h"
6 #include <Elementary.h>
7
8 typedef struct _E_Comp_Zone_Rotation_Effect_Begin E_Comp_Zone_Rotation_Effect_Begin;
9 typedef struct _E_Comp_Zone_Rotation_Effect_End   E_Comp_Zone_Rotation_Effect_End;
10
11 struct _E_Comp_Effect_Zone_Rotation
12 {
13    E_Comp_Canvas      *canvas;
14    Eina_Bool           ready;
15    Eina_Bool           run;
16    Elm_Transit        *trans_begin;
17    Elm_Transit        *trans_end;
18    Elm_Transit_Effect *effect_begin;
19    Elm_Transit_Effect *effect_end;
20 };
21
22 struct _E_Comp_Zone_Rotation_Effect_Begin
23 {
24    Evas_Object   *o;
25    E_Zone        *zone;
26    double         src;
27    double         target;
28    Ecore_X_Image *xim;
29    Evas_Object   *img;
30    E_Comp_Layer  *ly;
31 };
32
33 struct _E_Comp_Zone_Rotation_Effect_End
34 {
35    Evas_Object *o;
36    E_Zone      *zone;
37    double       src;
38    double       target;
39 };
40
41 /* local subsystem functions */
42 static Eina_Bool            _angle_get(E_Comp_Win *cw, int *req, int *curr);
43 static Elm_Transit_Effect *_effect_zone_rot_begin_new(E_Comp_Layer *ly);
44 static Elm_Transit_Effect *_effect_zone_rot_end_new(Evas_Object *o, E_Zone *zone);
45 static void                _effect_zone_rot_begin_free(Elm_Transit_Effect *effect, Elm_Transit *transit);
46 static void                _effect_zone_rot_end_free(Elm_Transit_Effect *effect, Elm_Transit *transit);
47 static void                _effect_zone_rot_begin_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress);
48 static void                _effect_zone_rot_end_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress);
49
50 /* externally accessible functions */
51 EINTERN Eina_Bool
52 e_mod_comp_effect_win_angle_get(E_Comp_Win *cw)
53 {
54    E_Comp_Effect_Style st;
55    int req_angle = -1;
56    int cur_angle = -1;
57    Eina_Bool res;
58    Ecore_X_Window win;
59    E_CHECK_RETURN(cw, 0);
60
61    win = e_mod_comp_util_client_xid_get(cw);
62    st = e_mod_comp_effect_style_get
63       (cw->eff_type,
64        E_COMP_EFFECT_KIND_ROTATION);
65
66    if (st == E_COMP_EFFECT_STYLE_NONE)
67      return EINA_FALSE;
68
69    res = _angle_get(cw, &req_angle, &cur_angle);
70    if (!res)
71      return EINA_FALSE;
72
73    cw->angle = cur_angle;
74    cw->angle %= 360;
75
76    return EINA_TRUE;
77 }
78
79 EINTERN E_Comp_Effect_Zone_Rotation *
80 e_mod_comp_effect_zone_rotation_new(E_Comp_Canvas *canvas)
81 {
82    E_Comp_Effect_Zone_Rotation *zr = NULL;
83    zr = E_NEW(E_Comp_Effect_Zone_Rotation, 1);
84    E_CHECK_RETURN(zr, NULL);
85
86    zr->canvas = canvas;
87
88    return zr;
89 }
90
91 EINTERN void
92 e_mod_comp_effect_zone_rotation_free(E_Comp_Effect_Zone_Rotation *zr)
93 {
94    E_FREE(zr);
95 }
96
97 EINTERN Eina_Bool
98 e_mod_comp_effect_zone_rotation_begin(E_Comp_Effect_Zone_Rotation *zr)
99 {
100    E_Comp_Layer *ly;
101    E_Comp *c = e_mod_comp_util_get();
102
103    E_CHECK_RETURN(c->animatable, EINA_FALSE);
104
105    /* HACK: disabled xv app rotation and lock screen rotation
106     * look for full-screen window and then check class and name.
107     * if it is an app window which is using xv, rotation effect will be
108     * canceled.
109     */
110    E_Border *bd = e_border_focused_get();
111    E_Border *_bd = NULL;
112    E_Comp_Win *cw = NULL, *cw2 = NULL, *cw3 = NULL;
113    if (bd)
114      {
115         cw = e_mod_comp_win_find(bd->win);
116         if ((cw) && (!cw->invalid) && (!cw->input_only) && (cw->visible))
117           {
118              /* floating mode window can have focus */
119              if (!REGION_EQUAL_TO_ZONE(cw, bd->zone))
120                {
121                   cw2 = e_mod_comp_util_win_normal_get(cw);
122                   if ((cw2) && (cw2->bd))
123                     {
124                        _bd = cw2->bd;
125                        cw3 = cw2;
126                     }
127                }
128              else
129                {
130                   _bd = bd;
131                   cw3 = cw;
132                }
133
134              if (cw3)
135                {
136                   if (TYPE_LOCKSCREEN_CHECK(cw3) ||
137                       TYPE_HOME_CHECK(cw3))
138                     {
139                        ELB(ELBT_COMP, "SKIP ROT_EFFECT",
140                            e_mod_comp_util_client_xid_get(cw3));
141                        return EINA_FALSE;
142                     }
143                }
144
145              if (_bd)
146                {
147                   if ((_bd->client.icccm.name) && (_bd->client.icccm.class))
148                     {
149                        if ((!strcmp(_bd->client.icccm.name, "camera")) &&
150                            (!strcmp(_bd->client.icccm.class, "camera")))
151                          {
152                             ELB(ELBT_COMP, "SKIP CAMERA", _bd->client.win);
153                             return EINA_FALSE;
154                          }
155                        else if (!strcmp(_bd->client.icccm.name, "video_play"))
156                          {
157                             ELB(ELBT_COMP, "SKIP VIDEO PLAYER", _bd->client.win);
158                             return EINA_FALSE;
159                          }
160                     }
161                }
162           }
163      }
164
165    ly = e_mod_comp_canvas_layer_get(zr->canvas, "effect");
166    if (ly)
167      {
168         /* TODO: check animation is running */
169         if (zr->trans_begin) elm_transit_del(zr->trans_begin);
170         if (zr->trans_end) elm_transit_del(zr->trans_end);
171         zr->trans_begin = NULL;
172         zr->trans_end = NULL;
173
174         zr->trans_begin = elm_transit_add();
175
176         zr->effect_begin = _effect_zone_rot_begin_new(ly);
177         if (!zr->effect_begin)
178           {
179              if (zr->trans_begin) elm_transit_del(zr->trans_begin);
180              zr->trans_begin = NULL;
181              zr->ready = EINA_FALSE;
182              return EINA_FALSE;
183           }
184         elm_transit_object_add(zr->trans_begin, ly->layout);
185         elm_transit_smooth_set(zr->trans_begin, EINA_FALSE);
186         elm_transit_duration_set(zr->trans_begin, 0.4f);
187         elm_transit_effect_add(zr->trans_begin, _effect_zone_rot_begin_op, zr->effect_begin, _effect_zone_rot_begin_free);
188         elm_transit_tween_mode_set(zr->trans_begin, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
189         elm_transit_objects_final_state_keep_set(zr->trans_begin, EINA_FALSE);
190
191         e_mod_comp_layer_effect_set(ly, EINA_TRUE);
192
193         zr->ready = EINA_TRUE;
194      }
195
196    return EINA_TRUE;
197 }
198
199 EINTERN Eina_Bool
200 e_mod_comp_effect_zone_rotation_end(E_Comp_Effect_Zone_Rotation *zr)
201 {
202    E_Comp_Layer *ly;
203    E_Comp *c = e_mod_comp_util_get();
204
205    E_CHECK_RETURN(c->animatable, EINA_FALSE);
206    E_CHECK_RETURN(zr->ready, EINA_FALSE);
207    E_CHECK_RETURN(zr->trans_begin, EINA_FALSE);
208
209    zr->ready = EINA_FALSE;
210
211    ly = e_mod_comp_canvas_layer_get(zr->canvas, "comp");
212    if (ly)
213      {
214         if (zr->trans_end) elm_transit_del(zr->trans_end);
215         zr->trans_end = NULL;
216
217         zr->trans_end = elm_transit_add();
218         zr->effect_end = _effect_zone_rot_end_new(ly->layout, zr->canvas->zone);
219         elm_transit_object_add(zr->trans_end, ly->layout);
220         elm_transit_smooth_set(zr->trans_end, EINA_FALSE);
221         elm_transit_duration_set(zr->trans_end, 0.4f);
222         elm_transit_effect_add(zr->trans_end, _effect_zone_rot_end_op, zr->effect_end, _effect_zone_rot_end_free);
223         elm_transit_tween_mode_set(zr->trans_end, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
224         elm_transit_objects_final_state_keep_set(zr->trans_end, EINA_FALSE);
225
226         e_zone_rotation_block_set(zr->canvas->zone, "comp-tizen", EINA_TRUE);
227
228         return EINA_TRUE;
229      }
230
231    return EINA_FALSE;
232 }
233
234 EINTERN Eina_Bool
235 e_mod_comp_effect_zone_rotation_cancel(E_Comp_Effect_Zone_Rotation *zr)
236 {
237    if (zr->trans_begin)
238      {
239         elm_transit_del(zr->trans_begin);
240         zr->trans_begin = NULL;
241      }
242    if (zr->trans_end)
243      {
244         elm_transit_del(zr->trans_end);
245         zr->trans_end = NULL;
246      }
247    zr->ready = EINA_FALSE;
248
249    return EINA_TRUE;
250 }
251
252 EINTERN Eina_Bool
253 e_mod_comp_effect_zone_rotation_do(E_Comp_Effect_Zone_Rotation *zr)
254 {
255    E_Comp *c = e_mod_comp_util_get();
256    E_CHECK_RETURN(c->animatable, EINA_FALSE);
257
258    elm_transit_go(zr->trans_begin);
259    elm_transit_go(zr->trans_end);
260
261    return EINA_TRUE;
262 }
263
264 /* local subsystem functions */
265 static Eina_Bool
266 _angle_get(E_Comp_Win *cw,
267            int        *req,
268            int        *curr)
269 {
270    E_CHECK_RETURN(cw->bd, 0);
271    E_CHECK_RETURN(req, 0);
272    E_CHECK_RETURN(curr, 0);
273
274    *req  = cw->bd->client.e.state.rot.prev;
275    *curr = cw->bd->client.e.state.rot.curr;
276
277    return EINA_TRUE;
278 }
279
280 static Elm_Transit_Effect *
281 _effect_zone_rot_begin_new(E_Comp_Layer *ly)
282 {
283    E_Comp_Zone_Rotation_Effect_Begin *ctx= E_NEW(E_Comp_Zone_Rotation_Effect_Begin, 1);
284    E_CHECK_RETURN(ctx, NULL);
285
286    E_Zone *zone = ly->canvas->zone;
287
288    /* capture the screen */
289    Ecore_X_Window_Attributes att;
290    Ecore_X_Window root = ecore_x_window_root_first_get();
291    memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
292    if (!ecore_x_window_attributes_get(root, &att))
293      {
294         E_FREE(ctx);
295         return NULL;
296      }
297
298    ctx->xim = ecore_x_image_new(zone->w, zone->h, att.visual, att.depth);
299    if (!ctx->xim)
300      {
301         E_FREE(ctx);
302         return NULL;
303      }
304
305    unsigned int *pix = ecore_x_image_data_get(ctx->xim, NULL, NULL, NULL);;
306    ELBF(ELBT_COMP, 0, 0, "%15.15s|root:0x%08x vis:%p depth:%d xim:%p pix:%p", "ZONE_ROT_B_NEW",
307         root, att.visual, att.depth, ctx->xim, pix);
308
309    ctx->img = evas_object_image_filled_add(evas_object_evas_get(ly->layout));
310    evas_object_image_colorspace_set(ctx->img, EVAS_COLORSPACE_ARGB8888);
311    evas_object_image_alpha_set(ctx->img, 0);
312    evas_object_image_size_set(ctx->img, zone->w, zone->h);
313    evas_object_image_smooth_scale_set(ctx->img, EINA_FALSE);
314    evas_object_image_data_set(ctx->img, pix);
315    evas_object_image_data_update_add(ctx->img, 0, 0, zone->w, zone->h);
316
317    // why do we neeed these 2? this smells wrong
318    if (ecore_x_image_get(ctx->xim, root, 0, 0, 0, 0, zone->w, zone->h))
319      {
320         pix = ecore_x_image_data_get(ctx->xim, NULL, NULL, NULL);;
321         evas_object_image_data_set(ctx->img, pix);
322         evas_object_image_data_update_add(ctx->img, 0, 0, zone->w, zone->h);
323      }
324    evas_object_show(ctx->img);
325
326    e_mod_comp_layer_populate(ly, ctx->img);
327    e_layout_child_move(ctx->img, 0, 0);
328    e_layout_child_resize(ctx->img, zone->w, zone->h);
329
330    ctx->o = ly->layout;
331    ctx->zone = ly->canvas->zone;
332    ctx->ly = ly;
333
334    int diff = zone->rot.prev - zone->rot.curr;
335    if (diff == 270) diff = -90;
336    else if (diff == -270) diff = 90;
337    ctx->src = 0.0;
338    ctx->target = diff;
339    ELBF(ELBT_COMP, 0, 0, "%15.15s|%d->%d pix:%p", "ZONE_ROT_B_NEW", zone->rot.prev, zone->rot.curr, pix);
340    return ctx;
341 }
342
343 static Elm_Transit_Effect *
344 _effect_zone_rot_end_new(Evas_Object *o,
345                          E_Zone      *zone)
346 {
347    E_Comp_Zone_Rotation_Effect_End *ctx= E_NEW(E_Comp_Zone_Rotation_Effect_End, 1);
348    E_CHECK_RETURN(ctx, NULL);
349
350    ctx->o = o;
351    ctx->zone = zone;
352    int diff = zone->rot.curr - zone->rot.prev;
353    if (diff == 270) diff = -90;
354    else if (diff == -270) diff = 90;
355    ctx->src = diff;
356    ctx->target = 0.0;
357    ELBF(ELBT_COMP, 0, 0, "%15.15s|%d->%d", "ZONE_ROTATION_EFFECT_END_NEW", zone->rot.prev, zone->rot.curr);
358    return ctx;
359 }
360
361 static void
362 _effect_zone_rot_begin_free(Elm_Transit_Effect *effect,
363                             Elm_Transit        *transit)
364 {
365    E_Comp_Zone_Rotation_Effect_Begin *ctx = (E_Comp_Zone_Rotation_Effect_Begin *)effect;
366    if (ctx->xim) ecore_x_image_free(ctx->xim);
367    if (ctx->img)
368      {
369         evas_object_hide(ctx->img);
370         e_layout_unpack(ctx->img);
371         evas_object_del(ctx->img);
372      }
373    //evas_object_color_set(ctx->o, 255, 255, 255, 255);
374
375    e_mod_comp_layer_effect_set(ctx->ly, EINA_FALSE);
376
377    E_FREE(ctx);
378 }
379
380 static void
381 _effect_zone_rot_end_free(Elm_Transit_Effect *effect,
382                           Elm_Transit        *transit)
383 {
384    E_Comp_Zone_Rotation_Effect_End *ctx = (E_Comp_Zone_Rotation_Effect_End *)effect;
385    e_zone_rotation_block_set(ctx->zone, "comp-tizen", EINA_FALSE);
386    evas_object_color_set(ctx->o, 255, 255, 255, 255);
387    ELBF(ELBT_COMP, 0, 0, "%15.15s|", "ZONE_ROTATION_EFFECT_END_FREE");
388    E_FREE(ctx);
389 }
390
391 static void
392 _effect_zone_rot_begin_op(Elm_Transit_Effect *effect,
393                           Elm_Transit        *transit,
394                           double              progress)
395 {
396    E_Comp_Zone_Rotation_Effect_Begin *ctx = (E_Comp_Zone_Rotation_Effect_Begin *)effect;
397    double curr = (progress * ctx->target);
398    Evas_Coord x, y, w, h;
399
400    double col = 255 - (255 * progress * 1.3);
401    if (col <= 0) col = 0;
402    evas_object_color_set(ctx->o, col, col, col, col);
403
404    int diff = ctx->zone->h - ctx->zone->w;
405    Evas_Coord _x = -1.0 * (diff * progress) / 2;
406    Evas_Coord _y = (diff * progress) / 2;
407    Evas_Coord _w = ctx->zone->w + (diff * progress);
408    Evas_Coord _h = ctx->zone->h - (diff * progress);
409    evas_object_move(ctx->o, _x, _y);
410    evas_object_resize(ctx->o, _w, _h);
411    evas_object_geometry_get(ctx->o, &x, &y, &w, &h);
412
413    Evas_Map *m = evas_map_new(4);
414    evas_map_util_points_populate_from_object(m, ctx->o);
415    evas_map_util_rotate(m, curr, x + (w/2), y + (h/2));
416    evas_object_map_set(ctx->o, m);
417    evas_object_map_enable_set(ctx->o, EINA_TRUE);
418    evas_map_free(m);
419
420 }
421
422 static void
423 _effect_zone_rot_end_op(Elm_Transit_Effect *effect,
424                         Elm_Transit        *transit,
425                         double              progress)
426 {
427    E_Comp_Zone_Rotation_Effect_End *ctx = (E_Comp_Zone_Rotation_Effect_End *)effect;
428    double curr = ((-1.0f * progress * ctx->src) + ctx->src);
429    Evas_Coord x, y, w, h;
430
431    double col = 100 + 155 * progress;
432    evas_object_color_set(ctx->o, col, col, col, 255);
433
434    evas_object_geometry_get(ctx->o, &x, &y, &w, &h);
435
436    Evas_Map *m = evas_map_new(4);
437    evas_map_util_points_populate_from_object(m, ctx->o);
438    evas_map_util_rotate(m, curr, x + (w/2), y + (h/2));
439    evas_object_map_set(ctx->o, m);
440    evas_object_map_enable_set(ctx->o, EINA_TRUE);
441    evas_map_free(m);
442 }