Added a policy to support such as quickpanel to rotate based Window manager.
[platform/core/uifw/e17-extra-modules.git] / move-tizen / src / e_mod_move_indicator_widget.c
1 #include "e_mod_move_shared_types.h"
2 #include "e_mod_move_debug.h"
3 #include "e_mod_move.h"
4
5 /* local subsystem functions */
6 static Eina_Bool      _e_mod_move_indicator_widget_apptray_move_set(E_Move_Indicator_Widget *indi_widget, Eina_Bool state);
7 static Eina_Bool      _e_mod_move_indicator_widget_quickpanel_move_set(E_Move_Indicator_Widget *indi_widget, Eina_Bool state);
8 static Eina_Bool      _e_mod_move_indicator_widget_apptray_move_get(E_Move_Indicator_Widget *indi_widget);
9 static Eina_Bool      _e_mod_move_indicator_widget_quickpanel_move_get(E_Move_Indicator_Widget *indi_widget);
10 static Eina_Bool      _e_mod_move_indicator_widget_cb_motion_start_internal_apptray_check(E_Move_Border *at_mb);
11 static Eina_Bool      _e_mod_move_indicator_widget_cb_motion_start_internal_quickpanel_check(E_Move_Border *qp_mb);
12 static Eina_Bool      _e_mod_move_indicator_widget_quickpanel_flick_process(E_Move_Indicator_Widget *indi_widget, E_Move_Border *mb2, int angle, Eina_Bool state);
13 static Eina_Bool      _e_mod_move_indicator_widget_apptray_flick_process(E_Move_Indicator_Widget *indi_widget, E_Move_Border *mb2, int angle, Eina_Bool state);
14 static Eina_Bool      _e_mod_move_indicator_widget_home_region_release_check(E_Move_Indicator_Widget  *indi_widget, Eina_Bool apptray_move, int angle, Evas_Point pos);
15 static Eina_Bool      _e_mod_move_indicator_widget_cb_motion_start(void *data, void *event_info);
16 static Eina_Bool      _e_mod_move_indicator_widget_cb_motion_move(void *data, void *event_info);
17 static Eina_Bool      _e_mod_move_indicator_widget_cb_motion_end(void *data, void *event_info);
18 static void           _e_mod_move_indicator_widget_obj_event_setup(E_Move_Indicator_Widget *indicator_widget, E_Move_Widget_Object *mwo);
19 static Eina_Bool      _e_mod_move_indicator_widget_scrollable_object_movable_check(E_Move_Border *mb, Evas_Point pos);
20 static Eina_Bool      _e_mod_move_indicator_widget_target_window_find_by_pointer(Ecore_X_Window *win, int x, int y);
21 static Ecore_X_Window _e_mod_move_indicator_widget_event_win_find(void *event_info);
22 static Eina_Bool      _e_mod_move_indicator_widget_target_window_policy_check(E_Move_Border *mb);
23 static Eina_Bool      _e_mod_move_indicator_widget_event_send_policy_check(E_Move_Indicator_Widget *indi_widget, Evas_Point pos);
24
25 /* local subsystem functions */
26 static Eina_Bool
27 _e_mod_move_indicator_widget_apptray_move_set(E_Move_Indicator_Widget *indi_widget,
28                                               Eina_Bool                state)
29 {
30    E_CHECK_RETURN(indi_widget, EINA_FALSE);
31    indi_widget->apptray_move = state;
32    return EINA_TRUE;
33 }
34
35 static Eina_Bool
36 _e_mod_move_indicator_widget_quickpanel_move_set(E_Move_Indicator_Widget *indi_widget,
37                                                  Eina_Bool                state)
38 {
39    E_CHECK_RETURN(indi_widget, EINA_FALSE);
40    indi_widget->quickpanel_move = state;
41    return EINA_TRUE;
42 }
43
44 static Eina_Bool
45 _e_mod_move_indicator_widget_apptray_move_get(E_Move_Indicator_Widget *indi_widget)
46 {
47    E_CHECK_RETURN(indi_widget, EINA_FALSE);
48    return indi_widget->apptray_move;
49 }
50
51 static Eina_Bool
52 _e_mod_move_indicator_widget_quickpanel_move_get(E_Move_Indicator_Widget *indi_widget)
53 {
54    E_CHECK_RETURN(indi_widget, EINA_FALSE);
55    return indi_widget->quickpanel_move;
56 }
57
58 static Eina_Bool
59 _e_mod_move_indicator_widget_cb_motion_start_internal_apptray_check(E_Move_Border *at_mb)
60 {
61    E_Move        *m;
62    E_Move_Border *find_mb = NULL;
63    Eina_Bool      found = EINA_FALSE;
64    m = e_mod_move_util_get();
65
66    E_CHECK_RETURN(m, EINA_FALSE);
67    E_CHECK_RETURN(at_mb, EINA_FALSE);
68    E_CHECK_RETURN(TYPE_APPTRAY_CHECK(at_mb), EINA_FALSE);
69    E_CHECK_RETURN(at_mb->visible, EINA_FALSE);
70    E_CHECK_RETURN(e_mod_move_util_compositor_object_visible_get(at_mb),
71                   EINA_FALSE);
72    if (e_mod_move_apptray_objs_animation_state_get(at_mb)) return EINA_FALSE;
73
74    // check if notification window is on-screen.
75    EINA_INLIST_REVERSE_FOREACH(m->borders, find_mb)
76      {
77         if (TYPE_INDICATOR_CHECK(find_mb)) continue;
78         if (find_mb->visible
79              && REGION_INTERSECTS_WITH_ZONE(find_mb, at_mb->bd->zone))
80           {
81               found = EINA_TRUE;
82               break;
83           }
84      }
85    if (found
86         && (find_mb->bd->client.netwm.type == ECORE_X_WINDOW_TYPE_NOTIFICATION))
87      {
88         return EINA_FALSE;
89      }
90    // check if notification window is on-screen.
91
92    e_mod_move_apptray_dim_show(at_mb);
93    e_mod_move_apptray_objs_add(at_mb);
94
95    // apptray_objs_animation_layer_set
96    e_mod_move_apptray_objs_animation_layer_set(at_mb);
97
98    return EINA_TRUE;
99 }
100
101 static Eina_Bool
102 _e_mod_move_indicator_widget_cb_motion_start_internal_quickpanel_check(E_Move_Border *qp_mb)
103 {
104    E_CHECK_RETURN(qp_mb, EINA_FALSE);
105    E_CHECK_RETURN(TYPE_QUICKPANEL_CHECK(qp_mb), EINA_FALSE);
106    E_CHECK_RETURN(qp_mb->visible, EINA_FALSE);
107    E_CHECK_RETURN(e_mod_move_util_compositor_object_visible_get(qp_mb),
108                   EINA_FALSE);
109
110    // Quickpanel is under rotation state.
111    // I think there is another exception case.
112    // It's posible that WM doesn't send rotation change request yet.
113    // In this case the value of wait_for_done is zero,
114    // it means quickpanel isn't rotating for now, but going to be rotated.
115    if (qp_mb->bd)
116      if (qp_mb->bd->client.e.state.rot.wait_for_done) return EINA_FALSE;
117
118    if (e_mod_move_quickpanel_objs_animation_state_get(qp_mb)) return EINA_FALSE;
119
120    if (!(qp_mb->m->qp_scroll_with_clipping))
121      e_mod_move_quickpanel_dim_show(qp_mb);
122
123    // Set Composite Mode & Rotation Lock & Make below win's mirror object
124    e_mod_move_quickpanel_stage_init(qp_mb);
125
126    e_mod_move_quickpanel_objs_add(qp_mb);
127
128    return EINA_TRUE;
129 }
130
131 static Eina_Bool
132 _e_mod_move_indicator_widget_quickpanel_flick_process(E_Move_Indicator_Widget  *indi_widget,
133                                                       E_Move_Border            *mb2, // mb2 : quickpanel
134                                                       int                       angle,
135                                                       Eina_Bool                 state)
136 {
137    E_Move                   *m = NULL;
138    E_Move_Border            *mb = NULL;
139    E_Move_Widget_Object     *mwo = NULL;
140    Eina_List                *l;
141    E_Zone                   *zone = NULL;
142    int mx = 0, my = 0, ax = 0, ay = 0;
143
144    E_CHECK_RETURN(indi_widget, EINA_FALSE);
145    mb = e_mod_move_border_client_find(indi_widget->win);
146    E_CHECK_RETURN(mb, EINA_FALSE);
147    E_CHECK_RETURN(mb2, EINA_FALSE);
148    E_CHECK_RETURN(TYPE_QUICKPANEL_CHECK(mb2), EINA_FALSE);
149    E_CHECK_RETURN(state, EINA_FALSE);
150
151    m = mb->m;
152    zone = mb->bd->zone;
153
154    EINA_LIST_FOREACH(indi_widget->objs, l, mwo) // indicator click unset
155      {
156         if (!mwo) continue;
157         e_mod_move_event_click_set(mwo->event, EINA_FALSE);
158      }
159
160    _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_FALSE);
161    _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_FALSE);
162
163    // flick data free
164    if (mb->flick_data) e_mod_move_flick_data_free(mb);
165
166    switch (angle)
167      {
168       case  90:
169          mx = 0; my = 0;
170          if (m->qp_scroll_with_clipping)
171            {
172               ax = zone->x + mb2->w;
173               ay = zone->y + mb2->h;
174            }
175          else
176            {
177               ax = mx; ay = my;
178            }
179          break;
180       case 180:
181          mx = 0; my = zone->h - mb2->h;
182          if (m->qp_scroll_with_clipping)
183            {
184               ax = zone->x; ay = zone->y;
185            }
186          else
187            {
188               ax = mx; ay = my;
189            }
190          break;
191       case 270:
192          mx = zone->w - mb2->w; my = 0;
193          if (m->qp_scroll_with_clipping)
194            {
195               ax = zone->x; ay = zone->y;
196            }
197          else
198            {
199               ax = mx; ay = my;
200            }
201          break;
202       case   0:
203       default :
204          mx = 0; my = 0;
205          if (m->qp_scroll_with_clipping)
206            {
207               ax = zone->x + mb2->w;
208               ay = zone->y + mb2->h;
209            }
210          else
211            {
212               ax = mx; ay = my;
213            }
214          break;
215      }
216
217    e_mod_move_quickpanel_e_border_move(mb2, mx, my);
218    e_mod_move_quickpanel_objs_animation_move(mb2, ax, ay);
219
220    return EINA_TRUE;
221 }
222
223 static Eina_Bool
224 _e_mod_move_indicator_widget_apptray_flick_process(E_Move_Indicator_Widget *indi_widget,
225                                                    E_Move_Border           *mb2, // mb2 : apptray
226                                                    int                      angle,
227                                                    Eina_Bool                state)
228 {
229    E_Move_Border            *mb = NULL;
230    E_Move_Widget_Object     *mwo = NULL;
231    Eina_List                *l;
232    E_Zone                   *zone = NULL;
233    int x = 0;
234    int y = 0;
235
236    E_CHECK_RETURN(indi_widget, EINA_FALSE);
237    mb = e_mod_move_border_client_find(indi_widget->win);
238    E_CHECK_RETURN(mb, EINA_FALSE);
239    E_CHECK_RETURN(mb2, EINA_FALSE);
240    E_CHECK_RETURN(TYPE_APPTRAY_CHECK(mb2), EINA_FALSE);
241    E_CHECK_RETURN(state, EINA_FALSE);
242
243    zone = mb->bd->zone;
244
245    EINA_LIST_FOREACH(indi_widget->objs, l, mwo) // indicator click unset
246      {
247         if (!mwo) continue;
248         e_mod_move_event_click_set(mwo->event, EINA_FALSE);
249      }
250
251    _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_FALSE);
252    _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_FALSE);
253
254    // flick data free
255    if (mb->flick_data) e_mod_move_flick_data_free(mb);
256
257    switch (angle)
258      {
259       case  90:
260          x = 0;
261          y = 0;
262          break;
263       case 180:
264          x = 0;
265          y = zone->h - mb2->h;
266          break;
267       case 270:
268          x = zone->w - mb2->w;
269          y = 0;
270          break;
271       case   0:
272       default :
273          x = 0;
274          y = 0;
275          break;
276      }
277
278    e_mod_move_apptray_e_border_move(mb2, x, y);
279    e_mod_move_apptray_objs_animation_move(mb2, x, y);
280
281    return EINA_TRUE;
282 }
283
284 static Eina_Bool
285 _e_mod_move_indicator_widget_home_region_release_check(E_Move_Indicator_Widget *indi_widget,
286                                                        Eina_Bool                apptray_move /* if home button is pressd, then apptray_move set true */,
287                                                        int                      angle,
288                                                        Evas_Point               pos /* mouse up position */)
289 {
290    E_Move_Border *mb = NULL;
291    int            region_check;
292    Eina_Bool      ret = EINA_FALSE;
293    E_Zone        *zone = NULL;
294    E_Move        *m = NULL;
295
296    m = e_mod_move_util_get();
297    E_CHECK_RETURN(m, EINA_FALSE);
298    E_CHECK_RETURN(indi_widget, EINA_FALSE);
299    mb = e_mod_move_border_client_find(indi_widget->win);
300    E_CHECK_RETURN(mb, EINA_FALSE);
301    E_CHECK_RETURN(apptray_move, EINA_FALSE);
302    E_CHECK_RETURN(mb->bd, EINA_FALSE);
303    zone = mb->bd->zone;
304    E_CHECK_RETURN(zone, EINA_FALSE);
305
306    switch (angle)
307      {
308       case   0:
309          region_check = m->indicator_widget_geometry[E_MOVE_ANGLE_0].h;
310          if (pos.y < region_check) ret = EINA_TRUE;
311          break;
312       case  90:
313          region_check = m->indicator_widget_geometry[E_MOVE_ANGLE_90].w;
314          if (pos.x < region_check) ret = EINA_TRUE;
315          break;
316       case 180:
317          region_check = zone->h - m->indicator_widget_geometry[E_MOVE_ANGLE_180].h;
318          if (pos.y > region_check) ret = EINA_TRUE;
319          break;
320       case 270:
321          region_check = zone->w - m->indicator_widget_geometry[E_MOVE_ANGLE_270].w;
322          if (pos.x > region_check) ret = EINA_TRUE;
323          break;
324       default :
325          L(LT_EVENT_OBJ,
326            "[MOVE] ev:%15.15s , invalid angle:%d, (%d,%d)  %s()\n",
327            "EVAS_OBJ", angle, pos.x, pos.y,
328             __func__)
329          break;
330      }
331    return ret;
332 }
333
334 static Eina_Bool
335 _e_mod_move_indicator_widget_cb_motion_start(void *data,
336                                              void *event_info)
337 {
338    E_Move *m = NULL;
339    E_Move_Indicator_Widget *indi_widget = (E_Move_Indicator_Widget *)data;
340
341    E_Move_Border *mb = NULL;
342    E_Move_Border *ev_mb = NULL;
343    E_Move_Border *qp_mb = NULL;
344    E_Move_Border *at_mb = NULL;
345    E_Move_Event_Motion_Info *info;
346    E_Move_Widget_Object *mwo = NULL;
347    Evas_Event_Mouse_Down *mouse_down_event = NULL;
348    Eina_Bool clicked = EINA_FALSE;
349    Eina_List *l;
350    E_Move_Scroll_Region_Indicator scroll_region = E_MOVE_SCROLL_REGION_NONE;
351    Ecore_X_Window ev_win = 0;
352
353    info  = (E_Move_Event_Motion_Info *)event_info;
354    m = e_mod_move_util_get();
355
356    E_CHECK_RETURN(indi_widget, EINA_FALSE);
357
358    // clicked window indicator policy check
359    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
360      {
361         if (!mwo) continue;
362         ev_win = e_mod_move_event_win_get(mwo->event);
363      }
364    ev_mb = e_mod_move_border_client_find(ev_win);
365    E_CHECK_RETURN(_e_mod_move_indicator_widget_target_window_policy_check(ev_mb),
366                   EINA_FALSE);
367
368    mb = e_mod_move_border_client_find(indi_widget->win);
369
370    if (!m || !mb || !indi_widget || !info) return EINA_FALSE;
371
372    mouse_down_event = info->event_info;
373    E_CHECK_RETURN(mouse_down_event, EINA_FALSE);
374    if (mouse_down_event->button != 1)
375      return EINA_FALSE;
376
377    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
378      {
379         if (!mwo) continue;
380         clicked = e_mod_move_event_click_get(mwo->event);
381      }
382    if (clicked)
383      return EINA_FALSE;
384
385    L(LT_EVENT_OBJ,
386      "[MOVE] ev:%15.15s w:0x%08x INDI_WIDGET_MOTION_START (%4d,%4d)\n",
387      "EVAS_OBJ", mb->bd->win,
388      info->coord.x, info->coord.y);
389
390    _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_FALSE);
391    _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_FALSE);
392
393    /* check if apptray or quickpanel exists on the current zone */
394    at_mb = e_mod_move_apptray_find();
395    if ((at_mb) &&
396        (REGION_INSIDE_ZONE(at_mb, mb->bd->zone)))
397      {
398         L(LT_EVENT_OBJ,
399           "[MOVE] ev:%15.15s w:0x%08x INDI_WIDGET_MOTION_START %s\n",
400           "EVAS_OBJ", mb->bd->win,
401           "apptray exists. return.");
402         return EINA_FALSE;
403      }
404
405    qp_mb = e_mod_move_quickpanel_find();
406    if ((qp_mb) &&
407        (REGION_INSIDE_ZONE(qp_mb, mb->bd->zone)))
408      {
409         L(LT_EVENT_OBJ,
410           "[MOVE] ev:%15.15s w:0x%08x INDI_WIDGET_MOTION_START %s\n",
411           "EVAS_OBJ", mb->bd->win,
412           "quickpanel exists. return.");
413         return EINA_FALSE;
414      }
415
416    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
417      {
418         if (!mwo) continue;
419         e_mod_move_event_click_set(mwo->event, EINA_TRUE);
420      }
421
422    E_CHECK_GOTO(e_mod_move_flick_data_new(mb), error_cleanup);
423    e_mod_move_flick_data_init(mb, info->coord.x, info->coord.y);
424
425    scroll_region = e_mod_move_indicator_region_scroll_check(mb->angle, info->coord);
426
427    if (scroll_region == E_MOVE_SCROLL_REGION_APPTRAY)
428      {
429         if (e_mod_move_panel_scrollable_get(mb, E_MOVE_PANEL_TYPE_APPTRAY))
430           {
431              if (_e_mod_move_indicator_widget_cb_motion_start_internal_apptray_check(at_mb))
432                {
433                   e_mod_move_apptray_e_border_raise(at_mb);
434                   _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_TRUE);
435                   e_mod_move_apptray_objs_animation_start_position_set(at_mb,
436                                                                        mb->angle);
437                   // send apptray to "move start message".
438                   e_mod_move_apptray_anim_state_send(at_mb, EINA_TRUE);
439                }
440           }
441      }
442    else if (scroll_region == E_MOVE_SCROLL_REGION_QUICKPANEL)
443      {
444         if (e_mod_move_panel_scrollable_get(mb, E_MOVE_PANEL_TYPE_QUICKPANEL))
445           {
446              if (_e_mod_move_indicator_widget_cb_motion_start_internal_quickpanel_check(qp_mb))
447                {
448                   _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_TRUE);
449                   e_mod_move_quickpanel_objs_animation_start_position_set(qp_mb,
450                                                                           mb->angle);
451                   // send quickpanel to "move start message".
452                   e_mod_move_quickpanel_anim_state_send(qp_mb, EINA_TRUE);
453                }
454           }
455      }
456
457    indi_widget->pos = info->coord; // save mouse click position
458
459    return EINA_TRUE;
460
461 error_cleanup:
462
463    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
464      {
465         if (!mwo) continue;
466         e_mod_move_event_click_set(mwo->event, EINA_FALSE);
467      }
468
469    _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_FALSE);
470    _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_FALSE);
471
472    return EINA_FALSE;
473 }
474
475 static Eina_Bool
476 _e_mod_move_indicator_widget_cb_motion_move(void *data,
477                                             void *event_info)
478 {
479    E_Move                   *m = NULL;
480    E_Move_Indicator_Widget  *indi_widget = (E_Move_Indicator_Widget *)data;
481    E_Move_Border            *mb = NULL;
482    E_Move_Border            *qp_mb = NULL;
483    E_Move_Border            *at_mb = NULL;
484    E_Move_Event_Motion_Info *info;
485    E_Move_Widget_Object     *mwo = NULL;
486    E_Zone                   *zone = NULL;
487    Eina_List                *l;
488    Eina_Bool                 click = EINA_FALSE;
489    Eina_Bool                 need_move = EINA_FALSE;
490    Eina_Bool                 contents = EINA_FALSE;
491
492    int cx, cy, cw, ch;
493    int x = 0, y = 0;
494    int angle;
495
496    info  = (E_Move_Event_Motion_Info *)event_info;
497    m = e_mod_move_util_get();
498
499    E_CHECK_RETURN(indi_widget, EINA_FALSE);
500    mb = e_mod_move_border_client_find(indi_widget->win);
501
502    if (!m || !mb || !info) return EINA_FALSE;
503
504    L(LT_EVENT_OBJ,
505      "[MOVE] ev:%15.15s w:0x%08x INDI_WIDGET_MOTION_MOVE a:%d (%4d,%4d)\n",
506      "EVAS_OBJ", mb->bd->win, mb->angle,
507      info->coord.x, info->coord.y);
508
509    angle = mb->angle;
510    zone = mb->bd->zone;
511
512    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
513      {
514         if (!mwo) continue;
515         click = e_mod_move_event_click_get(mwo->event);
516      }
517
518    E_CHECK_RETURN(click, EINA_FALSE);
519
520    if (_e_mod_move_indicator_widget_quickpanel_move_get(indi_widget))
521      {
522         qp_mb = e_mod_move_quickpanel_find();
523         E_CHECK_RETURN(qp_mb, EINA_FALSE);
524
525         contents = e_mod_move_border_contents_rect_get(qp_mb, &cx, &cy ,&cw, &ch);
526
527         switch (angle)
528           {
529            case   0:
530               if (info->coord.y < qp_mb->h)
531                 {
532                    if (contents)
533                      {
534                         if (info->coord.y < ch)
535                           {
536                              y = info->coord.y - ch;
537                              need_move = EINA_TRUE;
538                           }
539                      }
540                    else
541                      {
542                         y = info->coord.y - qp_mb->h;
543                         need_move = EINA_TRUE;
544                      }
545                 }
546               break;
547            case  90:
548               if (info->coord.x < qp_mb->w)
549                 {
550                    if (contents)
551                      {
552                         if (info->coord.x < cw)
553                           {
554                              x = info->coord.x - cw;
555                              need_move = EINA_TRUE;
556                           }
557                      }
558                    else
559                      {
560                         x = info->coord.x - qp_mb->w;
561                         need_move = EINA_TRUE;
562                      }
563                 }
564               break;
565            case 180:
566               if (info->coord.y > (zone->h - qp_mb->h))
567                 {
568                    if (contents)
569                      {
570                         if (info->coord.y > cy)
571                           {
572                              y = info->coord.y - cy;
573                              need_move = EINA_TRUE;
574                           }
575                      }
576                    else
577                      {
578                         y = info->coord.y;
579                         need_move = EINA_TRUE;
580                      }
581                 }
582               break;
583            case 270:
584               if (info->coord.x > (zone->w - qp_mb->w))
585                 {
586                    if (contents)
587                      {
588                         if (info->coord.x > cx)
589                           {
590                              x = info->coord.x - cx;
591                              need_move = EINA_TRUE;
592                           }
593                      }
594                    else
595                      {
596                         x = info->coord.x;
597                         need_move = EINA_TRUE;
598                      }
599                 }
600               break;
601            default :
602               break;
603           }
604
605         if (_e_mod_move_indicator_widget_scrollable_object_movable_check(mb, info->coord))
606           {
607              if (m->qp_scroll_with_clipping)
608                 e_mod_move_quickpanel_objs_move(qp_mb,
609                                                 info->coord.x,
610                                                 info->coord.y);
611              else
612                {
613                   if (need_move)
614                      e_mod_move_quickpanel_objs_move(qp_mb, x, y);
615                }
616           }
617      }
618    else if (_e_mod_move_indicator_widget_apptray_move_get(indi_widget))
619      {
620         at_mb = e_mod_move_apptray_find();
621         E_CHECK_RETURN(at_mb, EINA_FALSE);
622
623         switch (angle)
624           {
625            case   0:
626               if (info->coord.y < at_mb->h)
627                 {
628                    y = info->coord.y - at_mb->h;
629                    need_move = EINA_TRUE;
630                 }
631               break;
632            case  90:
633               if (info->coord.x < at_mb->w)
634                 {
635                    x = info->coord.x - at_mb->w;
636                    need_move = EINA_TRUE;
637                 }
638               break;
639            case 180:
640               if (info->coord.y > (zone->h - at_mb->h))
641                 {
642                    y = info->coord.y;
643                    need_move = EINA_TRUE;
644                 }
645               break;
646            case 270:
647               if (info->coord.x > (zone->w - at_mb->w))
648                 {
649                    x = info->coord.x;
650                    need_move = EINA_TRUE;
651                 }
652               break;
653            default :
654               break;
655           }
656         if (need_move)
657           e_mod_move_apptray_objs_move(at_mb, x, y);
658      }
659
660    indi_widget->pos = info->coord; // save mouse move position
661
662    return EINA_TRUE;
663 }
664
665 static Eina_Bool
666 _e_mod_move_indicator_widget_cb_motion_end(void *data,
667                                            void *event_info)
668 {
669    E_Move                   *m = NULL;
670    E_Move_Indicator_Widget  *indi_widget = (E_Move_Indicator_Widget *)data;
671    E_Move_Border            *mb = NULL;
672    E_Move_Border            *qp_mb = NULL;
673    E_Move_Border            *at_mb = NULL;
674    E_Move_Event_Motion_Info *info;
675    E_Move_Widget_Object     *mwo = NULL;
676    Eina_List                *l;
677    E_Zone                   *zone;
678    Evas_Event_Mouse_Up      *mouse_up_event;
679    Eina_Bool                 click = EINA_FALSE;
680    Eina_Bool                 flick_state = EINA_FALSE;
681    Eina_Bool                 qp_mv_state = EINA_FALSE;
682    Eina_Bool                 at_mv_state = EINA_FALSE;
683
684    int cx, cy, cw, ch;
685    int check_h, check_w;
686    int angle = 0;
687    int mx = 0, my = 0, ax = 0, ay = 0;
688
689    info  = (E_Move_Event_Motion_Info *)event_info;
690    m = e_mod_move_util_get();
691
692    E_CHECK_RETURN(indi_widget, EINA_FALSE);
693    mb = e_mod_move_border_client_find(indi_widget->win);
694
695    if (!m || !mb || !info) return EINA_FALSE;
696
697    mouse_up_event = info->event_info;
698    E_CHECK_RETURN(mouse_up_event, EINA_FALSE);
699    if (mouse_up_event->button != 1)
700      return EINA_FALSE;
701
702    L(LT_EVENT_OBJ,
703      "[MOVE] ev:%15.15s w:0x%08x ,angle:%d, (%d,%d)  %s()\n",
704      "EVAS_OBJ", mb->bd->win, mb->angle, info->coord.x, info->coord.y,
705      __func__);
706
707    angle = mb->angle;
708    zone = mb->bd->zone;
709
710    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
711      {
712         if (!mwo) continue;
713         click = e_mod_move_event_click_get(mwo->event);
714      }
715    E_CHECK_GOTO(click, error_cleanup);
716
717    qp_mv_state = _e_mod_move_indicator_widget_quickpanel_move_get(indi_widget);
718    at_mv_state = _e_mod_move_indicator_widget_apptray_move_get(indi_widget);
719    if (!qp_mv_state && !at_mv_state) goto finish;
720
721    e_mod_move_flick_data_update(mb, info->coord.x, info->coord.y);
722    flick_state = e_mod_move_flick_state_get(mb, EINA_TRUE);
723
724    if (qp_mv_state)
725      {
726         qp_mb = e_mod_move_quickpanel_find();
727         if (_e_mod_move_indicator_widget_quickpanel_flick_process(indi_widget, qp_mb,
728                                                                   angle, flick_state))
729           {
730              return EINA_TRUE;
731           }
732      }
733    if (at_mv_state)
734      {
735         at_mb = e_mod_move_apptray_find();
736
737         // if release position is on indicator's home button then, do not flick.
738         if (_e_mod_move_indicator_widget_home_region_release_check(indi_widget,
739                                                                    EINA_TRUE, /* upper if phrase check _e_mod_move_indicator_apptray_move_get(mb) value TURE or FALSE. */
740                                                                    angle,
741                                                                    info->coord))
742           {
743              flick_state = EINA_FALSE;
744           }
745
746         if (_e_mod_move_indicator_widget_apptray_flick_process(indi_widget, at_mb,
747                                                                angle, flick_state))
748           {
749              return EINA_TRUE;
750           }
751      }
752
753    mx = zone->x;
754    my = zone->y;
755    ax = mx;
756    ay = my;
757
758    switch (angle)
759      {
760       case   0:
761          if (at_mb)
762            {
763               check_h = at_mb->h;
764               if (check_h) check_h /= 2;
765               if (info->coord.y < check_h)
766                 {
767                    my = at_mb->h * -1;
768                    ay = my;
769                 }
770            }
771          if (qp_mb)
772            {
773               check_h = qp_mb->h;
774               if (check_h) check_h /= 2;
775               if (info->coord.y < check_h)
776                 {
777                    if (m->qp_scroll_with_clipping)
778                      {
779                         my = qp_mb->h * -1;
780                      }
781                    else
782                      {
783                         if (e_mod_move_border_contents_rect_get(qp_mb, &cx, &cy ,&cw, &ch))
784                           {
785                              check_h = ch;
786                              if (check_h) check_h /= 2;
787                              if (info->coord.y < check_h)
788                                {
789                                   my = qp_mb->h * -1;
790                                   ay = ch * -1;
791                                }
792                           }
793                      }
794                 }
795                else
796                 {
797                    if (m->qp_scroll_with_clipping)
798                      {
799                         ax = zone->x + qp_mb->w,
800                         ay = zone->y + qp_mb->h;
801                      }
802                 }
803            }
804          break;
805       case  90:
806          if (at_mb)
807            {
808               check_w = at_mb->w;
809               if (check_w) check_w /= 2;
810               if (info->coord.x < check_w)
811                 {
812                    mx = at_mb->w * -1;
813                    ax = mx;
814                 }
815            }
816          if (qp_mb)
817            {
818               check_w = qp_mb->w;
819               if (check_w) check_w /= 2;
820               if (info->coord.x < check_w)
821                 {
822                    if (m->qp_scroll_with_clipping)
823                      {
824                         mx = qp_mb->w * -1;
825                      }
826                    else
827                      {
828                         if (e_mod_move_border_contents_rect_get(qp_mb, &cx, &cy ,&cw, &ch))
829                           {
830                              check_w = cw;
831                              if (check_w) check_w /= 2;
832                              if (info->coord.x < check_w)
833                                {
834                                   mx = qp_mb->w * -1;
835                                   ax = cw * -1;
836                                }
837                           }
838                      }
839                 }
840                else
841                 {
842                    if (m->qp_scroll_with_clipping)
843                      {
844                         ax = zone->x + qp_mb->w;
845                         ay = zone->y + qp_mb->h;
846                      }
847                 }
848            }
849          break;
850       case 180:
851          if (at_mb)
852            {
853               check_h = at_mb->h;
854               if (check_h) check_h /= 2;
855               if (info->coord.y > (zone->h - check_h))
856                 {
857                    my = zone->h;
858                    ay = my;
859                 }
860                else
861                 {
862                    my = zone->h - at_mb->h;
863                    ay = my;
864                 }
865            }
866          if (qp_mb)
867            {
868               check_h = qp_mb->h;
869               if (check_h) check_h /= 2;
870               if (info->coord.y > (zone->h - check_h))
871                 {
872                    if (m->qp_scroll_with_clipping)
873                      {
874                         my = zone->h;
875                         ax = zone->x + qp_mb->w;
876                         ay = zone->y + qp_mb->h;
877                      }
878                    else
879                      {
880                         if (e_mod_move_border_contents_rect_get(qp_mb, &cx, &cy ,&cw, &ch))
881                           {
882                              check_h = ch;
883                              if (check_h) check_h /= 2;
884                              if (info->coord.y > (cy + check_h))
885                                {
886                                   my = zone->h;
887                                   ay = ch;
888                                }
889                           }
890                      }
891                 }
892            }
893          break;
894       case 270:
895          if (at_mb)
896            {
897               check_w = at_mb->w;
898               if (check_w) check_w /= 2;
899               if (info->coord.x > (zone->w - check_w))
900                 {
901                    mx = zone->w;
902                    ax = mx;
903                 }
904                else
905                 {
906                    mx = zone->w - at_mb->w;
907                    ax = mx;
908                 }
909            }
910          if (qp_mb)
911            {
912               check_w = qp_mb->w;
913               if (check_w) check_w /= 2;
914               if (info->coord.x > (zone->w - check_w))
915                 {
916                    if (m->qp_scroll_with_clipping)
917                      {
918                         mx = zone->w;
919                         ax = zone->x + qp_mb->w;
920                         ay = zone->y + qp_mb->h;
921                      }
922                    else
923                      {
924                         if (e_mod_move_border_contents_rect_get(qp_mb, &cx, &cy ,&cw, &ch))
925                           {
926                              check_w = cw;
927                              if (check_w) check_w /= 2;
928                              if (info->coord.x > (cx + check_w))
929                                {
930                                   mx = zone->w;
931                                   ax = cw;
932                                }
933                           }
934                      }
935                 }
936            }
937          break;
938       default :
939          break;
940      }
941
942    if (at_mb)
943      {
944         e_mod_move_apptray_e_border_move(at_mb, mx, my);
945         e_mod_move_apptray_objs_animation_move(at_mb, ax, ay);
946      }
947    else if (qp_mb)
948      {
949         e_mod_move_quickpanel_e_border_move(qp_mb, mx, my);
950         if (_e_mod_move_indicator_widget_scrollable_object_movable_check(mb, info->coord))
951           e_mod_move_quickpanel_objs_animation_move(qp_mb, ax, ay);
952         else
953           e_mod_move_quickpanel_objs_animation_move_with_time(qp_mb, ax, ay, 0.0000001);
954         // time :0.0 calls animation_frame with pos : 0.0  calls once.
955         // so I use small time value, it makes animation_frame with pos: 1.0 call once
956      }
957
958 finish:
959    indi_widget->pos = info->coord; // save mouse up position
960
961    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
962      {
963         if (!mwo) continue;
964         e_mod_move_event_click_set(mwo->event, EINA_FALSE);
965      }
966
967 error_cleanup:
968    if (mb->flick_data) e_mod_move_flick_data_free(mb);
969    _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_FALSE);
970    _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_FALSE);
971
972    return EINA_TRUE;
973 }
974
975 static void
976 _e_mod_move_indicator_widget_obj_event_setup(E_Move_Indicator_Widget *indicator_widget,
977                                              E_Move_Widget_Object    *mwo)
978 {
979    E_CHECK(indicator_widget);
980    E_CHECK(mwo);
981
982    mwo->event = e_mod_move_event_new(indicator_widget->win, mwo->obj);
983    E_CHECK(mwo->event);
984
985    e_mod_move_event_data_type_set(mwo->event, E_MOVE_EVENT_DATA_TYPE_WIDGET_INDICATOR);
986    e_mod_move_event_angle_cb_set(mwo->event,
987                                  e_mod_move_util_win_prop_angle_get);
988    e_mod_move_event_cb_set(mwo->event, E_MOVE_EVENT_TYPE_MOTION_START,
989                            _e_mod_move_indicator_widget_cb_motion_start,
990                            indicator_widget);
991    e_mod_move_event_cb_set(mwo->event, E_MOVE_EVENT_TYPE_MOTION_MOVE,
992                            _e_mod_move_indicator_widget_cb_motion_move,
993                            indicator_widget);
994    e_mod_move_event_cb_set(mwo->event, E_MOVE_EVENT_TYPE_MOTION_END,
995                            _e_mod_move_indicator_widget_cb_motion_end,
996                            indicator_widget);
997    e_mod_move_event_win_find_cb_set(mwo->event,
998                                     _e_mod_move_indicator_widget_event_win_find);
999    e_mod_move_event_propagate_type_set(mwo->event,
1000                                        E_MOVE_EVENT_PROPAGATE_TYPE_IMMEDIATELY);
1001 }
1002
1003 static Eina_Bool
1004 _e_mod_move_indicator_widget_scrollable_object_movable_check(E_Move_Border *mb, Evas_Point pos)
1005 {
1006    E_Move *m = NULL;
1007    int val1 = 0, val2 = 0;
1008    double threshold = 0.2; // 20 %
1009    Eina_Bool ret = EINA_FALSE;
1010    int sx = 0, sy = 0, ex = 0, ey = 0;
1011    double st = 0.0, et = 0.0;
1012
1013    m = e_mod_move_util_get();
1014    E_CHECK_RETURN(m, EINA_FALSE);
1015
1016    if (!e_mod_move_flick_data_get(mb, &sx, &sy, &ex, &ey, &st, &et))
1017      return EINA_FALSE;
1018
1019    switch (mb->angle)
1020      {
1021       case 90:
1022          val1 = pos.x - sx;
1023          val2 = m->indicator_widget_geometry[E_MOVE_ANGLE_90].w;
1024          break;
1025       case 180:
1026          val1 = sy - pos.y;
1027          val2 = m->indicator_widget_geometry[E_MOVE_ANGLE_180].h;
1028          break;
1029       case 270:
1030          val1 = sx - pos.x;
1031          val2 = m->indicator_widget_geometry[E_MOVE_ANGLE_270].w;
1032          break;
1033       case 0:
1034       default:
1035          val1 = pos.y - sy;
1036          val2 = m->indicator_widget_geometry[E_MOVE_ANGLE_0].h;
1037          break;
1038      }
1039
1040    if ((val1 / val2) > threshold) ret = EINA_TRUE;
1041
1042    return ret;
1043 }
1044
1045 static Eina_Bool
1046 _e_mod_move_indicator_widget_target_window_find_by_pointer(Ecore_X_Window *win,
1047                                                            int x,
1048                                                            int y)
1049 {
1050    E_Move        *m = NULL;
1051    E_Move_Border *find_mb = NULL;
1052    Eina_Bool      found = EINA_FALSE;
1053    Eina_Bool      ret = EINA_FALSE;
1054    Ecore_X_Window noti_win = 0;
1055    Eina_Bool      noti_win_saved = EINA_FALSE;
1056
1057    E_CHECK_RETURN(win, EINA_FALSE);
1058    m = e_mod_move_util_get();
1059    E_CHECK_RETURN(m, EINA_FALSE);
1060
1061    EINA_INLIST_REVERSE_FOREACH(m->borders, find_mb)
1062      {
1063         if (!find_mb->bd) continue;
1064
1065         // finding visible border
1066         if (!find_mb->visible) continue;
1067
1068         // finding pointed border
1069         if (!E_INSIDE(x, y, find_mb->bd->x, find_mb->bd->y,
1070                             find_mb->bd->w, find_mb->bd->h))
1071           continue;
1072
1073         // if notification , alpha, and indicator_state_none then search again below.
1074         if (TYPE_NOTIFICATION_CHECK(find_mb)
1075             && (find_mb->argb)
1076             && (find_mb->indicator_state == E_MOVE_INDICATOR_STATE_NONE))
1077           {
1078              if (!noti_win_saved)
1079                {
1080                   noti_win = find_mb->bd->client.win;
1081                   noti_win_saved = EINA_TRUE;
1082                }
1083              continue;
1084           }
1085         else
1086           {
1087              found = EINA_TRUE;
1088              break;
1089           }
1090      }
1091
1092    if (found)
1093      {
1094         if ((find_mb)
1095             && (find_mb->indicator_state == E_MOVE_INDICATOR_STATE_ON))
1096           {
1097              *win = find_mb->bd->client.win;
1098              ret = EINA_TRUE;
1099           }
1100         else
1101           {
1102              if (noti_win_saved)
1103                {
1104                   *win = noti_win;
1105                   ret = EINA_TRUE;
1106                }
1107              else
1108                {
1109                   *win = find_mb->bd->client.win;
1110                   ret = EINA_TRUE;
1111                }
1112           }
1113      }
1114
1115    return ret;
1116 }
1117
1118 static Ecore_X_Window
1119 _e_mod_move_indicator_widget_event_win_find(void *event_info)
1120 {
1121    E_Move_Event_Motion_Info *info = NULL;
1122    E_Border                 *find_bd = NULL;
1123    Ecore_X_Window            win = 0, res_win = 0;
1124    info  = (E_Move_Event_Motion_Info *)event_info;
1125
1126    E_CHECK_RETURN(info, 0);
1127
1128    find_bd = e_mod_move_util_border_find_by_pointer(info->coord.x, info->coord.y);
1129
1130    if (_e_mod_move_indicator_widget_target_window_find_by_pointer(&win,
1131                                                                   info->coord.x,
1132                                                                   info->coord.y))
1133      {
1134          res_win = win;
1135      }
1136
1137    L(LT_EVENT_OBJ,
1138      "[MOVE] ev:%15.15s INDICATOR_WIDGET_EVENT_WIN_FIND w:0x%08x (%4d,%4d)\n",
1139      "EVAS_OBJ", res_win, info->coord.x, info->coord.y);
1140
1141    return res_win;
1142 }
1143
1144 static Eina_Bool
1145 _e_mod_move_indicator_widget_target_window_policy_check(E_Move_Border *mb)
1146 {
1147    E_Move        *m = e_mod_move_util_get();
1148    E_Zone        *zone = NULL;
1149    Eina_Bool      ret = EINA_FALSE;
1150    E_Border      *bd = NULL;
1151
1152    E_CHECK_RETURN(m, EINA_FALSE);
1153    E_CHECK_RETURN(mb, EINA_FALSE);
1154
1155    bd = mb->bd;
1156    E_CHECK_RETURN(bd, EINA_FALSE);
1157    zone = bd->zone;
1158    E_CHECK_RETURN(zone, EINA_FALSE);
1159
1160    if (REGION_EQUAL_TO_ZONE(mb, zone)  // check fullscreen
1161        && (zone->id == 0)              // change zone->id comparing to bd's profile property (mobile)
1162        && (mb->indicator_state == E_MOVE_INDICATOR_STATE_ON)
1163        && (mb->indicator_type == E_MOVE_INDICATOR_TYPE_1))
1164      {
1165          ret = EINA_TRUE;
1166      }
1167
1168    return ret;
1169 }
1170
1171 static Eina_Bool
1172 _e_mod_move_indicator_widget_event_send_policy_check(E_Move_Indicator_Widget *indi_widget,
1173                                                      Evas_Point               pos)
1174 {
1175    int x = 0, y = 0, w = 0, h = 0;
1176    Eina_Bool ret = EINA_FALSE;
1177
1178    E_CHECK_RETURN(indi_widget, EINA_FALSE);
1179
1180    e_mod_move_widget_objs_geometry_get(indi_widget->objs, &x ,&y, &w, &h);
1181
1182    if (E_INSIDE(pos.x, pos.y, x, y, w, h)) ret = EINA_TRUE;
1183
1184    return ret;
1185 }
1186
1187 /* externally accessible functions */
1188
1189 /* set current indicator widget */
1190 EINTERN void
1191 e_mod_move_indicator_widget_set(E_Move_Indicator_Widget *indi_widget)
1192 {
1193    E_Move *m = NULL;
1194
1195    m = e_mod_move_util_get();
1196    E_CHECK(m);
1197
1198    if (m->indicator_widget)
1199      {
1200         e_mod_move_indicator_widget_del(m->indicator_widget);
1201      }
1202
1203    m->indicator_widget = indi_widget;
1204 }
1205
1206 /* get current indicator widget */
1207 EINTERN E_Move_Indicator_Widget *
1208 e_mod_move_indicator_widget_get(void)
1209 {
1210    E_Move *m = NULL;
1211    m = e_mod_move_util_get();
1212    E_CHECK_RETURN(m, NULL);
1213
1214    return m->indicator_widget;
1215 }
1216
1217 /* find indicator widget target window */
1218 EINTERN Eina_Bool
1219 e_mod_move_indicator_widget_target_window_find(Ecore_X_Window *win)
1220 {
1221    E_Move        *m = NULL;
1222    E_Move_Border *find_mb = NULL;
1223    Eina_Bool      found = EINA_FALSE;
1224    E_Zone        *zone = NULL;
1225    Eina_Bool      ret = EINA_FALSE;
1226
1227    E_CHECK_RETURN(win, EINA_FALSE);
1228    m = e_mod_move_util_get();
1229    E_CHECK_RETURN(m, EINA_FALSE);
1230
1231    // fix later
1232    EINA_INLIST_REVERSE_FOREACH(m->borders, find_mb)
1233      {
1234         if (!find_mb->bd) continue;
1235         // the first OnScreen & FullScreen Window
1236         zone = find_mb->bd->zone;
1237         if (find_mb->visible
1238             && REGION_EQUAL_TO_ZONE(find_mb, zone)  // check fullscreen
1239             && (zone->id == 0)) // change zone->id comparing to bd's profile property (mobile)
1240           {
1241              found = EINA_TRUE;
1242              break;
1243           }
1244      }
1245
1246    if (found
1247 //       && (find_mb->indicator_state == E_MOVE_INDICATOR_STATE_ON)
1248 //       && (find_mb->indicator_type == E_MOVE_INDICATOR_TYPE_1)
1249 //       && !(TYPE_INDICATOR_CHECK(find_mb))
1250        && !(TYPE_APPTRAY_CHECK(find_mb))
1251        && !(TYPE_QUICKPANEL_CHECK(find_mb)))
1252      {
1253         *win = find_mb->bd->client.win;
1254         ret = EINA_TRUE;
1255      }
1256
1257    return ret;
1258 }
1259
1260 /* find indicator widget's target window and apply indicator widget control */
1261 EINTERN void
1262 e_mod_move_indicator_widget_apply(void)
1263 {
1264    E_Move                  *m = NULL;
1265    E_Move_Indicator_Widget *indi_widget = NULL;
1266    Ecore_X_Window           target_win;
1267    E_Move_Border           *target_mb = NULL;
1268
1269    m = e_mod_move_util_get();
1270    E_CHECK(m);
1271    if (m->screen_reader_state) return;
1272
1273    if (e_mod_move_indicator_widget_target_window_find(&target_win))
1274      {
1275         target_mb = e_mod_move_border_client_find(target_win);
1276         // if previous indicator widget is created
1277         if ((indi_widget = e_mod_move_indicator_widget_get()))
1278           {
1279              // if current indicator widget's win is equal to finded win
1280              // then just return.
1281              if ((indi_widget->win == target_win)) return;
1282              else
1283                {
1284                   // if current indicator widget's win is not equal to finded win
1285                   // then del previous indicator_widget and add new indicator widget.
1286                   e_mod_move_indicator_widget_del(indi_widget);
1287                   e_mod_move_indicator_widget_set(e_mod_move_indicator_widget_add(target_win));
1288                   if (!TYPE_NOTIFICATION_CHECK(target_mb))
1289                     e_mod_move_util_prop_active_indicator_win_set(target_win, m);
1290                }
1291           }
1292         else
1293           {
1294              //if previous indicator widget is not creagted
1295              //then add new indicator widget.
1296              e_mod_move_indicator_widget_set(e_mod_move_indicator_widget_add(target_win));
1297              if (!TYPE_NOTIFICATION_CHECK(target_mb))
1298                e_mod_move_util_prop_active_indicator_win_set(target_win, m);
1299           }
1300      }
1301    else
1302      {
1303         // if current window does not require indicator widget
1304         // and previous indicator widget is created,
1305         // then del previous indicator_widget
1306         if ((indi_widget = e_mod_move_indicator_widget_get()))
1307           {
1308              e_mod_move_indicator_widget_del(indi_widget);
1309              e_mod_move_indicator_widget_set(NULL);
1310           }
1311      }
1312 }
1313
1314 /* create E_Move_Border related Indicator_Widget */
1315 EINTERN E_Move_Indicator_Widget *
1316 e_mod_move_indicator_widget_add(Ecore_X_Window win)
1317 {
1318    E_Move                  *m = NULL;
1319    E_Move_Border           *mb = NULL;
1320    E_Move_Indicator_Widget *indi_widget = NULL;
1321    E_Move_Widget_Object    *mwo = NULL;
1322    Eina_List               *l;
1323    int                      x;
1324    int                      y;
1325    int                      w;
1326    int                      h;
1327
1328    m = e_mod_move_util_get();
1329    E_CHECK_RETURN(m, EINA_FALSE);
1330
1331    mb = e_mod_move_border_client_find(win);
1332    E_CHECK_RETURN(mb, NULL);
1333
1334    indi_widget = E_NEW(E_Move_Indicator_Widget, 1);
1335    E_CHECK_RETURN(indi_widget, NULL);
1336
1337    indi_widget->win = win;
1338    indi_widget->objs = e_mod_move_widget_objs_add(m);
1339    if (indi_widget->objs)
1340      {
1341         switch (mb->angle)
1342           {
1343              case 90:
1344                 x = m->indicator_widget_geometry[E_MOVE_ANGLE_90].x;
1345                 y = m->indicator_widget_geometry[E_MOVE_ANGLE_90].y;
1346                 w = m->indicator_widget_geometry[E_MOVE_ANGLE_90].w;
1347                 h = m->indicator_widget_geometry[E_MOVE_ANGLE_90].h;
1348                 break;
1349              case 180:
1350                 x = m->indicator_widget_geometry[E_MOVE_ANGLE_180].x;
1351                 y = m->indicator_widget_geometry[E_MOVE_ANGLE_180].y;
1352                 w = m->indicator_widget_geometry[E_MOVE_ANGLE_180].w;
1353                 h = m->indicator_widget_geometry[E_MOVE_ANGLE_180].h;
1354                 break;
1355              case 270:
1356                 x = m->indicator_widget_geometry[E_MOVE_ANGLE_270].x;
1357                 y = m->indicator_widget_geometry[E_MOVE_ANGLE_270].y;
1358                 w = m->indicator_widget_geometry[E_MOVE_ANGLE_270].w;
1359                 h = m->indicator_widget_geometry[E_MOVE_ANGLE_270].h;
1360                 break;
1361              case 0:
1362              default:
1363                 x = m->indicator_widget_geometry[E_MOVE_ANGLE_0].x;
1364                 y = m->indicator_widget_geometry[E_MOVE_ANGLE_0].y;
1365                 w = m->indicator_widget_geometry[E_MOVE_ANGLE_0].w;
1366                 h = m->indicator_widget_geometry[E_MOVE_ANGLE_0].h;
1367                 break;
1368           }
1369         e_mod_move_widget_objs_move(indi_widget->objs, x, y);
1370         e_mod_move_widget_objs_resize(indi_widget->objs, w, h);
1371         e_mod_move_widget_objs_layer_set(indi_widget->objs, EVAS_LAYER_MAX);
1372         e_mod_move_widget_objs_color_set(indi_widget->objs, 0, 0, 0, 0);
1373         e_mod_move_widget_objs_show(indi_widget->objs);
1374         e_mod_move_widget_objs_raise(indi_widget->objs);
1375
1376         // Set Input Shape Mask
1377         if ((indi_widget->input_region_id = e_manager_comp_input_region_id_new(m->man)))
1378           {
1379              e_manager_comp_input_region_id_set(m->man,
1380                                                 indi_widget->input_region_id,
1381                                                 x, y, w, h);
1382           }
1383         else
1384           goto error_cleanup;
1385      }
1386    else
1387      {
1388         goto error_cleanup;
1389      }
1390
1391    // Set Event Handler
1392    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
1393      {
1394         if (!mwo) continue;
1395         _e_mod_move_indicator_widget_obj_event_setup(indi_widget, mwo);
1396      }
1397    return indi_widget;
1398
1399 error_cleanup:
1400    if (indi_widget->objs) e_mod_move_widget_objs_del(indi_widget->objs);
1401    memset(indi_widget, 0, sizeof(E_Move_Indicator_Widget));
1402    E_FREE(indi_widget);
1403    return NULL;
1404 }
1405
1406 /* delete indicator_widget */
1407 EINTERN void
1408 e_mod_move_indicator_widget_del(E_Move_Indicator_Widget *indi_widget)
1409 {
1410    E_Move        *m = NULL;
1411    E_Move_Border *mb = NULL;
1412    E_Move_Border *at_mb = NULL;
1413    E_Move_Border *qp_mb = NULL;
1414    E_Zone        *zone = NULL;
1415    int x = 0; int y = 0;
1416    int mx = 0, my = 0, ax = 0, ay = 0;
1417
1418    E_CHECK(indi_widget);
1419    m = e_mod_move_util_get();
1420
1421    if (e_mod_move_indicator_widget_click_get(indi_widget))
1422      ecore_x_mouse_up_send(indi_widget->win,
1423                            indi_widget->pos.x,
1424                            indi_widget->pos.y,
1425                            1);
1426
1427    if ((mb = e_mod_move_border_client_find(indi_widget->win)))
1428      {
1429         if (indi_widget->input_region_id)
1430           e_manager_comp_input_region_id_del(m->man, indi_widget->input_region_id);
1431
1432         // if indicaor widget is deleted, then apptray or quickpanel's mirror object hide with animation
1433         if (indi_widget->quickpanel_move)
1434           {
1435              qp_mb = e_mod_move_quickpanel_find();
1436              E_CHECK_GOTO(qp_mb, error_cleanup);
1437              zone = qp_mb->bd->zone;
1438
1439              switch (mb->angle)
1440                {
1441                 case  90:
1442                    mx = qp_mb->w * -1; my = 0;
1443                    if (m->qp_scroll_with_clipping)
1444                      {
1445                         ax = zone->x; ay = zone->y;
1446                      }
1447                    else
1448                      {
1449                         ax = mx; ay = my;
1450                      }
1451                    break;
1452                 case 180:
1453                    mx = 0; my = zone->h;
1454                    if (m->qp_scroll_with_clipping)
1455                      {
1456                         ax = zone->x + qp_mb->w;
1457                         ay = zone->y + qp_mb->h;
1458                      }
1459                    else
1460                      {
1461                         ax = mx; ay = my;
1462                      }
1463                    break;
1464                 case 270:
1465                    mx = zone->w; my = 0;
1466                    if (m->qp_scroll_with_clipping)
1467                      {
1468                         ax = zone->x + qp_mb->w;
1469                         ay = zone->y + qp_mb->h;
1470                      }
1471                    else
1472                      {
1473                         ax = mx; ay = my;
1474                      }
1475                    break;
1476                 case   0:
1477                 default :
1478                    mx = 0; my = qp_mb->h * -1;
1479                    if (m->qp_scroll_with_clipping)
1480                      {
1481                         ax = zone->x; ay = zone->y;
1482                      }
1483                    else
1484                      {
1485                         ax = mx; ay = my;
1486                      }
1487                    break;
1488                }
1489
1490              if (e_mod_move_quickpanel_objs_animation_state_get(qp_mb))
1491                {
1492                   e_mod_move_quickpanel_objs_animation_stop(qp_mb);
1493                   e_mod_move_quickpanel_objs_animation_clear(qp_mb);
1494                }
1495              e_mod_move_quickpanel_objs_add(qp_mb);
1496              e_mod_move_quickpanel_e_border_move(qp_mb, mx, my);
1497              e_mod_move_quickpanel_objs_animation_move(qp_mb, ax, ay);
1498              L(LT_EVENT_OBJ,
1499                "[MOVE] ev:%15.15s Indicator Widget Deleted: Hide QuickPanel %s():%d\n",
1500                "EVAS_OBJ", __func__, __LINE__);
1501           }
1502
1503         if (indi_widget->apptray_move)
1504           {
1505              at_mb = e_mod_move_apptray_find();
1506              E_CHECK_GOTO(at_mb, error_cleanup);
1507              zone = at_mb->bd->zone;
1508
1509              switch (mb->angle)
1510                {
1511                 case   0:
1512                    x = 0;
1513                    y = at_mb->h * -1;
1514                    break;
1515                 case  90:
1516                    x = at_mb->w * -1;
1517                    y = 0;
1518                    break;
1519                 case 180:
1520                    x = 0;
1521                    y = zone->h;
1522                    break;
1523                 case 270:
1524                    x = zone->w;
1525                    y = 0;
1526                    break;
1527                 default :
1528                    x = 0;
1529                    y = at_mb->h * -1;
1530                    break;
1531                }
1532              if (e_mod_move_apptray_objs_animation_state_get(at_mb))
1533                {
1534                   e_mod_move_apptray_objs_animation_stop(at_mb);
1535                   e_mod_move_apptray_objs_animation_clear(at_mb);
1536                }
1537              e_mod_move_apptray_objs_add(at_mb);
1538
1539              // apptray_objs_animation_layer_set
1540              e_mod_move_apptray_objs_animation_layer_set(at_mb);
1541
1542              e_mod_move_apptray_e_border_move(at_mb, x, y);
1543              e_mod_move_apptray_objs_animation_move(at_mb, x, y);
1544              L(LT_EVENT_OBJ,
1545                "[MOVE] ev:%15.15s Indicator Widget Deleted: Hide Apptray %s():%d\n",
1546                "EVAS_OBJ", __func__, __LINE__);
1547           }
1548      }
1549
1550 error_cleanup:
1551    if (indi_widget->objs) e_mod_move_widget_objs_del(indi_widget->objs);
1552    memset(indi_widget, 0, sizeof(E_Move_Indicator_Widget));
1553    E_FREE(indi_widget);
1554    if (m) m->indicator_widget = NULL;
1555 }
1556
1557 EINTERN Eina_Bool
1558 e_mod_move_indicator_widget_angle_change(Ecore_X_Window win)
1559 {
1560    E_Move                  *m = NULL;
1561    E_Move_Indicator_Widget *indi_widget = NULL;
1562    Eina_Bool                ret = EINA_FALSE;
1563    E_Move_Border           *mb = NULL;
1564    int                      x;
1565    int                      y;
1566    int                      w;
1567    int                      h;
1568
1569    m = e_mod_move_util_get();
1570    E_CHECK_RETURN(m, EINA_FALSE);
1571
1572    indi_widget = e_mod_move_indicator_widget_get();
1573    E_CHECK_RETURN(indi_widget, EINA_FALSE);
1574
1575    if ((indi_widget->win == win))
1576      {
1577         if ((mb = e_mod_move_border_client_find(win)))
1578           {
1579              switch (mb->angle)
1580                {
1581                   case 90:
1582                      x = m->indicator_widget_geometry[E_MOVE_ANGLE_90].x;
1583                      y = m->indicator_widget_geometry[E_MOVE_ANGLE_90].y;
1584                      w = m->indicator_widget_geometry[E_MOVE_ANGLE_90].w;
1585                      h = m->indicator_widget_geometry[E_MOVE_ANGLE_90].h;
1586                      break;
1587                   case 180:
1588                      x = m->indicator_widget_geometry[E_MOVE_ANGLE_180].x;
1589                      y = m->indicator_widget_geometry[E_MOVE_ANGLE_180].y;
1590                      w = m->indicator_widget_geometry[E_MOVE_ANGLE_180].w;
1591                      h = m->indicator_widget_geometry[E_MOVE_ANGLE_180].h;
1592                      break;
1593                   case 270:
1594                      x = m->indicator_widget_geometry[E_MOVE_ANGLE_270].x;
1595                      y = m->indicator_widget_geometry[E_MOVE_ANGLE_270].y;
1596                      w = m->indicator_widget_geometry[E_MOVE_ANGLE_270].w;
1597                      h = m->indicator_widget_geometry[E_MOVE_ANGLE_270].h;
1598                      break;
1599                   case 0:
1600                   default:
1601                      x = m->indicator_widget_geometry[E_MOVE_ANGLE_0].x;
1602                      y = m->indicator_widget_geometry[E_MOVE_ANGLE_0].y;
1603                      w = m->indicator_widget_geometry[E_MOVE_ANGLE_0].w;
1604                      h = m->indicator_widget_geometry[E_MOVE_ANGLE_0].h;
1605                      break;
1606                 }
1607               e_mod_move_widget_objs_move(indi_widget->objs, x, y);
1608               e_mod_move_widget_objs_resize(indi_widget->objs, w, h);
1609
1610               //change Input Shape Mask
1611               if (indi_widget->input_region_id)
1612                 {
1613                    e_manager_comp_input_region_id_set(m->man,
1614                                                       indi_widget->input_region_id,
1615                                                       x, y, w, h);
1616                 }
1617               ret = EINA_TRUE;
1618            }
1619      }
1620    return ret;
1621 }
1622
1623 EINTERN Eina_Bool
1624 e_mod_move_indicator_widget_scrollable_check(void)
1625 {
1626    E_Move_Border *lockscr_mb = NULL;
1627    E_Move_Border *taskmgr_mb = NULL;
1628    E_Move_Border *pwlock_mb = NULL;
1629
1630    // if lockscreen is exist & visible, then do not show  apptray & quickpanel
1631    if ((lockscr_mb = e_mod_move_lockscreen_find()))
1632      {
1633         if (lockscr_mb->visibility == E_MOVE_VISIBILITY_STATE_VISIBLE)
1634           {
1635              L(LT_EVENT_OBJ,
1636                "[MOVE] ev:%15.15s  %s %s()\n",
1637                "EVAS_OBJ","Lockscreen is exist.", __func__);
1638              return EINA_FALSE;
1639           }
1640      }
1641    // if taskmanage is exist & visible, then do not show  apptray & quickpanel
1642    if ((taskmgr_mb = e_mod_move_taskmanager_find()))
1643      {
1644         if (taskmgr_mb->visibility == E_MOVE_VISIBILITY_STATE_VISIBLE)
1645           {
1646              L(LT_EVENT_OBJ,
1647                "[MOVE] ev:%15.15s  %s %s()\n",
1648                "EVAS_OBJ","TaskManager is exist.", __func__);
1649              return EINA_FALSE;
1650           }
1651      }
1652
1653    // if pwlock is exist & visible, then do not show  apptray & quickpanel
1654    if ((pwlock_mb = e_mod_move_pwlock_find()))
1655      {
1656         if (pwlock_mb->visibility == E_MOVE_VISIBILITY_STATE_VISIBLE)
1657           {
1658              L(LT_EVENT_OBJ,
1659                "[MOVE] ev:%15.15s  %s %s()\n",
1660                "EVAS_OBJ","PWLOCK is exist.", __func__);
1661              return EINA_FALSE;
1662           }
1663      }
1664
1665    return EINA_TRUE;
1666 }
1667
1668 EINTERN Eina_Bool
1669 e_mod_move_indicator_widget_click_get(E_Move_Indicator_Widget* indi_widget)
1670 {
1671    Eina_Bool             click = EINA_FALSE;
1672    E_Move_Widget_Object *mwo = NULL;
1673    Eina_List             *l;
1674
1675    E_CHECK_RETURN(indi_widget, EINA_FALSE);
1676    E_CHECK_RETURN(indi_widget->objs, EINA_FALSE);
1677
1678    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
1679      {
1680         if (!mwo) continue;
1681         click = e_mod_move_event_click_get(mwo->event);
1682      }
1683
1684    return click;
1685 }
1686
1687 EINTERN Eina_Bool
1688 e_mod_move_indicator_widget_event_clear(E_Move_Indicator_Widget* indi_widget)
1689 {
1690    Eina_Bool             click = EINA_FALSE;
1691    E_Move_Widget_Object *mwo = NULL;
1692    Eina_List             *l;
1693    E_Move_Border         *mb = NULL;
1694
1695    E_CHECK_RETURN(indi_widget, EINA_FALSE);
1696    E_CHECK_RETURN(indi_widget->objs, EINA_FALSE);
1697
1698    click = e_mod_move_indicator_widget_click_get(indi_widget);
1699    E_CHECK_RETURN(click, EINA_FALSE);
1700
1701    EINA_LIST_FOREACH(indi_widget->objs, l, mwo)
1702      {
1703         if (!mwo) continue;
1704         e_mod_move_event_data_clear(mwo->event);
1705         e_mod_move_event_click_set(mwo->event, EINA_FALSE);
1706      }
1707
1708    _e_mod_move_indicator_widget_apptray_move_set(indi_widget, EINA_FALSE);
1709    _e_mod_move_indicator_widget_quickpanel_move_set(indi_widget, EINA_FALSE);
1710
1711    mb = e_mod_move_border_client_find(indi_widget->win);
1712    if (mb && mb->flick_data) e_mod_move_flick_data_free(mb);
1713    return EINA_TRUE;
1714 }
1715
1716 EINTERN Eina_Bool
1717 e_mod_move_indicator_widget_state_change(Ecore_X_Window win, Eina_Bool state)
1718 {
1719    E_Move_Indicator_Widget *indi_widget = NULL;
1720    E_Move_Border           *mb = NULL;
1721
1722    if ((indi_widget = e_mod_move_indicator_widget_get()))
1723      {
1724         if ((indi_widget->win == win)
1725             && (!state))
1726           {
1727              // indicator state disable -> delete current indicator widget
1728              e_mod_move_indicator_widget_del(indi_widget);
1729              e_mod_move_indicator_widget_set(NULL);
1730           }
1731      }
1732    else
1733      {
1734         mb = e_mod_move_border_client_find(win);
1735         if ((mb)
1736             && (mb->indicator_type == E_MOVE_INDICATOR_TYPE_1)
1737             && (state))
1738           e_mod_move_indicator_widget_apply();
1739      }
1740
1741    return EINA_TRUE;
1742 }
1743
1744 EINTERN Eina_Bool
1745 e_mod_move_indicator_widget_type_change(Ecore_X_Window win, E_Move_Indicator_Type type)
1746 {
1747    E_Move_Indicator_Widget *indi_widget = NULL;
1748    E_Move_Border           *mb = NULL;
1749
1750    if ((indi_widget = e_mod_move_indicator_widget_get()))
1751      {
1752         if ((indi_widget->win == win)
1753             && (type != E_MOVE_INDICATOR_TYPE_1))
1754           {
1755              // indicator type is not type_1 -> delete current indicator widget
1756              e_mod_move_indicator_widget_del(indi_widget);
1757              e_mod_move_indicator_widget_set(NULL);
1758 #if 1
1759              // change later
1760              e_mod_move_indicator_widget_apply();
1761 #endif
1762           }
1763      }
1764    else
1765      {
1766         mb = e_mod_move_border_client_find(win);
1767         if ((mb)
1768             && (mb->indicator_state == E_MOVE_INDICATOR_STATE_ON)
1769             && (type == E_MOVE_INDICATOR_TYPE_1))
1770           e_mod_move_indicator_widget_apply();
1771      }
1772
1773    return EINA_TRUE;
1774 }
1775
1776 EINTERN Eina_Bool
1777 e_mod_move_indicator_widget_angle_change_post_job(void)
1778 {
1779    E_Move_Indicator_Widget *indi_widget = NULL;
1780    E_Move_Border           *mb = NULL;
1781    E_Border                *bd = NULL;
1782    E_Zone                  *zone = NULL;
1783    int                      angle = 0;
1784    int                      x = 0, y = 0;
1785
1786    indi_widget = e_mod_move_indicator_widget_get();
1787    E_CHECK_RETURN(indi_widget, EINA_FALSE);
1788
1789    mb = e_mod_move_border_client_find(indi_widget->win);
1790    E_CHECK_RETURN(mb, EINA_FALSE);
1791
1792    bd = mb->bd;
1793    E_CHECK_RETURN(bd, EINA_FALSE);
1794
1795    zone = bd->zone;
1796    E_CHECK_RETURN(zone, EINA_FALSE);
1797
1798    angle = mb->angle;
1799
1800    if (e_mod_move_indicator_widget_click_get(indi_widget))
1801      {
1802          switch (angle)
1803            {
1804             case   0:
1805                x = zone->x;
1806                y = zone->y;
1807                break;
1808             case  90:
1809                x = zone->x;
1810                y = zone->y;
1811                break;
1812             case 180:
1813                x = zone->x + zone->w;
1814                y = zone->y + zone->h;
1815                break;
1816             case 270:
1817                x = zone->x + zone->w;
1818                y = zone->y + zone->h;
1819                break;
1820             default :
1821                break;
1822            }
1823      }
1824
1825    if (mb->flick_data)
1826      e_mod_move_flick_data_init(mb, x, y);
1827
1828    return EINA_TRUE;
1829 }