e_desk_area: remove use_desk_area config value
[platform/upstream/enlightenment.git] / src / bin / services / e_service_volume.c
1 #include "services/e_service_volume_intern.h"
2 #include "e_policy_private_data.h"
3 #include "e_client_intern.h"
4
5 #include <wayland-server.h>
6 #include <tzsh_server.h>
7
8 #define REGION_OBJS_FOREACH(l, o) \
9    EINA_LIST_FOREACH(_volume_region_objs[_volume_cur_angle_map], l, o)
10
11 #define REGION_OBJS_VISIBLE_CHANGE(V) \
12 do { \
13    Eina_List *l; \
14    Evas_Object *o; \
15    EINA_LIST_FOREACH(_volume_region_objs[_volume_cur_angle_map], l, o) \
16      { \
17         if (V) evas_object_show(o); \
18         else evas_object_hide(o); \
19      } \
20 } while(0)
21 #define REGION_OBJS_SHOW() REGION_OBJS_VISIBLE_CHANGE(EINA_TRUE)
22 #define REGION_OBJS_HIDE() REGION_OBJS_VISIBLE_CHANGE(EINA_FALSE)
23
24 /* private data for volume */
25 static struct wl_resource  *_volume_wl_touch = NULL;
26 static E_Client            *_volume_ec = NULL;
27 static Eina_List           *_volume_region_objs[E_POLICY_ANGLE_MAP_NUM];
28 static E_Policy_Angle_Map              _volume_cur_angle_map = E_POLICY_ANGLE_MAP_0;
29 static Eina_Bool            _volume_ec_ev_init = EINA_FALSE;
30
31 /* event handler */
32 static Ecore_Event_Handler *_rot_handler = NULL;
33 static E_Client_Hook       *_volume_del_hook = NULL;
34
35 EINTERN E_Client *
36 e_service_volume_client_get(void)
37 {
38    return _volume_ec;
39 }
40
41 static void
42 _volume_region_obj_cb_mouse_move(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
43 {
44    Evas_Event_Mouse_Move *e = event;
45
46    wl_touch_send_motion(_volume_wl_touch, e->timestamp, 0, // id 0 for the 1st figner
47                         wl_fixed_from_int(e->cur.canvas.x - _volume_ec->client.x),
48                         wl_fixed_from_int(e->cur.canvas.y - _volume_ec->client.y));
49 }
50
51 static void
52 _volume_region_obj_cb_mouse_down(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
53 {
54    Evas_Event_Mouse_Down *e = event;
55    uint32_t serial;
56    E_Comp_Wl_Client_Data *volume_cdata = e_client_cdata_get(_volume_ec);
57
58    serial = wl_display_next_serial(e_comp_wl->wl.disp);
59    wl_touch_send_down(_volume_wl_touch, serial, e->timestamp,
60                       volume_cdata->surface, 0,
61                       wl_fixed_from_int(e->canvas.x - _volume_ec->client.x),
62                       wl_fixed_from_int(e->canvas.y - _volume_ec->client.y));
63 }
64
65 static void
66 _volume_region_obj_cb_mouse_up(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
67 {
68    Evas_Event_Mouse_Up *e = event;
69    uint32_t serial;
70
71    serial = wl_display_next_serial(e_comp_wl->wl.disp);
72    wl_touch_send_up(_volume_wl_touch, serial, e->timestamp, 0);
73 }
74
75 static void
76 _volume_region_obj_cb_multi_down(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
77 {
78    Evas_Event_Multi_Down *e = event;
79    uint32_t serial;
80    E_Comp_Wl_Client_Data *volume_cdata = e_client_cdata_get(_volume_ec);
81
82    serial = wl_display_next_serial(e_comp_wl->wl.disp);
83    wl_touch_send_down(_volume_wl_touch, serial, e->timestamp,
84                       volume_cdata->surface, e->device,
85                       wl_fixed_from_int(e->canvas.x - _volume_ec->client.x),
86                       wl_fixed_from_int(e->canvas.y - _volume_ec->client.y));
87 }
88
89 static void
90 _volume_region_obj_cb_multi_up(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
91 {
92    Evas_Event_Multi_Up *e = event;
93    uint32_t serial;
94
95    serial = wl_display_next_serial(e_comp_wl->wl.disp);
96    wl_touch_send_up(_volume_wl_touch, serial, e->timestamp, e->device);
97 }
98
99 static void
100 _volume_region_obj_cb_multi_move(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
101 {
102    Evas_Event_Multi_Move *e = event;
103
104    wl_touch_send_motion(_volume_wl_touch, e->timestamp, e->device,
105                         wl_fixed_from_int(e->cur.canvas.x - _volume_ec->client.x),
106                         wl_fixed_from_int(e->cur.canvas.y - _volume_ec->client.y));
107 }
108
109 static void
110 _volume_client_evas_cb_show(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
111 {
112    /* show region objects in current rotation */
113    REGION_OBJS_SHOW();
114 }
115
116 static void
117 _volume_client_evas_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
118 {
119    /* hide region objects in current rotation */
120    REGION_OBJS_HIDE();
121 }
122
123 static void
124 _volume_client_evas_cb_move(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *volume_obj, void *event EINA_UNUSED)
125 {
126    Eina_List *l;
127    Eina_Rectangle *r;
128    Evas_Object *region_obj;
129    int x, y;
130
131    REGION_OBJS_FOREACH(l, region_obj)
132      {
133         r = evas_object_data_get(region_obj, "content_rect");
134         if (EINA_UNLIKELY(r == NULL))
135           continue;
136
137         evas_object_geometry_get(volume_obj, &x, &y, NULL, NULL);
138         evas_object_move(region_obj, x + r->x, y + r->y);
139      }
140 }
141
142 static void
143 _volume_client_evas_cb_restack(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
144 {
145    Eina_List *l;
146    Evas_Object *region_obj;
147
148    REGION_OBJS_FOREACH(l, region_obj)
149       evas_object_stack_above(region_obj, _volume_ec->frame);
150 }
151
152 static Eina_Bool
153 _region_objs_is_empty(void)
154 {
155    int i;
156
157    for (i = E_POLICY_ANGLE_MAP_0; i < E_POLICY_ANGLE_MAP_NUM; i++)
158      {
159         if (_volume_region_objs[i])
160           return EINA_FALSE;
161      }
162
163    return EINA_TRUE;
164 }
165
166 static void
167 _region_obj_del(Evas_Object *obj)
168 {
169    Eina_Rectangle *r;
170
171    r = evas_object_data_get(obj, "content_rect");
172    E_FREE_FUNC(r, eina_rectangle_free);
173    evas_object_del(obj);
174 }
175
176 static void
177 _region_objs_del(E_Policy_Angle_Map angle_map)
178 {
179    Evas_Object *obj;
180
181    EINA_LIST_FREE(_volume_region_objs[angle_map], obj)
182       _region_obj_del(obj);
183
184    if ((_volume_ec_ev_init) &&
185        (_region_objs_is_empty()))
186      {
187         _volume_ec_ev_init = EINA_FALSE;
188
189         evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_SHOW,
190                                        _volume_client_evas_cb_show);
191         evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_HIDE,
192                                        _volume_client_evas_cb_hide);
193         evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_MOVE,
194                                        _volume_client_evas_cb_move);
195         evas_object_event_callback_del(_volume_ec->frame, EVAS_CALLBACK_RESTACK,
196                                        _volume_client_evas_cb_restack);
197      }
198 }
199
200 static void
201 _volume_client_unset(void)
202 {
203    int i;
204
205    for (i = E_POLICY_ANGLE_MAP_0; i < E_POLICY_ANGLE_MAP_NUM; i++)
206      _region_objs_del(i);
207
208    E_FREE_FUNC(_rot_handler, ecore_event_handler_del);
209    E_FREE_FUNC(_volume_del_hook, e_client_hook_del);
210
211    _volume_wl_touch = NULL;
212    _volume_ec = NULL;
213 }
214
215 static void
216 _volume_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
217 {
218    if (EINA_UNLIKELY(!ec)) return;
219    if (EINA_LIKELY(_volume_ec != ec)) return;
220
221    ELOGF("VOLUME","Del Client", ec);
222
223    _volume_client_unset();
224 }
225
226 static Eina_Bool
227 _volume_client_cb_rot_done(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
228 {
229    E_Event_Client_Rotation_Change_End *e = event;
230    E_Policy_Angle_Map new_idx;
231
232    if (EINA_UNLIKELY(e == NULL))
233      goto end;
234
235    new_idx = e_policy_angle_map(_volume_ec->e.state.rot.ang.curr);
236    if (EINA_UNLIKELY(new_idx == -1))
237      goto end;
238
239    if (e->ec != _volume_ec)
240      goto end;
241
242    /* is new rotation same with previous? */
243    if (_volume_cur_angle_map == new_idx)
244      goto end;
245
246    /* hide region object in current rotation */
247    REGION_OBJS_HIDE();
248
249    /* update current rotation */
250    _volume_cur_angle_map = new_idx;
251
252    /* show region object in current rotation */
253    REGION_OBJS_SHOW();
254
255 end:
256    return ECORE_CALLBACK_RENEW;
257 }
258
259 EINTERN Eina_Bool
260 e_service_volume_client_set(E_Client *ec)
261 {
262    E_Layer layer;
263
264    if (!ec)
265      {
266         if (_volume_ec)
267           _volume_client_unset();
268
269         return EINA_TRUE;
270      }
271
272    if (_volume_ec)
273      {
274         ERR("Volume client is already registered."
275             "Multi volume service is not supported.");
276         return EINA_FALSE;
277      }
278
279    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
280
281    ELOGF("VOLUME","Set Client", ec);
282
283    _volume_ec = ec;
284    _volume_cur_angle_map = e_policy_angle_map(ec->e.state.rot.ang.curr);
285
286    /* repeat events for volume client. */
287    evas_object_repeat_events_set(ec->frame, EINA_TRUE);
288
289    _rot_handler =
290       ecore_event_handler_add(E_EVENT_CLIENT_ROTATION_CHANGE_END,
291                               (Ecore_Event_Handler_Cb)_volume_client_cb_rot_done,
292                               NULL);
293    _volume_del_hook =
294       e_client_hook_add(E_CLIENT_HOOK_DEL, _volume_hook_client_del, NULL);
295
296 #ifdef REFACTOR_DESK_AREA
297    // set volume layer
298    layer = e_client_layer_get(ec);
299 #else
300    // set volume layer
301    layer = e_client_desk_area_original_layer_get(ec);
302 #endif
303
304    if (E_POLICY_VOLUME_LAYER != layer)
305      {
306         e_client_layer_set(ec, E_POLICY_VOLUME_LAYER);
307      }
308
309    // set skip iconify
310    ec->exp_iconify.skip_iconify = 1;
311
312    return EINA_TRUE;
313 }
314
315 static Evas_Object *
316 _volume_content_region_obj_new(void)
317 {
318    Evas_Object *obj;
319
320    obj = evas_object_rectangle_add(evas_object_evas_get(_volume_ec->frame));
321
322    /* make it transparent */
323    evas_object_color_set(obj, 0, 0, 0, 0);
324
325    /* set stack of obj object on the volume object. */
326    evas_object_layer_set(obj, evas_object_layer_get(_volume_ec->frame));
327    evas_object_stack_above(obj, _volume_ec->frame);
328
329    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
330                                   _volume_region_obj_cb_mouse_move, NULL);
331    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
332                                   _volume_region_obj_cb_mouse_down, NULL);
333    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
334                                   _volume_region_obj_cb_mouse_up, NULL);
335    evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_DOWN,
336                                   _volume_region_obj_cb_multi_down, NULL);
337    evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_UP,
338                                   _volume_region_obj_cb_multi_up, NULL);
339    evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_MOVE,
340                                   _volume_region_obj_cb_multi_move, NULL);
341
342    return obj;
343 }
344
345 static void
346 _region_objs_tile_set(E_Policy_Angle_Map angle_map, Eina_Tiler *tiler)
347 {
348    Eina_List *objs_list, *l, *ll;
349    Eina_Iterator *it;
350    Eina_Rectangle *r, *cr;
351    Evas_Object *obj;
352    E_Zone *zone;
353    E_Desk *desk;
354
355    zone = e_comp_zone_find_by_ec(_volume_ec);
356    EINA_SAFETY_ON_NULL_RETURN(zone);
357
358    desk = e_desk_current_get(zone);
359    EINA_SAFETY_ON_NULL_RETURN(desk);
360
361    objs_list = _volume_region_objs[angle_map];
362    it = eina_tiler_iterator_new(tiler);
363    EINA_ITERATOR_FOREACH(it, r)
364      {
365         /* trying to reuse allocated object */
366         obj = eina_list_data_get(objs_list);
367         if (obj)
368           {
369              objs_list = eina_list_next(objs_list);
370              cr = evas_object_data_get(obj, "content_rect");
371              E_FREE_FUNC(cr, eina_rectangle_free);
372           }
373         else
374           {
375              obj = _volume_content_region_obj_new();
376              _volume_region_objs[angle_map] = eina_list_append(_volume_region_objs[angle_map], obj);
377              e_desk_smart_member_add(desk, obj);
378           }
379
380         INF("\t@@@@@ Region Set: %d %d %d %d", r->x, r->y, r->w, r->h);
381         /* set geometry of region object */
382         evas_object_move(obj, _volume_ec->client.x + r->x, _volume_ec->client.y + r->y);
383         evas_object_resize(obj, r->w, r->h);
384
385         /* store the value of reigon as a region object's data */
386         cr = eina_rectangle_new(r->x, r->y, r->w, r->h);
387         evas_object_data_set(obj, "content_rect", cr);
388
389         if (angle_map == _volume_cur_angle_map)
390           {
391              if (evas_object_visible_get(_volume_ec->frame))
392                evas_object_show(obj);
393           }
394      }
395    eina_iterator_free(it);
396
397    /* delete rest of objects after reusing */
398    EINA_LIST_FOREACH_SAFE(objs_list, l, ll, obj)
399      {
400         _region_obj_del(obj);
401         _volume_region_objs[angle_map] =
402            eina_list_remove_list(_volume_region_objs[angle_map], l);
403      }
404 }
405
406 static void
407 _volume_content_region_set(E_Policy_Angle_Map angle_map, Eina_Tiler *tiler)
408 {
409    if (!tiler)
410      {
411         _region_objs_del(angle_map);
412         return;
413      }
414
415    _region_objs_tile_set(angle_map, tiler);
416 }
417
418 static struct wl_resource *
419 _volume_wl_touch_resource_get(void)
420 {
421    Eina_List *l;
422    struct wl_client *wc;
423    struct wl_resource *res;
424    E_Comp_Wl_Client_Data *volume_cdata = e_client_cdata_get(_volume_ec);
425
426    if (_volume_wl_touch) goto end;
427
428    wc = wl_resource_get_client(volume_cdata->surface);
429    EINA_LIST_FOREACH(e_comp_wl->touch.resources, l, res)
430      {
431         if (wl_resource_get_client(res) != wc) continue;
432
433         _volume_wl_touch = res;
434         goto end;
435      }
436
437 end:
438    return _volume_wl_touch;
439 }
440
441 EINTERN Eina_Bool
442 e_service_volume_region_set(int type, int angle, Eina_Tiler *tiler)
443 {
444    E_Policy_Angle_Map angle_map;
445
446    if (EINA_UNLIKELY(!_volume_ec))
447      {
448         ERR("No registered volume client");
449         return EINA_FALSE;
450      }
451
452    angle_map = e_policy_angle_map(angle);
453    if (EINA_UNLIKELY(angle_map == -1))
454      return EINA_FALSE;
455
456    /* FIXME: use enum instead of constant */
457    if (EINA_UNLIKELY(type != 1))
458      {
459         ERR("Not supported region type %d", type);
460         return EINA_FALSE;
461      }
462
463    if (EINA_UNLIKELY(_volume_wl_touch_resource_get() == NULL))
464      {
465         ERR("Could not found wl_touch resource for volume");
466         return EINA_FALSE;
467      }
468
469    ELOGF("VOLUME","Content Region Set: angle %d, tiler %p",
470          NULL, angle, tiler);
471
472    _volume_content_region_set(angle_map, tiler);
473
474    if (!_volume_ec_ev_init)
475      {
476         _volume_ec_ev_init = EINA_TRUE;
477
478         evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_SHOW,
479                                        _volume_client_evas_cb_show, NULL);
480         evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_HIDE,
481                                        _volume_client_evas_cb_hide, NULL);
482         evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_MOVE,
483                                        _volume_client_evas_cb_move, NULL);
484         evas_object_event_callback_add(_volume_ec->frame, EVAS_CALLBACK_RESTACK,
485                                        _volume_client_evas_cb_restack, NULL);
486      }
487
488    return EINA_TRUE;
489 }