tizen 2.4 release
[framework/uifw/e17-mod-tizen-comp.git] / src / e_mod_comp_win_shape_input.c
1 #include "e_mod_comp_shared_types.h"
2 #include "e_mod_comp_debug.h"
3 #include <pixman.h>
4
5 // input shape geometry (used on Move Module,
6 // Compositor receives input evevnt from this region.)
7 struct _E_Comp_Win_Shape_Input
8 {
9    int x, y, w, h;
10 };
11
12 struct _E_Comp_Shape_Input
13 {
14    int id;
15    int x, y, w, h;
16    Eina_Bool managed;
17    Eina_Bool skip;
18 };
19
20 /* local subsystem functions */
21 static int
22 _e_mod_comp_shape_input_new_id_get(E_Comp *c)
23 {
24    int new_id = 1;
25    E_Comp_Shape_Input *shape_input = NULL;
26    Eina_List *l = NULL;
27    Eina_Bool create_id = EINA_FALSE;
28
29    E_CHECK_RETURN(c, 0);
30
31    while (new_id < INT_MAX)
32      {
33         create_id = EINA_TRUE;
34
35         EINA_LIST_FOREACH(c->shape_inputs, l, shape_input)
36           {
37              if (shape_input->id == new_id)
38                {
39                   new_id++;
40                   create_id = EINA_FALSE;
41                   break;
42                }
43            }
44
45         if (create_id) break;
46      }
47
48    if (create_id) return new_id;
49    else return 0;
50 }
51
52 /* externally accessible functions */
53 EAPI int
54 e_mod_comp_shape_input_new(E_Comp *c)
55 {
56    int id = 0;
57    E_Comp_Shape_Input *shape_input;
58    E_CHECK_RETURN(c, 0);
59
60    id = _e_mod_comp_shape_input_new_id_get(c);
61    if (id)
62      {
63         shape_input = E_NEW(E_Comp_Shape_Input, 1);
64         E_CHECK_RETURN(shape_input, 0);
65
66         shape_input->id = id;
67         c->shape_inputs = eina_list_append(c->shape_inputs, shape_input);
68      }
69    return id;
70 }
71
72 EAPI Eina_Bool
73 e_mod_comp_shape_input_set(E_Comp *c,
74                            int     id,
75                            int     x,
76                            int     y,
77                            int     w,
78                            int     h)
79 {
80    Eina_Bool found = EINA_FALSE;
81    E_Comp_Shape_Input *shape_input = NULL;
82    Eina_List *l = NULL;
83
84    E_CHECK_RETURN(c, EINA_FALSE);
85    if ( id <= 0 ) return EINA_FALSE;
86
87    EINA_LIST_FOREACH(c->shape_inputs, l, shape_input)
88      {
89         if (shape_input->id == id)
90           {
91              shape_input->x = x;
92              shape_input->y = y;
93              shape_input->w = w;
94              shape_input->h = h;
95              found = EINA_TRUE;
96              break;
97           }
98      }
99
100    return found;
101 }
102
103 EAPI Eina_Bool
104 e_mod_comp_shape_input_del(E_Comp *c,
105                            int     id)
106 {
107    E_Comp_Shape_Input *shape_input = NULL;
108    E_Comp_Shape_Input *find_shape_input = NULL;
109    Eina_List *l = NULL;
110    Eina_Bool found = EINA_FALSE;
111
112    E_CHECK_RETURN(c, EINA_FALSE);
113    if ( id <= 0 ) return EINA_FALSE;
114
115    EINA_LIST_FOREACH(c->shape_inputs, l, shape_input)
116      {
117         if (shape_input->id == id)
118           {
119              find_shape_input = shape_input;
120              found = EINA_TRUE;
121              break;
122           }
123      }
124
125    if (find_shape_input)
126      {
127         c->shape_inputs = eina_list_remove(c->shape_inputs, find_shape_input);
128         memset(find_shape_input, 0, sizeof(E_Comp_Shape_Input));
129         E_FREE(find_shape_input);
130      }
131
132    return found;
133 }
134
135 EAPI Eina_Bool
136 e_mod_comp_win_shape_input_update(E_Comp *c)
137 {
138    E_Comp_Win *_cw = NULL;
139    Eina_List *l = NULL;
140    E_Comp_Canvas *canvas = NULL;
141    E_Comp_Shape_Input *shape_input = NULL;
142
143    pixman_region32_t vis_part;
144    pixman_region32_t win_part;
145    pixman_region32_t cur_part;
146    pixman_region32_t res_part;
147
148    pixman_region32_t input_part;
149    pixman_region32_t cur_input_part;
150    pixman_region32_t res_input_part;
151    pixman_region32_t sum_input_part;
152    pixman_region32_t comp_input_part;
153
154    pixman_box32_t *input_rects;
155
156    Ecore_X_Rectangle *input_shape_rects = NULL;
157
158    int num_rects = 0;
159    int num_input_rects = 0;
160    int i = 0;
161
162    pixman_box32_t screen_rect;
163    pixman_box32_t window_rect;
164    pixman_box32_t input_rect;
165
166    E_CHECK_RETURN(c, EINA_FALSE);
167    if (c->eff_img)
168      {
169         Eina_Bool res = c->effect_funcs.image_launch_running_check(c->eff_img);
170         E_CHECK_RETURN(!res, EINA_FALSE);
171      }
172
173 #if 0
174    E_CHECK_RETURN(c->need_shape_merge, EINA_FALSE);
175 #endif
176
177    screen_rect.x1 = 0;
178    screen_rect.y1 = 0;
179    screen_rect.x2 = c->man->w;
180    screen_rect.y2 = c->man->h;
181
182    pixman_region32_init_rects(&vis_part, &screen_rect, 1);
183    pixman_region32_init_rect(&sum_input_part, 0, 0, 0, 0);
184
185    EINA_INLIST_REVERSE_FOREACH(c->wins, _cw)
186      {
187         if ((!_cw->visible) || (_cw->defer_hide) ||
188             (_cw->invalid)  ||
189             (!E_INTERSECTS(0, 0, c->man->w, c->man->h,
190                            _cw->x, _cw->y, _cw->w, _cw->h)))
191           {
192              continue;
193           }
194         if (TYPE_DEBUGGING_INFO_CHECK(_cw)) continue;
195
196         num_rects = 0;
197
198         window_rect.x1 = _cw->x;
199         window_rect.y1 = _cw->y;
200         window_rect.x2 = window_rect.x1 + _cw->w;
201         window_rect.y2 = window_rect.y1 + _cw->h;
202
203         if (_cw->shape_input)
204           {
205              input_rect.x1 = window_rect.x1 + _cw->shape_input->x;
206              input_rect.y1 = window_rect.y1 + _cw->shape_input->y;
207              input_rect.x2 = input_rect.x1 + _cw->shape_input->w;
208              input_rect.y2 = input_rect.y1 + _cw->shape_input->h;
209           }
210         else
211           {
212              input_rect.x1 = window_rect.x1;
213              input_rect.y1 = window_rect.y1;
214              input_rect.x2 = input_rect.x1;
215              input_rect.y2 = input_rect.y1;
216           }
217
218         pixman_region32_init_rects(&input_part, &input_rect, 1);
219         pixman_region32_init_rect(&cur_input_part, 0, 0, 0, 0);
220         pixman_region32_init_rect(&res_input_part, 0, 0, 0, 0);
221         pixman_region32_init_rect(&cur_part,       0, 0, 0, 0);
222         pixman_region32_init_rects(&win_part, &window_rect, 1);
223         pixman_region32_init_rects(&res_part, &screen_rect, 1);
224
225         // current_visible_window = window (intersect) screen visible part
226         pixman_region32_intersect(&cur_part, &win_part, &vis_part);
227
228         // current_input = current_visible_window (intersect) input
229         pixman_region32_intersect(&cur_input_part, &cur_part, &input_part);
230
231         // result_input = sum_input
232         // sum_input = result_input + current_input
233         pixman_region32_copy(&res_input_part, &sum_input_part);
234         pixman_region32_union(&sum_input_part, &res_input_part, &cur_input_part);
235
236         // result = visible - window
237         pixman_region32_subtract(&res_part, &vis_part, &win_part);
238         pixman_region32_rectangles(&res_part, &num_rects);
239
240         pixman_region32_fini(&input_part);
241         pixman_region32_fini(&cur_input_part);
242         pixman_region32_fini(&res_input_part);
243         pixman_region32_fini(&cur_part);
244         pixman_region32_fini(&win_part);
245
246         if (num_rects == 0)
247           {
248              pixman_region32_fini(&res_part);
249              break;
250           }
251
252         pixman_region32_copy(&vis_part, &res_part);
253         pixman_region32_fini(&res_part);
254      }
255
256    e_mod_comp_shape_input_manage(c);
257
258    EINA_LIST_FOREACH(c->shape_inputs, l, shape_input)
259      {
260         if ((shape_input->managed) && (shape_input->skip))
261           continue;
262         if (E_INTERSECTS(0, 0, c->man->w, c->man->h,
263                          shape_input->x, shape_input->y,
264                          shape_input->w, shape_input->h))
265           {
266              pixman_region32_init_rect(&comp_input_part,
267                                        shape_input->x,
268                                        shape_input->y,
269                                        shape_input->w,
270                                        shape_input->h);
271              pixman_region32_init_rect(&res_input_part, 0, 0, 0, 0);
272
273              pixman_region32_copy(&res_input_part, &sum_input_part);
274              pixman_region32_union(&sum_input_part, &res_input_part, &comp_input_part);
275
276              pixman_region32_fini(&res_input_part);
277              pixman_region32_fini(&comp_input_part);
278           }
279      }
280
281    input_rects = pixman_region32_rectangles(&sum_input_part, &num_input_rects);
282
283    if (num_input_rects)
284      {
285         input_shape_rects = E_NEW(Ecore_X_Rectangle, num_input_rects);
286         if (input_shape_rects)
287           {
288              for (i = 0; i < num_input_rects; i++)
289                {
290                   input_shape_rects[i].x = input_rects[i].x1;
291                   input_shape_rects[i].y = input_rects[i].y1;
292                   input_shape_rects[i].width = input_rects[i].x2 - input_rects[i].x1;
293                   input_shape_rects[i].height = input_rects[i].y2 - input_rects[i].y1;
294                }
295           }
296
297         if (_comp_mod->conf->nocomp_fs)
298           {
299              /* set shape before setting shape input */
300              EINA_LIST_FOREACH(c->canvases, l, canvas)
301                {
302                   if ((canvas) &&
303                       (canvas->nocomp.mode == E_NOCOMP_MODE_RUN))
304                     {
305                        ecore_x_window_shape_rectangles_set
306                          (c->win, input_shape_rects, num_input_rects);
307                        break;
308                     }
309                }
310
311              /* FIXME: this code causes compositor couldn't update center region during composite state and software backend.
312                 so, disable for now.
313                 we have to ask someone who wrote this code what purpose of this code,
314                 so that we can fix it appropriately. */
315 #if 0
316              /* for the xv */
317              if ((input_shape_rects) && (num_input_rects == 1))
318                {
319                   canvas = (E_Comp_Canvas *)eina_list_nth(c->canvases, 0);
320                   if ((canvas) &&
321                       (input_shape_rects[0].x == canvas->x) &&
322                       (input_shape_rects[0].y == canvas->y) &&
323                       (input_shape_rects[0].width == canvas->w) &&
324                       (input_shape_rects[0].height == canvas->h))
325                     {
326                        ecore_x_window_shape_rectangle_subtract(c->win,
327                                                                (canvas->w / 2) - 16,
328                                                                (canvas->h / 2) - 16,
329                                                                16, 16);
330                     }
331                }
332 #endif
333           }
334
335         ecore_x_window_shape_input_rectangles_set(c->win,
336                                                   input_shape_rects,
337                                                   num_input_rects);
338         if (input_shape_rects) E_FREE(input_shape_rects);
339      }
340    else
341      {
342         ecore_x_window_shape_input_rectangle_set(c->win, -1, -1, 1, 1);
343      }
344
345    pixman_region32_fini(&vis_part);
346    pixman_region32_fini(&sum_input_part);
347
348    c->need_shape_merge = EINA_FALSE;
349    return EINA_TRUE;
350 }
351
352 EAPI E_Comp_Win_Shape_Input *
353 e_mod_comp_win_shape_input_new(E_Comp_Win *cw)
354 {
355    Eina_List *l;
356    E_Comp_Object *co;
357
358    E_CHECK_RETURN(cw, 0);
359
360    EINA_LIST_FOREACH(cw->objs, l, co)
361      {
362         if (!co->img) return NULL;
363         if (!co->shadow) return NULL;
364      }
365
366    EINA_LIST_FOREACH(cw->objs, l, co)
367      {
368         evas_object_pass_events_set(co->img, EINA_FALSE);
369         evas_object_pass_events_set(co->shadow, EINA_FALSE);
370      }
371
372    return E_NEW(E_Comp_Win_Shape_Input, 1);
373 }
374
375 EAPI void
376 e_mod_comp_win_shape_input_free(E_Comp_Win_Shape_Input *input)
377 {
378    E_CHECK(input);
379    E_FREE(input);
380 }
381
382 EAPI Eina_Bool
383 e_mod_comp_win_shape_input_rect_set(E_Comp_Win_Shape_Input *input,
384                                     int                     x,
385                                     int                     y,
386                                     int                     w,
387                                     int                     h)
388 {
389    E_CHECK_RETURN(input, EINA_FALSE);
390
391    if (((input->x == x) && (input->y == y) &&
392         (input->w == w) && (input->h == h)))
393      {
394         return EINA_FALSE;
395      }
396
397    input->x = x;
398    input->y = y;
399    input->w = w;
400    input->h = h;
401
402    return EINA_TRUE;
403 }
404
405 EAPI Eina_Bool
406 e_mod_comp_win_shape_input_invalid_set(E_Comp    *c,
407                                        Eina_Bool  set)
408 {
409    E_CHECK_RETURN(c, EINA_FALSE);
410    c->need_shape_merge = set;
411    return EINA_TRUE;
412 }
413
414 EAPI void
415 e_mod_comp_shape_input_manage(E_Comp *c)
416 {
417    E_Comp_Shape_Input *shape_input;
418    Eina_List *l, *ll, *lm;
419    Evas_Object *o, *oo, *layout;
420    E_Comp_Layer *comp_ly, *ctrl_ly;
421    E_Comp_Canvas *canvas;
422    Eina_Bool hidden = EINA_FALSE;
423    int x = 0, y = 0, w = 0, h = 0;
424    int _x = 0, _y = 0, _w = 0, _h = 0;
425    int num_rects = 0;
426
427    pixman_region32_t target_part;
428    pixman_region32_t cur_part;
429    pixman_region32_t res_part;
430    pixman_box32_t *rects = NULL;
431
432    canvas = eina_list_nth(c->canvases, 0);
433    comp_ly = e_mod_comp_canvas_layer_get(canvas, "comp");
434    E_CHECK(comp_ly);
435
436    ctrl_ly = e_mod_comp_canvas_layer_get(canvas, "ly-ctrl");
437    E_CHECK(ctrl_ly);
438
439    EINA_LIST_FOREACH(c->shape_inputs_mo, l, o)
440      {
441         if (!evas_object_visible_get(o)) continue;
442
443         hidden = EINA_FALSE;
444
445         /*TODO: find layout of objects */
446         layout = ctrl_ly->layout;
447
448         evas_object_geometry_get(o, &x, &y, &w, &h);
449
450         pixman_region32_init_rect(&target_part, x, y, w, h);
451         pixman_region32_init_rect(&res_part, x, y, w, h);
452
453         num_rects = 0;
454         rects = NULL;
455
456         lm = evas_object_smart_members_get(comp_ly->layout);
457         EINA_LIST_REVERSE_FOREACH(lm, ll, oo)
458           {
459              if (!evas_object_visible_get(oo)) continue;
460              if ((oo == o) || ((oo == layout)))
461                break;
462
463              evas_object_geometry_get(oo, &_x, &_y, &_w, &_h);
464
465              //clipper
466              if (_x == -100001) continue;
467              if (!E_INTERSECTS(x, y, w, h, _x, _y, _w, _h))  continue;
468
469              pixman_region32_copy(&target_part, &res_part);
470              pixman_region32_init_rect(&cur_part, _x, _y, _w, _h);
471              pixman_region32_subtract(&res_part, &target_part, &cur_part);
472              pixman_region32_fini(&cur_part);
473
474              rects = pixman_region32_rectangles(&res_part, &num_rects);
475
476              if (num_rects == 0)
477                {
478                   hidden = EINA_TRUE;
479                   break;
480                }
481           }
482         if (lm) eina_list_free(lm);
483
484         if ((rects) && (num_rects == 1))
485           {
486              if (((rects[0].x2 - rects[0].x1) >= w/2) &&
487                  ((rects[0].y2 - rects[0].y1) >= h/2))
488                {
489                   x = rects[0].x1;
490                   y = rects[0].y1;
491                   w = rects[0].x2 - rects[0].x1;
492                   h = rects[0].y2 - rects[0].y1;
493
494                   hidden = EINA_FALSE;
495                }
496              else
497                hidden = EINA_TRUE;
498           }
499         else if ((rects) && (num_rects >=2))
500           {
501              if ((((rects[0].x2 - rects[0].x1) >= w/2)  &&
502                   ((rects[0].y2 - rects[0].y1) >= h/2)) ||
503                  (((rects[1].x2 - rects[1].x1) >= w/2)  &&
504                   ((rects[1].y2 - rects[1].y1) >= h/2)))
505                hidden = EINA_FALSE;
506              else
507                hidden = EINA_TRUE;
508           }
509
510         shape_input = evas_object_data_get(o, "e_shape_input_managed_data");
511         if (shape_input)
512           {
513              if (hidden)
514                {
515                   shape_input->skip = EINA_TRUE;
516                   shape_input->x = -1;
517                   shape_input->y = -1;
518                   shape_input->w = 1;
519                   shape_input->h = 1;
520                }
521              else
522                {
523                   shape_input->skip = EINA_FALSE;
524                   shape_input->x = x;
525                   shape_input->y = y;
526                   shape_input->w = w;
527                   shape_input->h = h;
528                }
529           }
530         pixman_region32_fini(&target_part);
531         pixman_region32_fini(&res_part);
532      }
533 }
534
535 EAPI Eina_Bool
536 e_mod_comp_shape_input_managed_set(E_Comp         *c,
537                                    int             id,
538                                    Evas_Object    *obj,
539                                    Eina_Bool       set)
540 {
541    Eina_Bool found = EINA_FALSE;
542    E_Comp_Shape_Input *shape_input = NULL;
543    E_Comp_Shape_Input *find_shape_input = NULL;
544    Eina_List *l = NULL;
545
546    E_CHECK_RETURN(c, EINA_FALSE);
547    if (id <= 0) return EINA_FALSE;
548
549    EINA_LIST_FOREACH(c->shape_inputs, l, shape_input)
550      {
551         if (shape_input->id == id)
552           {
553              found = EINA_TRUE;
554              find_shape_input = shape_input;
555              break;
556           }
557      }
558
559    if (find_shape_input)
560      {
561         find_shape_input->managed = set;
562         if (set)
563           {
564              evas_object_data_set(obj, "e_shape_input_managed_data", find_shape_input);
565              c->shape_inputs_mo = eina_list_append(c->shape_inputs_mo, obj);
566           }
567         else
568           {
569              evas_object_data_del(obj, "e_shape_input_managed_data");
570              c->shape_inputs_mo = eina_list_remove(c->shape_inputs_mo, obj);
571           }
572      }
573
574    return found;
575 }
576