ef326869fa67e7c5c156141c454694198e9b6347
[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;
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)) _bd = cw2->bd;
123                }
124              else
125                _bd = bd;
126
127              if (_bd)
128                {
129                   if ((_bd->client.icccm.name) && (_bd->client.icccm.class))
130                     {
131                        if ((!strcmp(_bd->client.icccm.name, "camera")) &&
132                            (!strcmp(_bd->client.icccm.class, "camera")))
133                          {
134                             ELB(ELBT_COMP, "SKIP CAMERA", _bd->client.win);
135                             return EINA_FALSE;
136                          }
137                        else if (!strcmp(_bd->client.icccm.name, "video_play"))
138                          {
139                             ELB(ELBT_COMP, "SKIP VIDEO PLAYER", _bd->client.win);
140                             return EINA_FALSE;
141                          }
142                        if ((!strcmp(_bd->client.icccm.name, "LOCK_SCREEN")) &&
143                            (!strcmp(_bd->client.icccm.class, "LOCK_SCREEN")))
144                          {
145                             ELB(ELBT_COMP, "SKIP LOCK_SCREEN", _bd->client.win);
146                             return EINA_FALSE;
147                          }
148                     }
149                }
150           }
151      }
152
153    ly = e_mod_comp_canvas_layer_get(zr->canvas, "effect");
154    if (ly)
155      {
156         /* TODO: check animation is running */
157         if (zr->trans_begin) elm_transit_del(zr->trans_begin);
158         if (zr->trans_end) elm_transit_del(zr->trans_end);
159         zr->trans_begin = NULL;
160         zr->trans_end = NULL;
161
162         zr->trans_begin = elm_transit_add();
163
164         zr->effect_begin = _effect_zone_rot_begin_new(ly);
165         if (!zr->effect_begin)
166           {
167              if (zr->trans_begin) elm_transit_del(zr->trans_begin);
168              zr->trans_begin = NULL;
169              zr->ready = EINA_FALSE;
170              return EINA_FALSE;
171           }
172         elm_transit_object_add(zr->trans_begin, ly->layout);
173         elm_transit_smooth_set(zr->trans_begin, EINA_FALSE);
174         elm_transit_duration_set(zr->trans_begin, 0.4f);
175         elm_transit_effect_add(zr->trans_begin, _effect_zone_rot_begin_op, zr->effect_begin, _effect_zone_rot_begin_free);
176         elm_transit_tween_mode_set(zr->trans_begin, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
177         elm_transit_objects_final_state_keep_set(zr->trans_begin, EINA_FALSE);
178
179         e_mod_comp_layer_effect_set(ly, EINA_TRUE);
180
181         zr->ready = EINA_TRUE;
182      }
183
184    return EINA_TRUE;
185 }
186
187 EINTERN Eina_Bool
188 e_mod_comp_effect_zone_rotation_end(E_Comp_Effect_Zone_Rotation *zr)
189 {
190    E_Comp_Layer *ly;
191    E_Comp *c = e_mod_comp_util_get();
192
193    E_CHECK_RETURN(c->animatable, EINA_FALSE);
194    E_CHECK_RETURN(zr->ready, EINA_FALSE);
195    E_CHECK_RETURN(zr->trans_begin, EINA_FALSE);
196
197    zr->ready = EINA_FALSE;
198
199    ly = e_mod_comp_canvas_layer_get(zr->canvas, "comp");
200    if (ly)
201      {
202         if (zr->trans_end) elm_transit_del(zr->trans_end);
203         zr->trans_end = NULL;
204
205         zr->trans_end = elm_transit_add();
206         zr->effect_end = _effect_zone_rot_end_new(ly->layout, zr->canvas->zone);
207         elm_transit_object_add(zr->trans_end, ly->layout);
208         elm_transit_smooth_set(zr->trans_end, EINA_FALSE);
209         elm_transit_duration_set(zr->trans_end, 0.4f);
210         elm_transit_effect_add(zr->trans_end, _effect_zone_rot_end_op, zr->effect_end, _effect_zone_rot_end_free);
211         elm_transit_tween_mode_set(zr->trans_end, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
212         elm_transit_objects_final_state_keep_set(zr->trans_end, EINA_FALSE);
213
214         e_zone_rotation_block_set(zr->canvas->zone, "comp-tizen", EINA_TRUE);
215
216         return EINA_TRUE;
217      }
218
219    return EINA_FALSE;
220 }
221
222 EINTERN Eina_Bool
223 e_mod_comp_effect_zone_rotation_cancel(E_Comp_Effect_Zone_Rotation *zr)
224 {
225    if (zr->trans_begin)
226      {
227         elm_transit_del(zr->trans_begin);
228         zr->trans_begin = NULL;
229      }
230    if (zr->trans_end)
231      {
232         elm_transit_del(zr->trans_end);
233         zr->trans_end = NULL;
234      }
235    zr->ready = EINA_FALSE;
236
237    return EINA_TRUE;
238 }
239
240 EINTERN Eina_Bool
241 e_mod_comp_effect_zone_rotation_do(E_Comp_Effect_Zone_Rotation *zr)
242 {
243    E_Comp *c = e_mod_comp_util_get();
244    E_CHECK_RETURN(c->animatable, EINA_FALSE);
245
246    elm_transit_go(zr->trans_begin);
247    elm_transit_go(zr->trans_end);
248
249    return EINA_TRUE;
250 }
251
252 /* local subsystem functions */
253 static Eina_Bool
254 _angle_get(E_Comp_Win *cw,
255            int        *req,
256            int        *curr)
257 {
258    E_CHECK_RETURN(cw->bd, 0);
259    E_CHECK_RETURN(req, 0);
260    E_CHECK_RETURN(curr, 0);
261
262    *req  = cw->bd->client.e.state.rot.prev;
263    *curr = cw->bd->client.e.state.rot.curr;
264
265    return EINA_TRUE;
266 }
267
268 static Elm_Transit_Effect *
269 _effect_zone_rot_begin_new(E_Comp_Layer *ly)
270 {
271    E_Comp_Zone_Rotation_Effect_Begin *ctx= E_NEW(E_Comp_Zone_Rotation_Effect_Begin, 1);
272    E_CHECK_RETURN(ctx, NULL);
273
274    E_Zone *zone = ly->canvas->zone;
275
276    /* capture the screen */
277    Ecore_X_Window_Attributes att;
278    Ecore_X_Window root = ecore_x_window_root_first_get();
279    memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
280    if (!ecore_x_window_attributes_get(root, &att))
281      {
282         E_FREE(ctx);
283         return NULL;
284      }
285
286    ctx->xim = ecore_x_image_new(zone->w, zone->h, att.visual, att.depth);
287    if (!ctx->xim)
288      {
289         E_FREE(ctx);
290         return NULL;
291      }
292
293    unsigned int *pix = ecore_x_image_data_get(ctx->xim, NULL, NULL, NULL);;
294    ELBF(ELBT_COMP, 0, 0, "%15.15s|root:0x%08x vis:%p depth:%d xim:%p pix:%p", "ZONE_ROT_B_NEW",
295         root, att.visual, att.depth, ctx->xim, pix);
296
297    ctx->img = evas_object_image_filled_add(evas_object_evas_get(ly->layout));
298    evas_object_image_colorspace_set(ctx->img, EVAS_COLORSPACE_ARGB8888);
299    evas_object_image_alpha_set(ctx->img, 0);
300    evas_object_image_size_set(ctx->img, zone->w, zone->h);
301    evas_object_image_smooth_scale_set(ctx->img, EINA_FALSE);
302    evas_object_image_data_set(ctx->img, pix);
303    evas_object_image_data_update_add(ctx->img, 0, 0, zone->w, zone->h);
304
305    // why do we neeed these 2? this smells wrong
306    if (ecore_x_image_get(ctx->xim, root, 0, 0, 0, 0, zone->w, zone->h))
307      {
308         pix = ecore_x_image_data_get(ctx->xim, NULL, NULL, NULL);;
309         evas_object_image_data_set(ctx->img, pix);
310         evas_object_image_data_update_add(ctx->img, 0, 0, zone->w, zone->h);
311      }
312    evas_object_show(ctx->img);
313
314    e_mod_comp_layer_populate(ly, ctx->img);
315    e_layout_child_move(ctx->img, 0, 0);
316    e_layout_child_resize(ctx->img, zone->w, zone->h);
317
318    ctx->o = ly->layout;
319    ctx->zone = ly->canvas->zone;
320    ctx->ly = ly;
321
322    int diff = zone->rot.prev - zone->rot.curr;
323    if (diff == 270) diff = -90;
324    else if (diff == -270) diff = 90;
325    ctx->src = 0.0;
326    ctx->target = diff;
327    ELBF(ELBT_COMP, 0, 0, "%15.15s|%d->%d pix:%p", "ZONE_ROT_B_NEW", zone->rot.prev, zone->rot.curr, pix);
328    return ctx;
329 }
330
331 static Elm_Transit_Effect *
332 _effect_zone_rot_end_new(Evas_Object *o,
333                          E_Zone      *zone)
334 {
335    E_Comp_Zone_Rotation_Effect_End *ctx= E_NEW(E_Comp_Zone_Rotation_Effect_End, 1);
336    E_CHECK_RETURN(ctx, NULL);
337
338    ctx->o = o;
339    ctx->zone = zone;
340    int diff = zone->rot.curr - zone->rot.prev;
341    if (diff == 270) diff = -90;
342    else if (diff == -270) diff = 90;
343    ctx->src = diff;
344    ctx->target = 0.0;
345    ELBF(ELBT_COMP, 0, 0, "%15.15s|%d->%d", "ZONE_ROTATION_EFFECT_END_NEW", zone->rot.prev, zone->rot.curr);
346    return ctx;
347 }
348
349 static void
350 _effect_zone_rot_begin_free(Elm_Transit_Effect *effect,
351                             Elm_Transit        *transit)
352 {
353    E_Comp_Zone_Rotation_Effect_Begin *ctx = (E_Comp_Zone_Rotation_Effect_Begin *)effect;
354    if (ctx->xim) ecore_x_image_free(ctx->xim);
355    if (ctx->img)
356      {
357         evas_object_hide(ctx->img);
358         e_layout_unpack(ctx->img);
359         evas_object_del(ctx->img);
360      }
361    //evas_object_color_set(ctx->o, 255, 255, 255, 255);
362
363    e_mod_comp_layer_effect_set(ctx->ly, EINA_FALSE);
364
365    E_FREE(ctx);
366 }
367
368 static void
369 _effect_zone_rot_end_free(Elm_Transit_Effect *effect,
370                           Elm_Transit        *transit)
371 {
372    E_Comp_Zone_Rotation_Effect_End *ctx = (E_Comp_Zone_Rotation_Effect_End *)effect;
373    e_zone_rotation_block_set(ctx->zone, "comp-tizen", EINA_FALSE);
374    evas_object_color_set(ctx->o, 255, 255, 255, 255);
375    ELBF(ELBT_COMP, 0, 0, "%15.15s|", "ZONE_ROTATION_EFFECT_END_FREE");
376    E_FREE(ctx);
377 }
378
379 static void
380 _effect_zone_rot_begin_op(Elm_Transit_Effect *effect,
381                           Elm_Transit        *transit,
382                           double              progress)
383 {
384    E_Comp_Zone_Rotation_Effect_Begin *ctx = (E_Comp_Zone_Rotation_Effect_Begin *)effect;
385    double curr = (progress * ctx->target);
386    Evas_Coord x, y, w, h;
387
388    double col = 255 - (255 * progress * 1.3);
389    if (col <= 0) col = 0;
390    evas_object_color_set(ctx->o, col, col, col, col);
391
392    int diff = ctx->zone->h - ctx->zone->w;
393    Evas_Coord _x = -1.0 * (diff * progress) / 2;
394    Evas_Coord _y = (diff * progress) / 2;
395    Evas_Coord _w = ctx->zone->w + (diff * progress);
396    Evas_Coord _h = ctx->zone->h - (diff * progress);
397    evas_object_move(ctx->o, _x, _y);
398    evas_object_resize(ctx->o, _w, _h);
399    evas_object_geometry_get(ctx->o, &x, &y, &w, &h);
400
401    Evas_Map *m = evas_map_new(4);
402    evas_map_util_points_populate_from_object(m, ctx->o);
403    evas_map_util_rotate(m, curr, x + (w/2), y + (h/2));
404    evas_object_map_set(ctx->o, m);
405    evas_object_map_enable_set(ctx->o, EINA_TRUE);
406    evas_map_free(m);
407
408 }
409
410 static void
411 _effect_zone_rot_end_op(Elm_Transit_Effect *effect,
412                         Elm_Transit        *transit,
413                         double              progress)
414 {
415    E_Comp_Zone_Rotation_Effect_End *ctx = (E_Comp_Zone_Rotation_Effect_End *)effect;
416    double curr = ((-1.0f * progress * ctx->src) + ctx->src);
417    Evas_Coord x, y, w, h;
418
419    double col = 100 + 155 * progress;
420    evas_object_color_set(ctx->o, col, col, col, 255);
421
422    evas_object_geometry_get(ctx->o, &x, &y, &w, &h);
423
424    Evas_Map *m = evas_map_new(4);
425    evas_map_util_points_populate_from_object(m, ctx->o);
426    evas_map_util_rotate(m, curr, x + (w/2), y + (h/2));
427    evas_object_map_set(ctx->o, m);
428    evas_object_map_enable_set(ctx->o, EINA_TRUE);
429    evas_map_free(m);
430 }