8bce9b90576efaf2c4db3f5cf87662841e89f781
[platform/core/api/efl-util.git] / src / efl_util.c
1 /*
2  * Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define LOG_TAG "TIZEN_N_EFL_UTIL"
18
19 #include <efl_util.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <xf86drm.h>
28 #include <tbm_bufmgr.h>
29 #include <tbm_surface.h>
30 #include <tbm_surface_internal.h>
31 #include <Elementary.h>
32 #include <Ecore_Evas.h>
33
34 #if X11
35 #include <X11/Xlib.h>
36 #include <X11/extensions/Xvlib.h>
37 #include <X11/extensions/Xvproto.h>
38 #include <X11/extensions/Xdamage.h>
39 #include <dri2.h>
40 #include <Ecore_X.h>
41 #include <utilX.h>
42 #endif /* end of X11 */
43
44 #if WAYLAND
45 #include <Ecore_Wayland.h>
46 #include <wayland-client.h>
47 #include <wayland-tbm-client.h>
48 #include <tizen-extension-client-protocol.h>
49 #include <screenshooter-client-protocol.h>
50 #endif /* end of WAYLAND */
51
52 /* callback handler index */
53 #define CBH_NOTI_LEV 0
54 #define CBH_SCR_MODE 1
55 #define CBH_MAX      2
56
57 typedef void (*Efl_Util_Cb)(Evas_Object *, int, void *);
58
59 typedef struct _Efl_Util_Callback_Info
60 {
61    Evas_Object *win;
62    Efl_Util_Cb cb;
63    void *data;
64 } Efl_Util_Callback_Info;
65
66 #if WAYLAND
67 typedef struct _Efl_Util_Wl_Surface_Lv_Info
68 {
69    void *surface; /* wl_surface */
70    int level;
71    Eina_Bool wait_for_done;
72    uint32_t state;
73 } Efl_Util_Wl_Surface_Lv_Info;
74
75 typedef struct _Efl_Util_Wl_Surface_Scr_Mode_Info
76 {
77    void *surface; /* wl_surface */
78    unsigned int mode;
79    Eina_Bool wait_for_done;
80    uint32_t state;
81 } Efl_Util_Wl_Surface_Scr_Mode_Info;
82
83 typedef struct _Efl_Util_Wl_Surface_Brightness_Info
84 {
85    void *surface; /* wl_surface */
86    int brightness;
87    Eina_Bool wait_for_done;
88    uint32_t state;
89 } Efl_Util_Wl_Surface_Brightness_Info;
90
91 typedef struct _Efl_Util_Wl_Output_Info
92 {
93     struct wl_output *output;
94     int offset_x, offset_y, width, height;
95 } Efl_Util_Wl_Output_Info;
96 #endif
97
98 typedef struct _Efl_Util_Data
99 {
100 #if X11
101    /* x11 related stuffs */
102    struct
103    {
104       Eina_Bool init;
105       Ecore_Event_Handler *handler; /* x11 client message handler */
106       Ecore_X_Display *dpy;
107    } x11;
108 #endif /* end of X11 */
109
110 #if WAYLAND
111    /* wayland related stuffs */
112    struct
113    {
114       Eina_Bool init;
115       struct wl_display *dpy;
116       struct wl_event_queue *queue;
117
118       struct
119       {
120          struct tizen_policy *proto;
121          Eina_Hash *hash_noti_lv;
122          Eina_Hash *hash_scr_mode;
123       } policy;
124       struct
125       {
126          struct screenshooter *screenshooter;
127          struct wayland_tbm_client *tbm_client;
128          Eina_List *output_list;
129       } shot;
130       struct
131       {
132          struct tizen_input_device_manager *devicemgr;
133          int request_notified;
134       } devmgr;
135       struct
136       {
137          struct tizen_display_policy *proto;
138          Eina_Hash *hash_brightness;
139       } display_policy;
140    } wl;
141 #endif /* end of WAYLAND */
142
143    struct
144    {
145       Eina_List *info_list; /* list of callback info */
146       unsigned int atom; /* x11 atom */
147    } cb_handler[CBH_MAX];
148 } Efl_Util_Data;
149
150 static Efl_Util_Data _eflutil =
151 {
152 #if X11
153    {
154       EINA_FALSE,
155       NULL,
156       NULL
157    },
158 #endif /* end of X11 */
159 #if WAYLAND
160    {
161       EINA_FALSE,
162       NULL, NULL,
163       { NULL, NULL, NULL }, /* tizen_policy protocol */
164       { NULL, NULL, NULL }, /* screenshooter protocol */
165       { NULL, -1 } /* tizen_input_device_manager protocol */
166    },
167 #endif /* end of WAYLAND */
168    {
169       { NULL, 0 }, /* handler for notification level */
170       { NULL, 0 }  /* handler for screen mode */
171    },
172 };
173
174 static Eina_Bool               _cb_info_add(Evas_Object *win, Efl_Util_Cb cb, void *data, int idx);
175 static Eina_Bool               _cb_info_del_by_win(Evas_Object *win, int idx);
176 static Eina_List              *_cb_info_list_get(int idx);
177 static Efl_Util_Callback_Info *_cb_info_find_by_win(Evas_Object *win, int idx);
178 #if X11
179 static Efl_Util_Callback_Info *_cb_info_find_by_xwin(unsigned int xwin, int idx);
180 static Eina_Bool               _cb_x11_client_msg(void *data, int type, void *event);
181 static Eina_Bool               _x11_init(void);
182 #endif /* end of X11 */
183 #if WAYLAND
184 static Eina_Bool               _wl_init(void);
185 static void                    _cb_wl_reg_global(void *data, struct wl_registry *reg, unsigned int name, const char *interface, unsigned int version);
186 static void                    _cb_wl_reg_global_remove(void *data, struct wl_registry *reg, unsigned int name);
187 static Efl_Util_Callback_Info *_cb_info_find_by_wlsurf(void *wlsurf, int idx);
188 static void                    _cb_wl_tz_policy_conformant(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface, uint32_t is_conformant);
189 static void                    _cb_wl_tz_policy_conformant_area(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface, uint32_t conformant_part, uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h);
190 static void                    _cb_wl_tz_policy_notification_done(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface, int32_t level, uint32_t state);
191 static void                    _cb_wl_tz_policy_transient_for_done(void *data, struct tizen_policy *tizen_policy, uint32_t child_id);
192 static void                    _cb_wl_tz_policy_scr_mode_done(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface, uint32_t mode, uint32_t state);
193 static void                    _cb_wl_tz_policy_iconify_state_changed(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface_resource, uint32_t iconified, uint32_t force);
194 static void                    _cb_wl_tz_policy_supported_aux_hints(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface_resource, struct wl_array *hints, uint32_t num_hints);
195 static void                    _cb_wl_tz_policy_allowed_aux_hint(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface_resource, int id);
196
197 static void                    _cb_wl_tz_display_policy_brightness_done(void *data, struct tizen_display_policy *tizen_display_policy, struct wl_surface *surface_resource, int32_t brightness, uint32_t state);
198
199 static void                    _cb_device_add(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t serial  EINA_UNUSED, const char *identifier  EINA_UNUSED, struct tizen_input_device *device  EINA_UNUSED, struct wl_seat *seat EINA_UNUSED);
200 static void                    _cb_device_remove(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t serial EINA_UNUSED, const char *identifier  EINA_UNUSED, struct tizen_input_device *device EINA_UNUSED, struct wl_seat *seat EINA_UNUSED);
201 static void                    _cb_error(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED, uint32_t errorcode);
202 static void                    _cb_block_expired(void *data EINA_UNUSED, struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED);
203
204 static const struct wl_registry_listener _wl_reg_listener =
205 {
206    _cb_wl_reg_global,
207    _cb_wl_reg_global_remove
208 };
209
210 struct tizen_policy_listener _wl_tz_policy_listener =
211 {
212    _cb_wl_tz_policy_conformant,
213    _cb_wl_tz_policy_conformant_area,
214    _cb_wl_tz_policy_notification_done,
215    _cb_wl_tz_policy_transient_for_done,
216    _cb_wl_tz_policy_scr_mode_done,
217    _cb_wl_tz_policy_iconify_state_changed,
218    _cb_wl_tz_policy_supported_aux_hints,
219    _cb_wl_tz_policy_allowed_aux_hint,
220 };
221
222 struct tizen_input_device_manager_listener _wl_tz_devmgr_listener =
223 {
224    _cb_device_add,
225    _cb_device_remove,
226    _cb_error,
227    _cb_block_expired
228 };
229
230 struct tizen_display_policy_listener _wl_tz_display_policy_listener =
231 {
232    _cb_wl_tz_display_policy_brightness_done,
233 };
234 #endif /* end of WAYLAND */
235
236 static Eina_Bool
237 _cb_info_add(Evas_Object *win,
238              Efl_Util_Cb cb,
239              void *data,
240              int idx)
241 {
242    Efl_Util_Callback_Info *info;
243
244    info = _cb_info_find_by_win(win, idx);
245    if (info)
246      {
247         _eflutil.cb_handler[idx].info_list
248            = eina_list_remove(_eflutil.cb_handler[idx].info_list,
249                               info);
250         free(info);
251      }
252
253    info = (Efl_Util_Callback_Info *)calloc(1, sizeof(Efl_Util_Callback_Info));
254    if (!info) return EINA_FALSE;
255
256    info->win = win;
257    info->cb = cb;
258    info->data = data;
259
260    _eflutil.cb_handler[idx].info_list
261       = eina_list_append(_eflutil.cb_handler[idx].info_list,
262                          info);
263
264 #if X11
265    if (!_eflutil.x11.handler)
266      _eflutil.x11.handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
267                                                     _cb_x11_client_msg,
268                                                     NULL);
269 #endif /* end of X11 */
270
271    return EINA_TRUE;
272 }
273
274 static Eina_Bool
275 _cb_info_del_by_win(Evas_Object *win,
276                     int idx)
277 {
278    Efl_Util_Callback_Info *info;
279
280    info = _cb_info_find_by_win(win, idx);
281    if (!info) return EINA_FALSE;
282
283    _eflutil.cb_handler[idx].info_list
284       = eina_list_remove(_eflutil.cb_handler[idx].info_list,
285                          info);
286    free(info);
287
288 #if X11
289    unsigned int count = eina_list_count(_eflutil.cb_handler[idx].info_list);
290    if ((count == 0) && (_eflutil.x11.handler))
291      {
292         ecore_event_handler_del(_eflutil.x11.handler);
293         _eflutil.x11.handler = NULL;
294      }
295 #endif
296
297    return EINA_TRUE;
298 }
299
300 static Eina_List *
301 _cb_info_list_get(int idx)
302 {
303    return _eflutil.cb_handler[idx].info_list;
304 }
305
306 static Efl_Util_Callback_Info *
307 _cb_info_find_by_win(Evas_Object *win,
308                      int idx)
309 {
310    Eina_List *l, *ll;
311    Efl_Util_Callback_Info *info;
312
313    l = _cb_info_list_get(idx);
314    EINA_LIST_FOREACH(l, ll, info)
315      {
316         if (info->win == win) return info;
317      }
318
319    return NULL;
320 }
321
322 #if X11
323 static Efl_Util_Callback_Info *
324 _cb_info_find_by_xwin(unsigned int xwin,
325                       int idx)
326 {
327    Eina_List *l, *ll;
328    Efl_Util_Callback_Info *info;
329    unsigned int xwin2;
330
331    l = _cb_info_list_get(idx);
332    EINA_LIST_FOREACH(l, ll, info)
333      {
334         xwin2 = elm_win_xwindow_get(info->win);
335         if (xwin == xwin2) return info;
336      }
337
338    return NULL;
339 }
340
341 static Eina_Bool
342 _cb_x11_client_msg(void *data,
343                    int type,
344                    void *event)
345 {
346    Ecore_X_Event_Client_Message *ev;
347    Ecore_X_Window xwin;
348    Efl_Util_Callback_Info *info;
349
350    ev = event;
351    if (!ev) return ECORE_CALLBACK_PASS_ON;
352
353    xwin = ev->win;
354    if (xwin == 0) return ECORE_CALLBACK_PASS_ON;
355
356    if (ev->message_type == _eflutil.cb_handler[CBH_NOTI_LEV].atom)
357      {
358         info = _cb_info_find_by_xwin(xwin, CBH_NOTI_LEV);
359
360         /* permission denied */
361         if ((ev->data.l[1] == 0) &&
362             (info) &&
363             (info->cb))
364           {
365              info->cb(info->win,
366                       EFL_UTIL_ERROR_PERMISSION_DENIED,
367                       info->data);
368           }
369      }
370    else if (ev->message_type == _eflutil.cb_handler[CBH_SCR_MODE].atom)
371      {
372         info = _cb_info_find_by_xwin(xwin, CBH_SCR_MODE);
373
374         /* permission denied */
375         if ((ev->data.l[1] == 0) &&
376             (info) &&
377             (info->cb))
378           {
379              info->cb(info->win,
380                       EFL_UTIL_ERROR_PERMISSION_DENIED,
381                       info->data);
382           }
383      }
384    return ECORE_CALLBACK_PASS_ON;
385 }
386
387 static Eina_Bool
388 _x11_init(void)
389 {
390    if (_eflutil.x11.init) return EINA_TRUE;
391
392    _eflutil.x11.dpy = ecore_x_display_get();
393    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.x11.dpy, EINA_FALSE);
394
395    _eflutil.x11.init = EINA_TRUE;
396
397    return EINA_TRUE;
398 }
399 #endif /* end of X11 */
400
401 #if WAYLAND
402 static Eina_Bool
403 _wl_init(void)
404 {
405    struct wl_registry *reg = NULL;
406
407    if (_eflutil.wl.init) return EINA_TRUE;
408
409    ecore_wl_init(NULL);
410
411    _eflutil.wl.dpy = ecore_wl_display_get();
412    EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.dpy, fail);
413
414    _eflutil.wl.queue = wl_display_create_queue(_eflutil.wl.dpy);
415    EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.queue, fail);
416
417    reg = wl_display_get_registry(_eflutil.wl.dpy);
418    EINA_SAFETY_ON_NULL_GOTO(reg, fail);
419
420    wl_proxy_set_queue((struct wl_proxy*)reg, _eflutil.wl.queue);
421    wl_registry_add_listener(reg, &_wl_reg_listener, NULL);
422
423    _eflutil.wl.init = EINA_TRUE;
424
425    return EINA_TRUE;
426 fail:
427    if (_eflutil.wl.queue)
428      {
429         wl_event_queue_destroy(_eflutil.wl.queue);
430         _eflutil.wl.queue = NULL;
431      }
432
433    if (reg)
434      wl_registry_destroy(reg);
435    ecore_wl_shutdown();
436    return EINA_FALSE;
437 }
438
439 static void
440 _cb_wl_output_geometry(void *data, struct wl_output *wl_output, int x, int y,
441                        int physical_width, int physical_height, int subpixel,
442                        const char *make, const char *model, int transform)
443 {
444    Efl_Util_Wl_Output_Info *output = wl_output_get_user_data(wl_output);
445    if (wl_output == output->output)
446      {
447         output->offset_x = x;
448         output->offset_y = y;
449      }
450 }
451
452 static void
453 _cb_wl_output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
454                    int width, int height, int refresh)
455 {
456    Efl_Util_Wl_Output_Info *output = wl_output_get_user_data(wl_output);
457    if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT))
458      {
459         output->width = width;
460         output->height = height;
461      }
462 }
463
464 static void
465 _cb_wl_output_done(void *data, struct wl_output *wl_output)
466 {
467 }
468
469 static void
470 _cb_wl_output_scale(void *data, struct wl_output *wl_output, int32_t factor)
471 {
472 }
473
474 static const struct wl_output_listener output_listener =
475 {
476     _cb_wl_output_geometry,
477     _cb_wl_output_mode,
478     _cb_wl_output_done,
479     _cb_wl_output_scale
480 };
481
482 static void
483 _cb_wl_screenshot_done(void *data, struct screenshooter *screenshooter)
484 {
485    Eina_Bool *shot_done = (Eina_Bool*)data;
486    if (shot_done)
487      *shot_done = EINA_TRUE;
488 }
489
490 static const struct screenshooter_listener screenshooter_listener =
491 {
492     _cb_wl_screenshot_done
493 };
494
495 static void
496 _cb_wl_reg_global(void *data,
497                   struct wl_registry *reg,
498                   unsigned int name,
499                   const char *interface,
500                   unsigned int version)
501 {
502    if (!strcmp(interface, "tizen_policy"))
503      {
504         struct tizen_policy *proto;
505         proto = wl_registry_bind(reg,
506                                   name,
507                                   &tizen_policy_interface,
508                                   1);
509         if (!proto) return;
510
511         tizen_policy_add_listener(proto,
512                                   &_wl_tz_policy_listener,
513                                   NULL);
514
515         _eflutil.wl.policy.hash_noti_lv = eina_hash_pointer_new(free);
516         _eflutil.wl.policy.hash_scr_mode = eina_hash_pointer_new(free);
517         _eflutil.wl.policy.proto = proto;
518      }
519    else if (strcmp(interface, "wl_output") == 0)
520      {
521         Efl_Util_Wl_Output_Info *output = calloc(1, sizeof(Efl_Util_Wl_Output_Info));
522         EINA_SAFETY_ON_NULL_RETURN(output);
523
524         _eflutil.wl.shot.output_list = eina_list_append(_eflutil.wl.shot.output_list, output);
525
526         output->output = wl_registry_bind(reg, name, &wl_output_interface, version);
527         wl_output_add_listener(output->output, &output_listener, output);
528      }
529    else if (strcmp(interface, "screenshooter") == 0)
530      {
531         _eflutil.wl.shot.screenshooter = wl_registry_bind(reg, name, &screenshooter_interface, version);
532         screenshooter_add_listener(_eflutil.wl.shot.screenshooter, &screenshooter_listener, NULL);
533      }
534    else if (strcmp(interface, "tizen_input_device_manager") == 0)
535      {
536         _eflutil.wl.devmgr.devicemgr = wl_registry_bind(reg, name, &tizen_input_device_manager_interface, version);
537         tizen_input_device_manager_add_listener(_eflutil.wl.devmgr.devicemgr, &_wl_tz_devmgr_listener, NULL);
538      }
539    else if (!strcmp(interface, "tizen_display_policy"))
540      {
541         _eflutil.wl.display_policy.proto = wl_registry_bind(reg, name, &tizen_display_policy_interface, version);
542         if (!_eflutil.wl.display_policy.proto) return;
543
544         tizen_display_policy_add_listener(_eflutil.wl.display_policy.proto,
545                                           &_wl_tz_display_policy_listener,
546                                           NULL);
547
548         _eflutil.wl.display_policy.hash_brightness = eina_hash_pointer_new(free);
549      }
550
551 }
552
553 static void
554 _cb_wl_reg_global_remove(void *data,
555                          struct wl_registry *reg,
556                          unsigned int name)
557 {
558    _eflutil.wl.policy.proto = NULL;
559    eina_hash_free(_eflutil.wl.policy.hash_noti_lv);
560    eina_hash_free(_eflutil.wl.policy.hash_scr_mode);
561
562    _eflutil.wl.display_policy.proto = NULL;
563    eina_hash_free(_eflutil.wl.display_policy.hash_brightness);
564 }
565
566 static Efl_Util_Callback_Info *
567 _cb_info_find_by_wlsurf(void *wlsurf,
568                         int idx)
569 {
570    Eina_List *l, *ll;
571    Efl_Util_Callback_Info *info;
572    Ecore_Wl_Window *wlwin2 = NULL;
573    void *wlsurf2 = NULL;
574
575    l = _cb_info_list_get(idx);
576    EINA_LIST_FOREACH(l, ll, info)
577      {
578         wlwin2 = elm_win_wl_window_get(info->win);
579         wlsurf2 = ecore_wl_window_surface_get(wlwin2);
580         if (wlsurf== wlsurf2) return info;
581      }
582
583    return NULL;
584 }
585
586 static void
587 _cb_wl_tz_policy_conformant(void *data, struct tizen_policy *tizen_policy,
588                             struct wl_surface *surface, uint32_t is_conformant)
589 {
590 }
591
592 static void
593 _cb_wl_tz_policy_conformant_area(void *data, struct tizen_policy *tizen_policy,
594                                  struct wl_surface *surface, uint32_t conformant_part,
595                                  uint32_t state, int32_t x, int32_t y, int32_t w, int32_t h)
596 {
597 }
598
599 static void
600 _cb_wl_tz_policy_notification_done(void *data,
601                                    struct tizen_policy *tizen_policy,
602                                    struct wl_surface *surface,
603                                    int32_t level,
604                                    uint32_t state)
605 {
606    Efl_Util_Wl_Surface_Lv_Info *lv_info;
607    Efl_Util_Callback_Info *cb_info;
608
609    lv_info = eina_hash_find(_eflutil.wl.policy.hash_noti_lv, &surface);
610    if (lv_info)
611      {
612         lv_info->level = level;
613         lv_info->wait_for_done = EINA_FALSE;
614         lv_info->state = state;
615      }
616
617    if (state != TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED) return;
618
619    cb_info = _cb_info_find_by_wlsurf((void *)surface, CBH_NOTI_LEV);
620    if (!cb_info) return;
621    if (!cb_info->cb) return;
622
623    cb_info->cb(cb_info->win,
624                EFL_UTIL_ERROR_PERMISSION_DENIED,
625                cb_info->data);
626 }
627
628 static void
629 _cb_wl_tz_policy_transient_for_done(void *data, struct tizen_policy *tizen_policy, uint32_t child_id)
630 {
631 }
632
633 static void
634 _cb_wl_tz_policy_scr_mode_done(void *data,
635                                struct tizen_policy *tizen_policy,
636                                struct wl_surface *surface,
637                                uint32_t mode,
638                                uint32_t state)
639 {
640
641    Efl_Util_Wl_Surface_Scr_Mode_Info *scr_mode_info;
642    Efl_Util_Callback_Info *cb_info;
643
644    scr_mode_info = eina_hash_find(_eflutil.wl.policy.hash_scr_mode, &surface);
645    if (scr_mode_info)
646      {
647         scr_mode_info->mode = mode;
648         scr_mode_info->wait_for_done = EINA_FALSE;
649         scr_mode_info->state = state;
650      }
651
652    if (state != TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED) return;
653
654    cb_info = _cb_info_find_by_wlsurf((void *)surface, CBH_SCR_MODE);
655    if (!cb_info) return;
656    if (!cb_info->cb) return;
657
658    cb_info->cb(cb_info->win,
659                EFL_UTIL_ERROR_PERMISSION_DENIED,
660                cb_info->data);
661 }
662
663 static void                    _cb_wl_tz_policy_iconify_state_changed(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface_resource, uint32_t iconified, uint32_t force)
664 {
665 }
666
667 static void                    _cb_wl_tz_policy_supported_aux_hints(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface_resource, struct wl_array *hints, uint32_t num_hints)
668 {
669 }
670
671 static void                    _cb_wl_tz_policy_allowed_aux_hint(void *data, struct tizen_policy *tizen_policy, struct wl_surface *surface_resource, int id)
672 {
673 }
674
675 static void
676 _cb_wl_tz_display_policy_brightness_done(void *data,
677                                  struct tizen_display_policy *tizen_display_policy,
678                                  struct wl_surface *surface,
679                                  int32_t brightness,
680                                  uint32_t state)
681 {
682    Efl_Util_Wl_Surface_Brightness_Info *brightness_info;
683
684    brightness_info = eina_hash_find(_eflutil.wl.display_policy.hash_brightness, &surface);
685    if (brightness_info)
686      {
687         brightness_info->brightness = brightness;
688         brightness_info->wait_for_done = EINA_FALSE;
689         brightness_info->state = state;
690      }
691 }
692
693 static void
694 _cb_window_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
695 {
696    Efl_Util_Wl_Surface_Lv_Info *lv_info;
697
698    lv_info = data;
699    if (EINA_UNLIKELY(!lv_info))
700      return;
701
702    eina_hash_del(_eflutil.wl.policy.hash_noti_lv, &lv_info->surface, lv_info);
703 }
704 #endif /* end of WAYLAND */
705
706 API int
707 efl_util_set_notification_window_level(Evas_Object *window,
708                                        efl_util_notification_level_e level)
709 {
710    Eina_Bool res;
711
712    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
713    EINA_SAFETY_ON_FALSE_RETURN_VAL((level >= EFL_UTIL_NOTIFICATION_LEVEL_NONE) &&
714                                    (level <= EFL_UTIL_NOTIFICATION_LEVEL_TOP),
715                                    EFL_UTIL_ERROR_INVALID_PARAMETER);
716
717 #if X11
718    Ecore_X_Window_Type window_type;
719    Ecore_X_Window xwin;
720
721    res = _x11_init();
722    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
723
724    xwin = elm_win_xwindow_get(window);
725    if (xwin)
726      {
727         if (ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
728           {
729              // success to get window type
730              if (window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
731                {
732                   // given EFL window's type is not notification type.
733                   return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
734                }
735           }
736         else
737           return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
738
739         utilx_set_system_notification_level(_eflutil.x11.dpy,
740                                             xwin,
741                                             level);
742         return EFL_UTIL_ERROR_NONE;
743      }
744
745    return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
746 #endif /* end of X11 */
747
748 #if WAYLAND
749    Elm_Win_Type type;
750    Ecore_Wl_Window *wlwin;
751    struct wl_surface *surface;
752    Efl_Util_Wl_Surface_Lv_Info *lv_info;
753    Ecore_Wl_Window_Type wl_type;
754
755    res = _wl_init();
756    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
757
758    wlwin = elm_win_wl_window_get(window);
759    EINA_SAFETY_ON_NULL_RETURN_VAL(wlwin, EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
760
761    type = elm_win_type_get(window);
762    if (type != ELM_WIN_NOTIFICATION)
763      {
764         wl_type = ecore_wl_window_type_get(wlwin);
765         EINA_SAFETY_ON_FALSE_RETURN_VAL((wl_type == ECORE_WL_WINDOW_TYPE_NOTIFICATION),
766                                         EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
767      }
768
769    while (!_eflutil.wl.policy.proto)
770      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
771
772    surface = ecore_wl_window_surface_get(wlwin);
773    EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
774                                   EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
775
776    lv_info = eina_hash_find(_eflutil.wl.policy.hash_noti_lv, &surface);
777    if (!lv_info)
778      {
779         lv_info = calloc(1, sizeof(Efl_Util_Wl_Surface_Lv_Info));
780         EINA_SAFETY_ON_NULL_RETURN_VAL(lv_info, EFL_UTIL_ERROR_OUT_OF_MEMORY);
781
782         lv_info->surface = surface;
783         lv_info->level = (int)level;
784         lv_info->wait_for_done = EINA_TRUE;
785         lv_info->state = TIZEN_POLICY_ERROR_STATE_NONE;
786         eina_hash_add(_eflutil.wl.policy.hash_noti_lv,
787                       &surface,
788                       lv_info);
789
790         evas_object_event_callback_add(window, EVAS_CALLBACK_DEL,
791                                        _cb_window_del, lv_info);
792      }
793    else
794      {
795         lv_info->level = (int)level;
796         lv_info->wait_for_done = EINA_TRUE;
797         lv_info->state = TIZEN_POLICY_ERROR_STATE_NONE;
798      }
799
800
801    tizen_policy_set_notification_level(_eflutil.wl.policy.proto,
802                                        surface, (int)level);
803
804    if (lv_info->wait_for_done)
805      {
806         int count = 0;
807         while (lv_info->wait_for_done && (count < 3))
808           {
809              ecore_wl_flush();
810              wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
811              count++;
812           }
813
814         if (lv_info->wait_for_done)
815           {
816              return EFL_UTIL_ERROR_INVALID_PARAMETER;
817           }
818         else
819           {
820              if (lv_info->state == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
821                {
822                   return EFL_UTIL_ERROR_PERMISSION_DENIED;
823                }
824           }
825      }
826
827    return EFL_UTIL_ERROR_NONE;
828 #endif /* end of WAYLAND */
829 }
830
831 API int
832 efl_util_get_notification_window_level(Evas_Object *window,
833                                        efl_util_notification_level_e *level)
834 {
835    Eina_Bool res;
836
837    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
838    EINA_SAFETY_ON_NULL_RETURN_VAL(level, EFL_UTIL_ERROR_INVALID_PARAMETER);
839
840 #if X11
841    Ecore_X_Window_Type window_type;
842    Utilx_Notification_Level utilx_level;
843    Ecore_X_Window xwin;
844
845    res = _x11_init();
846    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
847
848    xwin = elm_win_xwindow_get(window);
849    if (xwin)
850      {
851         if (ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
852           {
853              // success to get window type
854              if (window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
855                {
856                   // given EFL window's type is not notification type.
857                   return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
858                }
859
860              utilx_level = utilx_get_system_notification_level(_eflutil.x11.dpy, xwin);
861              if (utilx_level == UTILX_NOTIFICATION_LEVEL_LOW)
862                *level = EFL_UTIL_NOTIFICATION_LEVEL_1;
863              else if(utilx_level == UTILX_NOTIFICATION_LEVEL_NORMAL)
864                *level = EFL_UTIL_NOTIFICATION_LEVEL_2;
865              else if(utilx_level == UTILX_NOTIFICATION_LEVEL_HIGH)
866                *level = EFL_UTIL_NOTIFICATION_LEVEL_3;
867              else
868                return EFL_UTIL_ERROR_INVALID_PARAMETER;
869           }
870         else
871           return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
872
873         return EFL_UTIL_ERROR_NONE;
874      }
875
876    return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
877 #endif /* end of X11 */
878
879 #if WAYLAND
880    Elm_Win_Type type;
881    Ecore_Wl_Window *wlwin;
882    struct wl_surface *surface;
883    Efl_Util_Wl_Surface_Lv_Info *lv_info;
884    Ecore_Wl_Window_Type wl_type;
885
886    res = _wl_init();
887    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
888
889    wlwin = elm_win_wl_window_get(window);
890    EINA_SAFETY_ON_NULL_RETURN_VAL(wlwin, EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
891
892    type = elm_win_type_get(window);
893    if (type != ELM_WIN_NOTIFICATION)
894      {
895         wl_type = ecore_wl_window_type_get(wlwin);
896         EINA_SAFETY_ON_FALSE_RETURN_VAL((wl_type == ECORE_WL_WINDOW_TYPE_NOTIFICATION),
897                                         EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
898      }
899
900    while (!_eflutil.wl.policy.proto)
901      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
902
903    surface = ecore_wl_window_surface_get(wlwin);
904    EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
905                                   EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
906
907    lv_info = eina_hash_find(_eflutil.wl.policy.hash_noti_lv, &surface);
908    if (lv_info)
909      {
910         if (lv_info->wait_for_done)
911           {
912              int count = 0;
913              while ((lv_info->wait_for_done) && (count < 3))
914                {
915                   ecore_wl_flush();
916                   wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
917                   count++;
918                }
919
920              if (lv_info->wait_for_done)
921                {
922                   *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
923                   return EFL_UTIL_ERROR_INVALID_PARAMETER;
924                }
925           }
926
927         switch (lv_info->level)
928           {
929            case TIZEN_POLICY_LEVEL_1:       *level = EFL_UTIL_NOTIFICATION_LEVEL_1;       break;
930            case TIZEN_POLICY_LEVEL_2:       *level = EFL_UTIL_NOTIFICATION_LEVEL_2;       break;
931            case TIZEN_POLICY_LEVEL_3:       *level = EFL_UTIL_NOTIFICATION_LEVEL_3;       break;
932            case TIZEN_POLICY_LEVEL_NONE:    *level = EFL_UTIL_NOTIFICATION_LEVEL_NONE;    break;
933            case TIZEN_POLICY_LEVEL_DEFAULT: *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT; break;
934            case TIZEN_POLICY_LEVEL_MEDIUM:  *level = EFL_UTIL_NOTIFICATION_LEVEL_MEDIUM;  break;
935            case TIZEN_POLICY_LEVEL_HIGH:    *level = EFL_UTIL_NOTIFICATION_LEVEL_HIGH;    break;
936            case TIZEN_POLICY_LEVEL_TOP:     *level = EFL_UTIL_NOTIFICATION_LEVEL_TOP;     break;
937            default:                         *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
938             return EFL_UTIL_ERROR_INVALID_PARAMETER;
939           }
940         return EFL_UTIL_ERROR_NONE;
941      }
942    else
943      *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
944
945    return EFL_UTIL_ERROR_NONE;
946 #endif /* end of WAYLAND */
947 }
948
949 API int
950 efl_util_set_notification_window_level_error_cb(Evas_Object *window,
951                                                 efl_util_notification_window_level_error_cb callback,
952                                                 void *user_data)
953 {
954    Eina_Bool ret = EINA_FALSE;
955
956    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
957    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EFL_UTIL_ERROR_INVALID_PARAMETER);
958
959    ret = _cb_info_add(window,
960                       (Efl_Util_Cb)callback,
961                       user_data,
962                       CBH_NOTI_LEV);
963    if (!ret) return EFL_UTIL_ERROR_OUT_OF_MEMORY;
964
965 #if X11
966    if (!_eflutil.cb_handler[CBH_NOTI_LEV].atom)
967      _eflutil.cb_handler[CBH_NOTI_LEV].atom = ecore_x_atom_get("_E_NOTIFICATION_LEVEL_ACCESS_RESULT");
968 #endif /* end of X11 */
969
970    return EFL_UTIL_ERROR_NONE;
971 }
972
973 API int
974 efl_util_unset_notification_window_level_error_cb(Evas_Object *window)
975 {
976    Eina_Bool ret = EINA_FALSE;
977
978    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
979
980    ret = _cb_info_del_by_win(window, CBH_NOTI_LEV);
981    if (!ret) return EFL_UTIL_ERROR_INVALID_PARAMETER;
982
983    return EFL_UTIL_ERROR_NONE;
984 }
985
986 API int
987 efl_util_set_window_opaque_state(Evas_Object *window,
988                                  int opaque)
989 {
990    Eina_Bool res;
991
992    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
993    EINA_SAFETY_ON_FALSE_RETURN_VAL(((opaque >= 0) && (opaque <= 1)),
994                                    EFL_UTIL_ERROR_INVALID_PARAMETER);
995
996 #if X11
997    Ecore_X_Window xwin;
998    Utilx_Opaque_State state;
999    int ret;
1000
1001    res = _x11_init();
1002    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1003
1004    xwin = elm_win_xwindow_get(window);
1005    EINA_SAFETY_ON_FALSE_RETURN_VAL(xwin > 0, EFL_UTIL_ERROR_INVALID_PARAMETER);
1006
1007    if (opaque)
1008      state = UTILX_OPAQUE_STATE_ON;
1009    else
1010      state = UTILX_OPAQUE_STATE_OFF;
1011
1012    ret = utilx_set_window_opaque_state(_eflutil.x11.dpy,
1013                                        xwin,
1014                                        state);
1015
1016    if (!ret)
1017      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1018    else
1019      return EFL_UTIL_ERROR_NONE;
1020 #endif /* end of X11 */
1021
1022 #if WAYLAND
1023    Ecore_Wl_Window *wlwin;
1024    struct wl_surface *surface;
1025
1026    if (!_eflutil.wl.policy.proto)
1027      {
1028         int ret = 0;
1029
1030         res = _wl_init();
1031         EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1032
1033         while (!_eflutil.wl.policy.proto && ret != -1)
1034           ret = wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1035
1036         EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.policy.proto, EFL_UTIL_ERROR_INVALID_PARAMETER);
1037      }
1038
1039    wlwin = elm_win_wl_window_get(window);
1040    if (!wlwin)
1041       return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
1042
1043    surface  = ecore_wl_window_surface_get(wlwin);
1044    if (!surface)
1045       return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
1046
1047    tizen_policy_set_opaque_state(_eflutil.wl.policy.proto, surface, opaque);
1048
1049    return EFL_UTIL_ERROR_NONE;
1050 #endif /* end of WAYLAND */
1051 }
1052
1053 API int
1054 efl_util_set_window_screen_mode(Evas_Object *window,
1055                                 efl_util_screen_mode_e mode)
1056 {
1057    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1058    EINA_SAFETY_ON_FALSE_RETURN_VAL(((mode >= EFL_UTIL_SCREEN_MODE_DEFAULT) &&
1059                                     (mode <= EFL_UTIL_SCREEN_MODE_ALWAYS_ON)),
1060                                    EFL_UTIL_ERROR_INVALID_PARAMETER);
1061
1062 #if X11
1063    Evas *e;
1064    Ecore_Evas *ee;
1065    int id;
1066
1067    e = evas_object_evas_get(window);
1068    EINA_SAFETY_ON_NULL_RETURN_VAL(e, EFL_UTIL_ERROR_INVALID_PARAMETER);
1069
1070    ee = ecore_evas_ecore_evas_get(e);
1071    EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EFL_UTIL_ERROR_INVALID_PARAMETER);
1072
1073    id = ecore_evas_aux_hint_id_get(ee, "wm.policy.win.lcd.lock");
1074    if (mode == EFL_UTIL_SCREEN_MODE_ALWAYS_ON)
1075      {
1076         if (id == -1)
1077           ecore_evas_aux_hint_add(ee, "wm.policy.win.lcd.lock", "1");
1078         else
1079           ecore_evas_aux_hint_val_set(ee, id, "1");
1080      }
1081    else if (mode == EFL_UTIL_SCREEN_MODE_DEFAULT)
1082      {
1083         if (id == -1)
1084           ecore_evas_aux_hint_add(ee, "wm.policy.win.lcd.lock", "0");
1085         else
1086           ecore_evas_aux_hint_val_set(ee, id, "0");
1087      }
1088    else
1089      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1090
1091    return EFL_UTIL_ERROR_NONE;
1092 #endif /* end of X11 */
1093
1094 #if WAYLAND
1095    Ecore_Wl_Window *wlwin;
1096    struct wl_surface *surface;
1097    Efl_Util_Wl_Surface_Scr_Mode_Info *scr_mode_info;
1098    Eina_Bool res;
1099
1100    res = _wl_init();
1101    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1102
1103    wlwin = elm_win_wl_window_get(window);
1104    if (wlwin)
1105      {
1106         while (!_eflutil.wl.policy.proto)
1107           wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1108
1109         surface = ecore_wl_window_surface_get(wlwin);
1110         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1111                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
1112
1113         scr_mode_info = eina_hash_find(_eflutil.wl.policy.hash_scr_mode, &surface);
1114         if (!scr_mode_info)
1115           {
1116              scr_mode_info = calloc(1, sizeof(Efl_Util_Wl_Surface_Scr_Mode_Info));
1117              EINA_SAFETY_ON_NULL_RETURN_VAL(scr_mode_info, EFL_UTIL_ERROR_OUT_OF_MEMORY);
1118
1119              scr_mode_info->surface = surface;
1120              scr_mode_info->mode = (unsigned int)mode;
1121              scr_mode_info->wait_for_done = EINA_TRUE;
1122              scr_mode_info->state = TIZEN_POLICY_ERROR_STATE_NONE;
1123
1124              eina_hash_add(_eflutil.wl.policy.hash_scr_mode,
1125                            &surface,
1126                            scr_mode_info);
1127           }
1128         else
1129           {
1130              scr_mode_info->mode = (unsigned int)mode;
1131              scr_mode_info->wait_for_done = EINA_TRUE;
1132              scr_mode_info->state = TIZEN_POLICY_ERROR_STATE_NONE;
1133           }
1134
1135         tizen_policy_set_window_screen_mode(_eflutil.wl.policy.proto,
1136                                             surface, (unsigned int)mode);
1137         if (scr_mode_info->wait_for_done)
1138           {
1139              int count = 0;
1140              while (scr_mode_info->wait_for_done && (count < 3))
1141                {
1142                   ecore_wl_flush();
1143                   wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1144                   count++;
1145                }
1146
1147              if (scr_mode_info->wait_for_done)
1148                {
1149                   return EFL_UTIL_ERROR_INVALID_PARAMETER;
1150                }
1151              else
1152                {
1153                   if (scr_mode_info->state == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
1154                     {
1155                        return EFL_UTIL_ERROR_PERMISSION_DENIED;
1156                     }
1157                }
1158           }
1159
1160         return EFL_UTIL_ERROR_NONE;
1161      }
1162    else
1163      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1164 #endif /* end of WAYLAND */
1165 }
1166
1167 API int
1168 efl_util_get_window_screen_mode(Evas_Object *window,
1169                                 efl_util_screen_mode_e *mode)
1170 {
1171    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1172    EINA_SAFETY_ON_NULL_RETURN_VAL(mode, EFL_UTIL_ERROR_INVALID_PARAMETER);
1173
1174 #if X11
1175    Evas *e;
1176    Ecore_Evas *ee;
1177    const char *str;
1178    int id;
1179
1180    e = evas_object_evas_get(window);
1181    EINA_SAFETY_ON_NULL_RETURN_VAL(e, EFL_UTIL_ERROR_INVALID_PARAMETER);
1182
1183    ee = ecore_evas_ecore_evas_get(e);
1184    EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EFL_UTIL_ERROR_INVALID_PARAMETER);
1185
1186    id = ecore_evas_aux_hint_id_get(ee, "wm.policy.win.lcd.lock");
1187    EINA_SAFETY_ON_TRUE_RETURN_VAL((id == -1), EFL_UTIL_ERROR_INVALID_PARAMETER);
1188
1189    str = ecore_evas_aux_hint_val_get(ee, id);
1190    EINA_SAFETY_ON_NULL_RETURN_VAL(str, EFL_UTIL_ERROR_INVALID_PARAMETER);
1191
1192    if (strncmp(str, "1", strlen("1")) == 0)
1193      *mode = EFL_UTIL_SCREEN_MODE_ALWAYS_ON;
1194    else
1195      *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;
1196
1197    return EFL_UTIL_ERROR_NONE;
1198 #endif /* end of X11 */
1199
1200 #if WAYLAND
1201    Ecore_Wl_Window *wlwin;
1202    struct wl_surface *surface;
1203    Efl_Util_Wl_Surface_Scr_Mode_Info *scr_mode_info;
1204    Eina_Bool res;
1205
1206    res = _wl_init();
1207    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1208
1209    wlwin = elm_win_wl_window_get(window);
1210    if (wlwin)
1211      {
1212         while (!_eflutil.wl.policy.proto)
1213           wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1214
1215         surface = ecore_wl_window_surface_get(wlwin);
1216         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1217                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
1218
1219         scr_mode_info = eina_hash_find(_eflutil.wl.policy.hash_scr_mode, &surface);
1220         if (scr_mode_info)
1221           {
1222              if (scr_mode_info->wait_for_done)
1223                {
1224                   while (scr_mode_info->wait_for_done)
1225                     {
1226                        ecore_wl_flush();
1227                        wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1228                     }
1229                }
1230
1231              switch (scr_mode_info->mode)
1232                {
1233                 case TIZEN_POLICY_MODE_DEFAULT:   *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;   break;
1234                 case TIZEN_POLICY_MODE_ALWAYS_ON: *mode = EFL_UTIL_SCREEN_MODE_ALWAYS_ON; break;
1235                 default:                          *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;
1236                   return EFL_UTIL_ERROR_INVALID_PARAMETER;
1237                }
1238              return EFL_UTIL_ERROR_NONE;
1239           }
1240         else
1241           {
1242              *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;
1243              return EFL_UTIL_ERROR_INVALID_PARAMETER;
1244           }
1245      }
1246    else
1247      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1248 #endif /* end of WAYLAND */
1249 }
1250
1251 API int
1252 efl_util_set_window_screen_mode_error_cb(Evas_Object *window,
1253                                          efl_util_window_screen_mode_error_cb callback,
1254                                          void *user_data)
1255 {
1256    Eina_Bool ret = EINA_FALSE;
1257
1258    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1259    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EFL_UTIL_ERROR_INVALID_PARAMETER);
1260
1261    ret = _cb_info_add(window,
1262                       (Efl_Util_Cb)callback,
1263                       user_data,
1264                       CBH_SCR_MODE);
1265    if (!ret) return EFL_UTIL_ERROR_OUT_OF_MEMORY;
1266
1267 #if X11
1268    if (!_eflutil.cb_handler[CBH_SCR_MODE].atom)
1269      _eflutil.cb_handler[CBH_SCR_MODE].atom = ecore_x_atom_get("_E_SCREEN_MODE_ACCESS_RESULT");
1270 #endif /* end of X11 */
1271
1272    return EFL_UTIL_ERROR_NONE;
1273 }
1274
1275 API int
1276 efl_util_unset_window_screen_mode_error_cb(Evas_Object *window)
1277 {
1278    Eina_Bool ret = EINA_FALSE;
1279
1280    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1281
1282    ret = _cb_info_del_by_win(window, CBH_SCR_MODE);
1283    if (!ret) return EFL_UTIL_ERROR_INVALID_PARAMETER;
1284
1285    return EFL_UTIL_ERROR_NONE;
1286 }
1287
1288 API int
1289 efl_util_set_window_brightness(Evas_Object *window, int brightness)
1290 {
1291    Ecore_Wl_Window *wlwin;
1292    struct wl_surface *surface;
1293    Efl_Util_Wl_Surface_Brightness_Info *brightness_info;
1294    Eina_Bool res;
1295
1296    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1297    EINA_SAFETY_ON_FALSE_RETURN_VAL(brightness <= 100, EFL_UTIL_ERROR_INVALID_PARAMETER);
1298
1299    res = _wl_init();
1300    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1301
1302    wlwin = elm_win_wl_window_get(window);
1303    if (wlwin)
1304      {
1305         while (!_eflutil.wl.display_policy.proto)
1306           wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1307
1308         surface = ecore_wl_window_surface_get(wlwin);
1309         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1310                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
1311
1312         brightness_info = eina_hash_find(_eflutil.wl.display_policy.hash_brightness, &surface);
1313         if (!brightness_info)
1314           {
1315              brightness_info = calloc(1, sizeof(Efl_Util_Wl_Surface_Brightness_Info));
1316              EINA_SAFETY_ON_NULL_RETURN_VAL(brightness_info, EFL_UTIL_ERROR_OUT_OF_MEMORY);
1317
1318              brightness_info->surface = surface;
1319              brightness_info->brightness = brightness;
1320              brightness_info->wait_for_done = EINA_TRUE;
1321              brightness_info->state = TIZEN_DISPLAY_POLICY_ERROR_STATE_NONE;
1322
1323              eina_hash_add(_eflutil.wl.display_policy.hash_brightness,
1324                            &surface,
1325                            brightness_info);
1326            }
1327          else
1328            {
1329               brightness_info->brightness = brightness;
1330               brightness_info->wait_for_done = EINA_TRUE;
1331               brightness_info->state = TIZEN_DISPLAY_POLICY_ERROR_STATE_NONE;
1332            }
1333
1334          tizen_display_policy_set_window_brightness(_eflutil.wl.display_policy.proto,
1335                                                     surface, brightness);
1336          if (brightness_info->wait_for_done)
1337            {
1338               int count = 0;
1339               while (brightness_info->wait_for_done && (count < 3))
1340                 {
1341                    ecore_wl_flush();
1342                    wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1343                    count++;
1344                 }
1345
1346               if (brightness_info->wait_for_done)
1347                 {
1348                    return EFL_UTIL_ERROR_INVALID_PARAMETER;
1349                 }
1350               else
1351                 {
1352                    if (brightness_info->state == TIZEN_DISPLAY_POLICY_ERROR_STATE_PERMISSION_DENIED)
1353                      {
1354                         return EFL_UTIL_ERROR_PERMISSION_DENIED;
1355                      }
1356                 }
1357            }
1358         return EFL_UTIL_ERROR_NONE;
1359      }
1360    else
1361      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1362 }
1363
1364 API int
1365 efl_util_get_window_brightness(Evas_Object *window, int *brightness)
1366 {
1367    Ecore_Wl_Window *wlwin;
1368    struct wl_surface *surface;
1369    Efl_Util_Wl_Surface_Brightness_Info *brightness_info;
1370    Eina_Bool res;
1371
1372    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1373    EINA_SAFETY_ON_NULL_RETURN_VAL(brightness, EFL_UTIL_ERROR_INVALID_PARAMETER);
1374
1375    res = _wl_init();
1376    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1377
1378    wlwin = elm_win_wl_window_get(window);
1379    if (!wlwin) return EFL_UTIL_ERROR_INVALID_PARAMETER;
1380
1381    while (!_eflutil.wl.display_policy.proto)
1382      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1383
1384    surface = ecore_wl_window_surface_get(wlwin);
1385    EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1386                                   EFL_UTIL_ERROR_INVALID_PARAMETER);
1387
1388    brightness_info = eina_hash_find(_eflutil.wl.display_policy.hash_brightness, &surface);
1389    if (brightness_info)
1390      {
1391         if (brightness_info->wait_for_done)
1392           {
1393              while (brightness_info->wait_for_done)
1394                {
1395                   ecore_wl_flush();
1396                   wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1397                }
1398           }
1399          *brightness = brightness_info->brightness;
1400      }
1401    else
1402      *brightness = -1;
1403
1404    return EFL_UTIL_ERROR_NONE;
1405 }
1406
1407
1408 struct _efl_util_inputgen_h
1409 {
1410    unsigned int init_type;
1411 };
1412
1413 #if WAYLAND
1414 static void
1415 _cb_device_add(void *data EINA_UNUSED,
1416                struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED,
1417                uint32_t serial EINA_UNUSED,
1418                const char *identifier EINA_UNUSED,
1419                struct tizen_input_device *device EINA_UNUSED,
1420                struct wl_seat *seat EINA_UNUSED)
1421 {
1422    ;
1423 }
1424
1425 static void
1426 _cb_device_remove(void *data EINA_UNUSED,
1427                struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED,
1428                uint32_t serial  EINA_UNUSED,
1429                const char *identifier  EINA_UNUSED,
1430                struct tizen_input_device *device  EINA_UNUSED,
1431                struct wl_seat *seat  EINA_UNUSED)
1432 {
1433    ;
1434 }
1435
1436 static void
1437 _cb_error(void *data EINA_UNUSED,
1438           struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED,
1439           uint32_t errorcode)
1440 {
1441    _eflutil.wl.devmgr.request_notified = errorcode;
1442 }
1443
1444 static void
1445 _cb_block_expired(void *data EINA_UNUSED,
1446                   struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED)
1447 {
1448    ;
1449 }
1450 #endif /* end of WAYLAND */
1451
1452 static efl_util_error_e
1453 _efl_util_input_convert_input_generator_error(int ret)
1454 {
1455    switch (ret)
1456      {
1457         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE:
1458            return EFL_UTIL_ERROR_NONE;
1459         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION:
1460            return EFL_UTIL_ERROR_PERMISSION_DENIED;
1461         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES:
1462            return EFL_UTIL_ERROR_OUT_OF_MEMORY;
1463         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER:
1464            return EFL_UTIL_ERROR_INVALID_PARAMETER;
1465         default :
1466            return EFL_UTIL_ERROR_NONE;
1467      }
1468 }
1469
1470 API efl_util_inputgen_h
1471 efl_util_input_initialize_generator(efl_util_input_device_type_e dev_type)
1472 {
1473    int ret = EFL_UTIL_ERROR_NONE;
1474    efl_util_inputgen_h inputgen_h = NULL;
1475
1476    if ((dev_type <= EFL_UTIL_INPUT_DEVTYPE_NONE) ||
1477        (dev_type >= EFL_UTIL_INPUT_DEVTYPE_MAX))
1478      {
1479         set_last_result(EFL_UTIL_ERROR_NO_SUCH_DEVICE);
1480         goto out;
1481      }
1482
1483    inputgen_h = (efl_util_inputgen_h)calloc(1, sizeof(struct _efl_util_inputgen_h));
1484    if (!inputgen_h)
1485      {
1486         set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY);
1487         goto out;
1488      }
1489
1490    inputgen_h->init_type |= dev_type;
1491 #if WAYLAND
1492    ret = _wl_init();
1493    if (ret == (int)EINA_FALSE)
1494      {
1495         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1496         goto out;
1497      }
1498
1499    while (!_eflutil.wl.devmgr.devicemgr)
1500      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1501
1502    tizen_input_device_manager_init_generator(_eflutil.wl.devmgr.devicemgr);
1503
1504    while (_eflutil.wl.devmgr.request_notified == -1)
1505      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1506
1507    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1508    _eflutil.wl.devmgr.request_notified = -1;
1509
1510    set_last_result(ret);
1511    if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
1512      goto out;
1513 #endif
1514
1515    return inputgen_h;
1516
1517 out:
1518    if (inputgen_h)
1519      {
1520         free(inputgen_h);
1521         inputgen_h = NULL;
1522      }
1523    return NULL;
1524 }
1525
1526 API int
1527 efl_util_input_deinitialize_generator(efl_util_inputgen_h inputgen_h)
1528 {
1529    int ret = EFL_UTIL_ERROR_NONE;
1530    EINA_SAFETY_ON_NULL_RETURN_VAL(inputgen_h, EFL_UTIL_ERROR_INVALID_PARAMETER);
1531
1532    free(inputgen_h);
1533    inputgen_h = NULL;
1534
1535 #if WAYLAND
1536    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.devmgr.devicemgr, EFL_UTIL_ERROR_INVALID_PARAMETER);
1537
1538    tizen_input_device_manager_deinit_generator(_eflutil.wl.devmgr.devicemgr);
1539
1540    while (_eflutil.wl.devmgr.request_notified == -1)
1541      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1542
1543    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1544    _eflutil.wl.devmgr.request_notified = -1;
1545 #endif
1546
1547    return ret;
1548 }
1549
1550 API int
1551 efl_util_input_generate_key(efl_util_inputgen_h inputgen_h, const char *key_name, int pressed)
1552 {
1553    int ret = EFL_UTIL_ERROR_NONE;
1554
1555    EINA_SAFETY_ON_NULL_RETURN_VAL(inputgen_h, EFL_UTIL_ERROR_INVALID_PARAMETER);
1556    EINA_SAFETY_ON_NULL_RETURN_VAL(key_name, EFL_UTIL_ERROR_INVALID_PARAMETER);
1557    EINA_SAFETY_ON_FALSE_RETURN_VAL(pressed == 0 || pressed == 1, EFL_UTIL_ERROR_INVALID_PARAMETER);
1558    EINA_SAFETY_ON_FALSE_RETURN_VAL(inputgen_h->init_type & EFL_UTIL_INPUT_DEVTYPE_KEYBOARD, EFL_UTIL_ERROR_NO_SUCH_DEVICE);
1559
1560 #if WAYLAND
1561    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.devmgr.devicemgr, EFL_UTIL_ERROR_INVALID_PARAMETER);
1562
1563    tizen_input_device_manager_generate_key(_eflutil.wl.devmgr.devicemgr, key_name, pressed);
1564
1565    while (_eflutil.wl.devmgr.request_notified == -1)
1566      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1567
1568    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1569    _eflutil.wl.devmgr.request_notified = -1;
1570 #endif
1571
1572    return ret;
1573 }
1574
1575 API int
1576 efl_util_input_generate_touch(efl_util_inputgen_h inputgen_h, int idx,
1577                               efl_util_input_touch_type_e touch_type, int x, int y)
1578 {
1579    int ret;
1580 #if WAYLAND
1581    enum tizen_input_device_manager_pointer_event_type type;
1582 #endif
1583
1584    EINA_SAFETY_ON_NULL_RETURN_VAL(inputgen_h, EFL_UTIL_ERROR_INVALID_PARAMETER);
1585    EINA_SAFETY_ON_FALSE_RETURN_VAL(idx >= 0, EFL_UTIL_ERROR_INVALID_PARAMETER);
1586    EINA_SAFETY_ON_FALSE_RETURN_VAL((x > 0 && y > 0), EFL_UTIL_ERROR_INVALID_PARAMETER);
1587    EINA_SAFETY_ON_FALSE_RETURN_VAL(inputgen_h->init_type & EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN, EFL_UTIL_ERROR_NO_SUCH_DEVICE);
1588
1589 #if WAYLAND
1590    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.devmgr.devicemgr, EFL_UTIL_ERROR_INVALID_PARAMETER);
1591
1592    switch(touch_type)
1593      {
1594         case EFL_UTIL_INPUT_TOUCH_BEGIN:
1595            type = TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN;
1596            break;
1597         case EFL_UTIL_INPUT_TOUCH_UPDATE:
1598            type = TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE;
1599            break;
1600         case EFL_UTIL_INPUT_TOUCH_END:
1601            type = TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END;
1602            break;
1603         default:
1604            return EFL_UTIL_ERROR_INVALID_PARAMETER;
1605      }
1606
1607    tizen_input_device_manager_generate_touch(_eflutil.wl.devmgr.devicemgr, type, x, y, idx);
1608
1609    while (_eflutil.wl.devmgr.request_notified == -1)
1610      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1611
1612    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1613    _eflutil.wl.devmgr.request_notified = -1;
1614 #endif
1615
1616    return ret;
1617 }
1618
1619 struct _efl_util_screenshot_h
1620 {
1621    int width;
1622    int height;
1623
1624 #if X11
1625    Ecore_X_Display *dpy;
1626    int internal_display;
1627    int screen;
1628    Window root;
1629    Pixmap pixmap;
1630    GC gc;
1631    Atom atom_capture;
1632
1633    /* port */
1634    int port;
1635
1636    /* damage */
1637    Damage   damage;
1638    int      damage_base;
1639
1640    /* dri2 */
1641    int eventBase, errorBase;
1642    int dri2Major, dri2Minor;
1643    char *driver_name, *device_name;
1644    drm_magic_t magic;
1645
1646    /* drm */
1647    int drm_fd;
1648 #endif
1649
1650    Eina_Bool shot_done;
1651
1652    /* tbm bufmgr */
1653    tbm_bufmgr bufmgr;
1654 };
1655
1656 /* scrrenshot handle */
1657 static efl_util_screenshot_h g_screenshot;
1658
1659 #if X11
1660 #define FOURCC(a,b,c,d) (((unsigned)d&0xff)<<24 | ((unsigned)c&0xff)<<16 | ((unsigned)b&0xff)<<8 | ((unsigned)a&0xff))
1661 #define FOURCC_RGB32    FOURCC('R','G','B','4')
1662 #define TIMEOUT_CAPTURE 3
1663
1664 /* x error handling */
1665 static Bool g_efl_util_x_error_caught;
1666
1667 static int
1668 _efl_util_screenshot_x_error_handle(Display *dpy, XErrorEvent *ev)
1669 {
1670    if (!g_screenshot || (dpy != g_screenshot->dpy))
1671      return 0;
1672
1673    g_efl_util_x_error_caught = True;
1674
1675    return 0;
1676 }
1677
1678 static int
1679 _efl_util_screenshot_get_port(Display *dpy, unsigned int id, Window win)
1680 {
1681    unsigned int ver, rev, req_base, evt_base, err_base;
1682    unsigned int adaptors;
1683    XvAdaptorInfo *ai = NULL;
1684    XvImageFormatValues *fo = NULL;
1685    int formats;
1686    int i, j, p;
1687
1688    if (XvQueryExtension(dpy, &ver, &rev, &req_base, &evt_base, &err_base) != Success)
1689      {
1690         fprintf(stderr, "[screenshot] fail: no XV extension. \n");
1691         return -1;
1692      }
1693
1694    if (XvQueryAdaptors(dpy, win, &adaptors, &ai) != Success)
1695      {
1696         fprintf(stderr, "[screenshot] fail: query adaptors. \n");
1697         return -1;
1698      }
1699
1700    EINA_SAFETY_ON_NULL_RETURN_VAL(ai, -1);
1701
1702    for (i = 0; i < adaptors; i++)
1703      {
1704         int support_format = False;
1705
1706         if (!(ai[i].type & XvInputMask) ||
1707             !(ai[i].type & XvStillMask))
1708           continue;
1709
1710         p = ai[i].base_id;
1711
1712         fo = XvListImageFormats(dpy, p, &formats);
1713         for (j = 0; j < formats; j++)
1714           if (fo[j].id == (int)id)
1715             support_format = True;
1716
1717         if (fo)
1718           XFree(fo);
1719
1720         if (!support_format)
1721           continue;
1722
1723         for (; p < ai[i].base_id + ai[i].num_ports; p++)
1724           {
1725              if (XvGrabPort(dpy, p, 0) == Success)
1726                {
1727                   XvFreeAdaptorInfo(ai);
1728                   return p;
1729                }
1730           }
1731      }
1732
1733    XvFreeAdaptorInfo(ai);
1734
1735    XSync(dpy, False);
1736
1737    return -1;
1738 }
1739
1740 static int
1741 _efl_util_screenshot_get_best_size(Display *dpy, int port, int width, int height, unsigned int *best_width, unsigned int *best_height)
1742 {
1743    XErrorHandler old_handler = NULL;
1744
1745    Atom atom_capture = XInternAtom(dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1746
1747    g_efl_util_x_error_caught = False;
1748    old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
1749
1750    XvSetPortAttribute(dpy, port, atom_capture, 1);
1751    XSync(dpy, False);
1752
1753    g_efl_util_x_error_caught = False;
1754    XSetErrorHandler(old_handler);
1755
1756    XvQueryBestSize(dpy, port, 0, 0, 0, width, height, best_width, best_height);
1757    if (best_width <= 0 || best_height <= 0)
1758      return 0;
1759
1760    return 1;
1761 }
1762 #endif
1763
1764 API efl_util_screenshot_h
1765 efl_util_screenshot_initialize(int width, int height)
1766 {
1767 #if X11
1768    efl_util_screenshot_h screenshot = NULL;
1769    int depth = 0;
1770    int damage_err_base = 0;
1771    unsigned int best_width = 0;
1772    unsigned int best_height = 0;
1773
1774    EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
1775    EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
1776
1777    if (g_screenshot != NULL)
1778      {
1779         if (g_screenshot->width != width || g_screenshot->height != height)
1780           {
1781              // TODO: recreate pixmap and update information
1782              if (!_efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height))
1783                {
1784                   set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
1785                   return NULL;
1786                }
1787
1788              g_screenshot->width = width;
1789              g_screenshot->height = height;
1790           }
1791
1792         return g_screenshot;
1793      }
1794
1795    screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
1796    EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
1797
1798    /* set dpy */
1799    screenshot->dpy = ecore_x_display_get();
1800    if (!screenshot->dpy)
1801      {
1802         screenshot->dpy = XOpenDisplay(0);
1803         EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_init);
1804
1805         /* for XCloseDisplay at denitialization */
1806         screenshot->internal_display = 1;
1807      }
1808
1809    /* set screen */
1810    screenshot->screen = DefaultScreen(screenshot->dpy);
1811
1812    /* set root window */
1813    screenshot->root = DefaultRootWindow(screenshot->dpy);
1814
1815    /* initialize capture adaptor */
1816    screenshot->port = _efl_util_screenshot_get_port(screenshot->dpy, FOURCC_RGB32, screenshot->root);
1817    EINA_SAFETY_ON_FALSE_GOTO(screenshot->port > 0, fail_init);
1818
1819    /* get the best size */
1820    _efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height);
1821    EINA_SAFETY_ON_FALSE_GOTO(best_width > 0, fail_init);
1822    EINA_SAFETY_ON_FALSE_GOTO(best_height > 0, fail_init);
1823
1824    /* set the width and the height */
1825    screenshot->width = best_width;
1826    screenshot->height = best_height;
1827
1828    /* create a pixmap */
1829    depth = DefaultDepth(screenshot->dpy, screenshot->screen);
1830    screenshot->pixmap = XCreatePixmap(screenshot->dpy, screenshot->root, screenshot->width, screenshot->height, depth);
1831    EINA_SAFETY_ON_FALSE_GOTO(screenshot->pixmap > 0, fail_init);
1832
1833    screenshot->gc = XCreateGC(screenshot->dpy, screenshot->pixmap, 0, 0);
1834    EINA_SAFETY_ON_NULL_GOTO(screenshot->gc, fail_init);
1835
1836    XSetForeground(screenshot->dpy, screenshot->gc, 0xFF000000);
1837    XFillRectangle(screenshot->dpy, screenshot->pixmap, screenshot->gc, 0, 0, width, height);
1838
1839    /* initialize damage */
1840    if (!XDamageQueryExtension(screenshot->dpy, &screenshot->damage_base, &damage_err_base))
1841      goto fail_init;
1842
1843    screenshot->damage = XDamageCreate(screenshot->dpy, screenshot->pixmap, XDamageReportNonEmpty);
1844    EINA_SAFETY_ON_FALSE_GOTO(screenshot->damage > 0, fail_init);
1845
1846    /* initialize dri3 and dri2 */
1847    if (!DRI2QueryExtension(screenshot->dpy, &screenshot->eventBase, &screenshot->errorBase))
1848      {
1849         fprintf(stderr, "[screenshot] fail: DRI2QueryExtention\n");
1850         goto fail_init;
1851      }
1852
1853    if (!DRI2QueryVersion(screenshot->dpy, &screenshot->dri2Major, &screenshot->dri2Minor))
1854      {
1855         fprintf(stderr, "[screenshot] fail: DRI2QueryVersion\n");
1856         goto fail_init;
1857      }
1858
1859    if (!DRI2Connect(screenshot->dpy, screenshot->root, &screenshot->driver_name, &screenshot->device_name))
1860      {
1861         fprintf(stderr, "[screenshot] fail: DRI2Connect\n");
1862         goto fail_init;
1863      }
1864
1865    screenshot->drm_fd = open(screenshot->device_name, O_RDWR);
1866    EINA_SAFETY_ON_FALSE_GOTO(screenshot->drm_fd >= 0, fail_init);
1867
1868    if (drmGetMagic(screenshot->drm_fd, &screenshot->magic))
1869      {
1870         fprintf(stderr, "[screenshot] fail: drmGetMagic\n");
1871         goto fail_init;
1872      }
1873
1874    if (!DRI2Authenticate(screenshot->dpy, screenshot->root, screenshot->magic))
1875      {
1876         fprintf(stderr, "[screenshot] fail: DRI2Authenticate\n");
1877         goto fail_init;
1878      }
1879
1880    if (!drmAuthMagic(screenshot->drm_fd, screenshot->magic))
1881      {
1882         fprintf(stderr, "[screenshot] fail: drmAuthMagic\n");
1883         goto fail_init;
1884      }
1885
1886    DRI2CreateDrawable(screenshot->dpy, screenshot->pixmap);
1887
1888    /* tbm bufmgr */
1889    screenshot->bufmgr = tbm_bufmgr_init(screenshot->drm_fd);
1890    EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
1891
1892    XFlush(screenshot->dpy);
1893
1894    g_screenshot = screenshot;
1895    set_last_result(EFL_UTIL_ERROR_NONE);
1896
1897    return g_screenshot;
1898 #endif
1899
1900 #if WAYLAND
1901    efl_util_screenshot_h screenshot = NULL;
1902
1903    if (!_eflutil.wl.shot.screenshooter)
1904      {
1905         int ret = 0;
1906         _wl_init();
1907         while (!_eflutil.wl.shot.screenshooter && ret != -1)
1908           ret = wl_display_roundtrip_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1909         EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.screenshooter, fail_init);
1910
1911        _eflutil.wl.shot.tbm_client = wayland_tbm_client_init(_eflutil.wl.dpy);
1912        EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.tbm_client, fail_init);
1913      }
1914
1915    EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
1916    EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
1917
1918    if (g_screenshot)
1919      {
1920         if (g_screenshot->width != width || g_screenshot->height != height)
1921           {
1922              g_screenshot->width = width;
1923              g_screenshot->height = height;
1924           }
1925
1926         return g_screenshot;
1927      }
1928
1929    screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
1930    EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
1931
1932    screenshot->width = width;
1933    screenshot->height = height;
1934
1935    screenshot->bufmgr = wayland_tbm_client_get_bufmgr(_eflutil.wl.shot.tbm_client);
1936    EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
1937
1938    g_screenshot = screenshot;
1939    set_last_result(EFL_UTIL_ERROR_NONE);
1940
1941    screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, &screenshot->shot_done);
1942
1943    return g_screenshot;
1944 #endif
1945 fail_param:
1946    if (screenshot)
1947      efl_util_screenshot_deinitialize(screenshot);
1948    set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1949    return NULL;
1950 fail_memory:
1951    if (screenshot)
1952      efl_util_screenshot_deinitialize(screenshot);
1953    set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY);
1954    return NULL;
1955 fail_init:
1956    if (screenshot)
1957      efl_util_screenshot_deinitialize(screenshot);
1958    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
1959    return NULL;
1960 }
1961
1962 API int
1963 efl_util_screenshot_deinitialize(efl_util_screenshot_h screenshot)
1964 {
1965 #if X11
1966    if (!screenshot)
1967      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1968
1969    /* tbm bufmgr */
1970    if (screenshot->bufmgr)
1971      tbm_bufmgr_deinit(screenshot->bufmgr);
1972
1973    DRI2DestroyDrawable(screenshot->dpy, screenshot->pixmap);
1974
1975    /* dri2 */
1976    if (screenshot->drm_fd)
1977      close(screenshot->drm_fd);
1978    if (screenshot->driver_name)
1979      free(screenshot->driver_name);
1980    if (screenshot->device_name)
1981      free(screenshot->device_name);
1982
1983    /* xv */
1984    if (screenshot->port > 0 && screenshot->pixmap > 0)
1985      XvStopVideo(screenshot->dpy, screenshot->port, screenshot->pixmap);
1986
1987    /* damage */
1988    if (screenshot->damage)
1989      XDamageDestroy(screenshot->dpy, screenshot->damage);
1990
1991    /* gc */
1992    if (screenshot->gc)
1993      XFreeGC(screenshot->dpy, screenshot->gc);
1994
1995    /* pixmap */
1996    if (screenshot->pixmap > 0)
1997      XFreePixmap(screenshot->dpy, screenshot->pixmap);
1998
1999    /* port */
2000    if (screenshot->port > 0)
2001      XvUngrabPort(screenshot->dpy, screenshot->port, 0);
2002
2003    XSync(screenshot->dpy, False);
2004
2005    /* dpy */
2006    if (screenshot->internal_display ==1 && screenshot->dpy)
2007      XCloseDisplay(screenshot->dpy);
2008
2009    free(screenshot);
2010    g_screenshot = NULL;
2011
2012    return EFL_UTIL_ERROR_NONE;
2013 #endif
2014 #if WAYLAND
2015    if (!screenshot)
2016      return EFL_UTIL_ERROR_INVALID_PARAMETER;
2017
2018    free(screenshot);
2019    g_screenshot = NULL;
2020
2021    if (_eflutil.wl.shot.screenshooter)
2022      screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, NULL);
2023
2024    return EFL_UTIL_ERROR_NONE;
2025 #endif
2026 }
2027
2028
2029 API tbm_surface_h
2030 efl_util_screenshot_take_tbm_surface(efl_util_screenshot_h screenshot)
2031 {
2032 #if X11
2033    XEvent ev = {0,};
2034    XErrorHandler old_handler = NULL;
2035    unsigned int attachment = DRI2BufferFrontLeft;
2036    int nbufs = 0;
2037    DRI2Buffer *bufs = NULL;
2038    tbm_bo t_bo = NULL;
2039    tbm_surface_h t_surface = NULL;
2040    int buf_width = 0;
2041    int buf_height = 0;
2042    tbm_surface_info_s surf_info;
2043    int i;
2044
2045    if (screenshot != g_screenshot)
2046      {
2047         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
2048         return NULL;
2049      }
2050
2051    /* for flush other pending requests and pending events */
2052    XSync(screenshot->dpy, 0);
2053
2054    g_efl_util_x_error_caught = False;
2055    old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
2056
2057    /* dump here */
2058    XvPutStill(screenshot->dpy, screenshot->port, screenshot->pixmap, screenshot->gc,
2059               0, 0, screenshot->width, screenshot->height,
2060               0, 0, screenshot->width, screenshot->height);
2061
2062    XSync(screenshot->dpy, 0);
2063
2064    if (g_efl_util_x_error_caught)
2065      {
2066         g_efl_util_x_error_caught = False;
2067         XSetErrorHandler(old_handler);
2068         goto fail;
2069      }
2070
2071    g_efl_util_x_error_caught = False;
2072    XSetErrorHandler(old_handler);
2073
2074    if (XPending(screenshot->dpy))
2075      XNextEvent(screenshot->dpy, &ev);
2076    else
2077      {
2078         int fd = ConnectionNumber(screenshot->dpy);
2079         fd_set mask;
2080         struct timeval tv;
2081         int ret;
2082
2083         FD_ZERO(&mask);
2084         FD_SET(fd, &mask);
2085
2086         tv.tv_usec = 0;
2087         tv.tv_sec = TIMEOUT_CAPTURE;
2088
2089         ret = select(fd + 1, &mask, 0, 0, &tv);
2090         if (ret < 0)
2091           fprintf(stderr, "[screenshot] fail: select.\n");
2092         else if (ret == 0)
2093           fprintf(stderr, "[screenshot] fail: timeout(%d sec)!\n", TIMEOUT_CAPTURE);
2094         else if (XPending(screenshot->dpy))
2095           XNextEvent(screenshot->dpy, &ev);
2096         else
2097           fprintf(stderr, "[screenshot] fail: not passed a event!\n");
2098      }
2099
2100    /* check if the capture is done by xserver and pixmap has got the captured image */
2101    if (ev.type == (screenshot->damage_base + XDamageNotify))
2102      {
2103         XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
2104         if (damage_ev->drawable == screenshot->pixmap)
2105           {
2106              /* Get DRI2 FrontLeft buffer of the pixmap */
2107              bufs = DRI2GetBuffers(screenshot->dpy, screenshot->pixmap, &buf_width, &buf_height, &attachment, 1, &nbufs);
2108              if (!bufs)
2109                {
2110                   fprintf(stderr, "[screenshot] fail: DRI2GetBuffers\n");
2111                   goto fail;
2112                }
2113
2114              t_bo = tbm_bo_import(screenshot->bufmgr, bufs[0].name);
2115              if (!t_bo)
2116                {
2117                   fprintf(stderr, "[screenshot] fail: import tbm_bo!\n");
2118                   goto fail;
2119                }
2120
2121              surf_info.width = buf_width;
2122              surf_info.height = buf_height;
2123              surf_info.format = TBM_FORMAT_XRGB8888;
2124              surf_info.bpp = 32;
2125              surf_info.size = bufs->pitch * surf_info.height;
2126              surf_info.num_planes = 1;
2127              for (i = 0; i < surf_info.num_planes; i++)
2128                {
2129                   surf_info.planes[i].size = bufs->pitch * surf_info.height;
2130                   surf_info.planes[i].stride = bufs->pitch;
2131                   surf_info.planes[i].offset = 0;
2132                }
2133              t_surface = tbm_surface_internal_create_with_bos(&surf_info, &t_bo, 1);
2134              if (!t_surface)
2135                {
2136                   fprintf(stderr, "[screenshot] fail: get tbm_surface!\n");
2137                   goto fail;
2138                }
2139
2140              tbm_bo_unref(t_bo);
2141              free(bufs);
2142
2143              XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
2144
2145              set_last_result(EFL_UTIL_ERROR_NONE);
2146
2147              return t_surface;
2148           }
2149
2150         XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
2151      }
2152
2153 fail:
2154
2155    if (t_bo)
2156      tbm_bo_unref(t_bo);
2157    if (bufs)
2158      free(bufs);
2159
2160    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
2161
2162    return NULL;
2163 #endif
2164
2165 #if WAYLAND
2166    tbm_surface_h t_surface = NULL;
2167    struct wl_buffer *buffer = NULL;
2168    Efl_Util_Wl_Output_Info *output;
2169    int ret = 0;
2170
2171    if (screenshot != g_screenshot)
2172      {
2173         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
2174         return NULL;
2175      }
2176
2177    output = eina_list_nth(_eflutil.wl.shot.output_list, 0);
2178    if (!output)
2179      {
2180         fprintf(stderr, "[screenshot] fail: no output for screenshot\n");
2181         goto fail;
2182      }
2183
2184    t_surface = tbm_surface_create(screenshot->width, screenshot->height, TBM_FORMAT_XRGB8888);
2185    if (!t_surface)
2186      {
2187         fprintf(stderr, "[screenshot] fail: tbm_surface_create\n");
2188         goto fail;
2189      }
2190
2191    buffer = wayland_tbm_client_create_buffer(_eflutil.wl.shot.tbm_client, t_surface);
2192    if (!buffer)
2193      {
2194         fprintf(stderr, "[screenshot] fail: create wl_buffer for screenshot\n");
2195         goto fail;
2196      }
2197
2198    screenshooter_shoot(_eflutil.wl.shot.screenshooter, output->output, buffer);
2199
2200    screenshot->shot_done = EINA_FALSE;
2201    while (!screenshot->shot_done && ret != -1)
2202      ret = wl_display_roundtrip_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
2203
2204    if (ret == -1)
2205      {
2206         fprintf(stderr, "[screenshot] fail: screenshooter_shoot\n");
2207         goto fail;
2208      }
2209
2210    wl_buffer_destroy(buffer);
2211
2212    /* reset shot_done for next screenshot */
2213    screenshot->shot_done = EINA_FALSE;
2214
2215    return t_surface;
2216
2217 fail:
2218    if (t_surface)
2219      tbm_surface_destroy(t_surface);
2220    if (buffer)
2221      wl_buffer_destroy(buffer);
2222
2223    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
2224
2225    return NULL;
2226 #endif
2227 }