Devide header file for wearable and non-wearable.
[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 #ifndef TIZEN_WEARABLE
1252 API int
1253 efl_util_set_window_screen_mode_error_cb(Evas_Object *window,
1254                                          efl_util_window_screen_mode_error_cb callback,
1255                                          void *user_data)
1256 {
1257    Eina_Bool ret = EINA_FALSE;
1258
1259    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1260    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EFL_UTIL_ERROR_INVALID_PARAMETER);
1261
1262    ret = _cb_info_add(window,
1263                       (Efl_Util_Cb)callback,
1264                       user_data,
1265                       CBH_SCR_MODE);
1266    if (!ret) return EFL_UTIL_ERROR_OUT_OF_MEMORY;
1267
1268 #if X11
1269    if (!_eflutil.cb_handler[CBH_SCR_MODE].atom)
1270      _eflutil.cb_handler[CBH_SCR_MODE].atom = ecore_x_atom_get("_E_SCREEN_MODE_ACCESS_RESULT");
1271 #endif /* end of X11 */
1272
1273    return EFL_UTIL_ERROR_NONE;
1274 }
1275
1276 API int
1277 efl_util_unset_window_screen_mode_error_cb(Evas_Object *window)
1278 {
1279    Eina_Bool ret = EINA_FALSE;
1280
1281    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1282
1283    ret = _cb_info_del_by_win(window, CBH_SCR_MODE);
1284    if (!ret) return EFL_UTIL_ERROR_INVALID_PARAMETER;
1285
1286    return EFL_UTIL_ERROR_NONE;
1287 }
1288 #endif
1289
1290 API int
1291 efl_util_set_window_brightness(Evas_Object *window, int brightness)
1292 {
1293    Ecore_Wl_Window *wlwin;
1294    struct wl_surface *surface;
1295    Efl_Util_Wl_Surface_Brightness_Info *brightness_info;
1296    Eina_Bool res;
1297
1298    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1299    EINA_SAFETY_ON_FALSE_RETURN_VAL(brightness <= 100, EFL_UTIL_ERROR_INVALID_PARAMETER);
1300
1301    res = _wl_init();
1302    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1303
1304    wlwin = elm_win_wl_window_get(window);
1305    if (wlwin)
1306      {
1307         while (!_eflutil.wl.display_policy.proto)
1308           wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1309
1310         surface = ecore_wl_window_surface_get(wlwin);
1311         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1312                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
1313
1314         brightness_info = eina_hash_find(_eflutil.wl.display_policy.hash_brightness, &surface);
1315         if (!brightness_info)
1316           {
1317              brightness_info = calloc(1, sizeof(Efl_Util_Wl_Surface_Brightness_Info));
1318              EINA_SAFETY_ON_NULL_RETURN_VAL(brightness_info, EFL_UTIL_ERROR_OUT_OF_MEMORY);
1319
1320              brightness_info->surface = surface;
1321              brightness_info->brightness = brightness;
1322              brightness_info->wait_for_done = EINA_TRUE;
1323              brightness_info->state = TIZEN_DISPLAY_POLICY_ERROR_STATE_NONE;
1324
1325              eina_hash_add(_eflutil.wl.display_policy.hash_brightness,
1326                            &surface,
1327                            brightness_info);
1328            }
1329          else
1330            {
1331               brightness_info->brightness = brightness;
1332               brightness_info->wait_for_done = EINA_TRUE;
1333               brightness_info->state = TIZEN_DISPLAY_POLICY_ERROR_STATE_NONE;
1334            }
1335
1336          tizen_display_policy_set_window_brightness(_eflutil.wl.display_policy.proto,
1337                                                     surface, brightness);
1338          if (brightness_info->wait_for_done)
1339            {
1340               int count = 0;
1341               while (brightness_info->wait_for_done && (count < 3))
1342                 {
1343                    ecore_wl_flush();
1344                    wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1345                    count++;
1346                 }
1347
1348               if (brightness_info->wait_for_done)
1349                 {
1350                    return EFL_UTIL_ERROR_INVALID_PARAMETER;
1351                 }
1352               else
1353                 {
1354                    if (brightness_info->state == TIZEN_DISPLAY_POLICY_ERROR_STATE_PERMISSION_DENIED)
1355                      {
1356                         return EFL_UTIL_ERROR_PERMISSION_DENIED;
1357                      }
1358                 }
1359            }
1360         return EFL_UTIL_ERROR_NONE;
1361      }
1362    else
1363      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1364 }
1365
1366 API int
1367 efl_util_get_window_brightness(Evas_Object *window, int *brightness)
1368 {
1369    Ecore_Wl_Window *wlwin;
1370    struct wl_surface *surface;
1371    Efl_Util_Wl_Surface_Brightness_Info *brightness_info;
1372    Eina_Bool res;
1373
1374    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1375    EINA_SAFETY_ON_NULL_RETURN_VAL(brightness, EFL_UTIL_ERROR_INVALID_PARAMETER);
1376
1377    res = _wl_init();
1378    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1379
1380    wlwin = elm_win_wl_window_get(window);
1381    if (!wlwin) return EFL_UTIL_ERROR_INVALID_PARAMETER;
1382
1383    while (!_eflutil.wl.display_policy.proto)
1384      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1385
1386    surface = ecore_wl_window_surface_get(wlwin);
1387    EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1388                                   EFL_UTIL_ERROR_INVALID_PARAMETER);
1389
1390    brightness_info = eina_hash_find(_eflutil.wl.display_policy.hash_brightness, &surface);
1391    if (brightness_info)
1392      {
1393         if (brightness_info->wait_for_done)
1394           {
1395              while (brightness_info->wait_for_done)
1396                {
1397                   ecore_wl_flush();
1398                   wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1399                }
1400           }
1401          *brightness = brightness_info->brightness;
1402      }
1403    else
1404      *brightness = -1;
1405
1406    return EFL_UTIL_ERROR_NONE;
1407 }
1408
1409
1410 struct _efl_util_inputgen_h
1411 {
1412    unsigned int init_type;
1413 };
1414
1415 #if WAYLAND
1416 static void
1417 _cb_device_add(void *data EINA_UNUSED,
1418                struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED,
1419                uint32_t serial EINA_UNUSED,
1420                const char *identifier EINA_UNUSED,
1421                struct tizen_input_device *device EINA_UNUSED,
1422                struct wl_seat *seat EINA_UNUSED)
1423 {
1424    ;
1425 }
1426
1427 static void
1428 _cb_device_remove(void *data EINA_UNUSED,
1429                struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED,
1430                uint32_t serial  EINA_UNUSED,
1431                const char *identifier  EINA_UNUSED,
1432                struct tizen_input_device *device  EINA_UNUSED,
1433                struct wl_seat *seat  EINA_UNUSED)
1434 {
1435    ;
1436 }
1437
1438 static void
1439 _cb_error(void *data EINA_UNUSED,
1440           struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED,
1441           uint32_t errorcode)
1442 {
1443    _eflutil.wl.devmgr.request_notified = errorcode;
1444 }
1445
1446 static void
1447 _cb_block_expired(void *data EINA_UNUSED,
1448                   struct tizen_input_device_manager *tizen_input_device_manager EINA_UNUSED)
1449 {
1450    ;
1451 }
1452 #endif /* end of WAYLAND */
1453
1454 static efl_util_error_e
1455 _efl_util_input_convert_input_generator_error(int ret)
1456 {
1457    switch (ret)
1458      {
1459         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE:
1460            return EFL_UTIL_ERROR_NONE;
1461         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION:
1462            return EFL_UTIL_ERROR_PERMISSION_DENIED;
1463         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_SYSTEM_RESOURCES:
1464            return EFL_UTIL_ERROR_OUT_OF_MEMORY;
1465         case TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER:
1466            return EFL_UTIL_ERROR_INVALID_PARAMETER;
1467         default :
1468            return EFL_UTIL_ERROR_NONE;
1469      }
1470 }
1471
1472 API efl_util_inputgen_h
1473 efl_util_input_initialize_generator(efl_util_input_device_type_e dev_type)
1474 {
1475    int ret = EFL_UTIL_ERROR_NONE;
1476    efl_util_inputgen_h inputgen_h = NULL;
1477
1478    if ((dev_type <= EFL_UTIL_INPUT_DEVTYPE_NONE) ||
1479        (dev_type >= EFL_UTIL_INPUT_DEVTYPE_MAX))
1480      {
1481         set_last_result(EFL_UTIL_ERROR_NO_SUCH_DEVICE);
1482         goto out;
1483      }
1484
1485    inputgen_h = (efl_util_inputgen_h)calloc(1, sizeof(struct _efl_util_inputgen_h));
1486    if (!inputgen_h)
1487      {
1488         set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY);
1489         goto out;
1490      }
1491
1492    inputgen_h->init_type |= dev_type;
1493 #if WAYLAND
1494    ret = _wl_init();
1495    if (ret == (int)EINA_FALSE)
1496      {
1497         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1498         goto out;
1499      }
1500
1501    while (!_eflutil.wl.devmgr.devicemgr)
1502      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1503
1504    tizen_input_device_manager_init_generator(_eflutil.wl.devmgr.devicemgr);
1505
1506    while (_eflutil.wl.devmgr.request_notified == -1)
1507      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1508
1509    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1510    _eflutil.wl.devmgr.request_notified = -1;
1511
1512    set_last_result(ret);
1513    if (ret != TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE)
1514      goto out;
1515 #endif
1516
1517    return inputgen_h;
1518
1519 out:
1520    if (inputgen_h)
1521      {
1522         free(inputgen_h);
1523         inputgen_h = NULL;
1524      }
1525    return NULL;
1526 }
1527
1528 API int
1529 efl_util_input_deinitialize_generator(efl_util_inputgen_h inputgen_h)
1530 {
1531    int ret = EFL_UTIL_ERROR_NONE;
1532    EINA_SAFETY_ON_NULL_RETURN_VAL(inputgen_h, EFL_UTIL_ERROR_INVALID_PARAMETER);
1533
1534    free(inputgen_h);
1535    inputgen_h = NULL;
1536
1537 #if WAYLAND
1538    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.devmgr.devicemgr, EFL_UTIL_ERROR_INVALID_PARAMETER);
1539
1540    tizen_input_device_manager_deinit_generator(_eflutil.wl.devmgr.devicemgr);
1541
1542    while (_eflutil.wl.devmgr.request_notified == -1)
1543      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1544
1545    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1546    _eflutil.wl.devmgr.request_notified = -1;
1547 #endif
1548
1549    return ret;
1550 }
1551
1552 API int
1553 efl_util_input_generate_key(efl_util_inputgen_h inputgen_h, const char *key_name, int pressed)
1554 {
1555    int ret = EFL_UTIL_ERROR_NONE;
1556
1557    EINA_SAFETY_ON_NULL_RETURN_VAL(inputgen_h, EFL_UTIL_ERROR_INVALID_PARAMETER);
1558    EINA_SAFETY_ON_NULL_RETURN_VAL(key_name, EFL_UTIL_ERROR_INVALID_PARAMETER);
1559    EINA_SAFETY_ON_FALSE_RETURN_VAL(pressed == 0 || pressed == 1, EFL_UTIL_ERROR_INVALID_PARAMETER);
1560    EINA_SAFETY_ON_FALSE_RETURN_VAL(inputgen_h->init_type & EFL_UTIL_INPUT_DEVTYPE_KEYBOARD, EFL_UTIL_ERROR_NO_SUCH_DEVICE);
1561
1562 #if WAYLAND
1563    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.devmgr.devicemgr, EFL_UTIL_ERROR_INVALID_PARAMETER);
1564
1565    tizen_input_device_manager_generate_key(_eflutil.wl.devmgr.devicemgr, key_name, pressed);
1566
1567    while (_eflutil.wl.devmgr.request_notified == -1)
1568      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1569
1570    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1571    _eflutil.wl.devmgr.request_notified = -1;
1572 #endif
1573
1574    return ret;
1575 }
1576
1577 API int
1578 efl_util_input_generate_touch(efl_util_inputgen_h inputgen_h, int idx,
1579                               efl_util_input_touch_type_e touch_type, int x, int y)
1580 {
1581    int ret;
1582 #if WAYLAND
1583    enum tizen_input_device_manager_pointer_event_type type;
1584 #endif
1585
1586    EINA_SAFETY_ON_NULL_RETURN_VAL(inputgen_h, EFL_UTIL_ERROR_INVALID_PARAMETER);
1587    EINA_SAFETY_ON_FALSE_RETURN_VAL(idx >= 0, EFL_UTIL_ERROR_INVALID_PARAMETER);
1588    EINA_SAFETY_ON_FALSE_RETURN_VAL((x > 0 && y > 0), EFL_UTIL_ERROR_INVALID_PARAMETER);
1589    EINA_SAFETY_ON_FALSE_RETURN_VAL(inputgen_h->init_type & EFL_UTIL_INPUT_DEVTYPE_TOUCHSCREEN, EFL_UTIL_ERROR_NO_SUCH_DEVICE);
1590
1591 #if WAYLAND
1592    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.devmgr.devicemgr, EFL_UTIL_ERROR_INVALID_PARAMETER);
1593
1594    switch(touch_type)
1595      {
1596         case EFL_UTIL_INPUT_TOUCH_BEGIN:
1597            type = TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_BEGIN;
1598            break;
1599         case EFL_UTIL_INPUT_TOUCH_UPDATE:
1600            type = TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_UPDATE;
1601            break;
1602         case EFL_UTIL_INPUT_TOUCH_END:
1603            type = TIZEN_INPUT_DEVICE_MANAGER_POINTER_EVENT_TYPE_END;
1604            break;
1605         default:
1606            return EFL_UTIL_ERROR_INVALID_PARAMETER;
1607      }
1608
1609    tizen_input_device_manager_generate_touch(_eflutil.wl.devmgr.devicemgr, type, x, y, idx);
1610
1611    while (_eflutil.wl.devmgr.request_notified == -1)
1612      wl_display_dispatch_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1613
1614    ret = _efl_util_input_convert_input_generator_error(_eflutil.wl.devmgr.request_notified);
1615    _eflutil.wl.devmgr.request_notified = -1;
1616 #endif
1617
1618    return ret;
1619 }
1620
1621 struct _efl_util_screenshot_h
1622 {
1623    int width;
1624    int height;
1625
1626 #if X11
1627    Ecore_X_Display *dpy;
1628    int internal_display;
1629    int screen;
1630    Window root;
1631    Pixmap pixmap;
1632    GC gc;
1633    Atom atom_capture;
1634
1635    /* port */
1636    int port;
1637
1638    /* damage */
1639    Damage   damage;
1640    int      damage_base;
1641
1642    /* dri2 */
1643    int eventBase, errorBase;
1644    int dri2Major, dri2Minor;
1645    char *driver_name, *device_name;
1646    drm_magic_t magic;
1647
1648    /* drm */
1649    int drm_fd;
1650 #endif
1651
1652    Eina_Bool shot_done;
1653
1654    /* tbm bufmgr */
1655    tbm_bufmgr bufmgr;
1656 };
1657
1658 /* scrrenshot handle */
1659 static efl_util_screenshot_h g_screenshot;
1660
1661 #if X11
1662 #define FOURCC(a,b,c,d) (((unsigned)d&0xff)<<24 | ((unsigned)c&0xff)<<16 | ((unsigned)b&0xff)<<8 | ((unsigned)a&0xff))
1663 #define FOURCC_RGB32    FOURCC('R','G','B','4')
1664 #define TIMEOUT_CAPTURE 3
1665
1666 /* x error handling */
1667 static Bool g_efl_util_x_error_caught;
1668
1669 static int
1670 _efl_util_screenshot_x_error_handle(Display *dpy, XErrorEvent *ev)
1671 {
1672    if (!g_screenshot || (dpy != g_screenshot->dpy))
1673      return 0;
1674
1675    g_efl_util_x_error_caught = True;
1676
1677    return 0;
1678 }
1679
1680 static int
1681 _efl_util_screenshot_get_port(Display *dpy, unsigned int id, Window win)
1682 {
1683    unsigned int ver, rev, req_base, evt_base, err_base;
1684    unsigned int adaptors;
1685    XvAdaptorInfo *ai = NULL;
1686    XvImageFormatValues *fo = NULL;
1687    int formats;
1688    int i, j, p;
1689
1690    if (XvQueryExtension(dpy, &ver, &rev, &req_base, &evt_base, &err_base) != Success)
1691      {
1692         fprintf(stderr, "[screenshot] fail: no XV extension. \n");
1693         return -1;
1694      }
1695
1696    if (XvQueryAdaptors(dpy, win, &adaptors, &ai) != Success)
1697      {
1698         fprintf(stderr, "[screenshot] fail: query adaptors. \n");
1699         return -1;
1700      }
1701
1702    EINA_SAFETY_ON_NULL_RETURN_VAL(ai, -1);
1703
1704    for (i = 0; i < adaptors; i++)
1705      {
1706         int support_format = False;
1707
1708         if (!(ai[i].type & XvInputMask) ||
1709             !(ai[i].type & XvStillMask))
1710           continue;
1711
1712         p = ai[i].base_id;
1713
1714         fo = XvListImageFormats(dpy, p, &formats);
1715         for (j = 0; j < formats; j++)
1716           if (fo[j].id == (int)id)
1717             support_format = True;
1718
1719         if (fo)
1720           XFree(fo);
1721
1722         if (!support_format)
1723           continue;
1724
1725         for (; p < ai[i].base_id + ai[i].num_ports; p++)
1726           {
1727              if (XvGrabPort(dpy, p, 0) == Success)
1728                {
1729                   XvFreeAdaptorInfo(ai);
1730                   return p;
1731                }
1732           }
1733      }
1734
1735    XvFreeAdaptorInfo(ai);
1736
1737    XSync(dpy, False);
1738
1739    return -1;
1740 }
1741
1742 static int
1743 _efl_util_screenshot_get_best_size(Display *dpy, int port, int width, int height, unsigned int *best_width, unsigned int *best_height)
1744 {
1745    XErrorHandler old_handler = NULL;
1746
1747    Atom atom_capture = XInternAtom(dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1748
1749    g_efl_util_x_error_caught = False;
1750    old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
1751
1752    XvSetPortAttribute(dpy, port, atom_capture, 1);
1753    XSync(dpy, False);
1754
1755    g_efl_util_x_error_caught = False;
1756    XSetErrorHandler(old_handler);
1757
1758    XvQueryBestSize(dpy, port, 0, 0, 0, width, height, best_width, best_height);
1759    if (best_width <= 0 || best_height <= 0)
1760      return 0;
1761
1762    return 1;
1763 }
1764 #endif
1765
1766 API efl_util_screenshot_h
1767 efl_util_screenshot_initialize(int width, int height)
1768 {
1769 #if X11
1770    efl_util_screenshot_h screenshot = NULL;
1771    int depth = 0;
1772    int damage_err_base = 0;
1773    unsigned int best_width = 0;
1774    unsigned int best_height = 0;
1775
1776    EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
1777    EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
1778
1779    if (g_screenshot != NULL)
1780      {
1781         if (g_screenshot->width != width || g_screenshot->height != height)
1782           {
1783              // TODO: recreate pixmap and update information
1784              if (!_efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height))
1785                {
1786                   set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
1787                   return NULL;
1788                }
1789
1790              g_screenshot->width = width;
1791              g_screenshot->height = height;
1792           }
1793
1794         return g_screenshot;
1795      }
1796
1797    screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
1798    EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
1799
1800    /* set dpy */
1801    screenshot->dpy = ecore_x_display_get();
1802    if (!screenshot->dpy)
1803      {
1804         screenshot->dpy = XOpenDisplay(0);
1805         EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_init);
1806
1807         /* for XCloseDisplay at denitialization */
1808         screenshot->internal_display = 1;
1809      }
1810
1811    /* set screen */
1812    screenshot->screen = DefaultScreen(screenshot->dpy);
1813
1814    /* set root window */
1815    screenshot->root = DefaultRootWindow(screenshot->dpy);
1816
1817    /* initialize capture adaptor */
1818    screenshot->port = _efl_util_screenshot_get_port(screenshot->dpy, FOURCC_RGB32, screenshot->root);
1819    EINA_SAFETY_ON_FALSE_GOTO(screenshot->port > 0, fail_init);
1820
1821    /* get the best size */
1822    _efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height);
1823    EINA_SAFETY_ON_FALSE_GOTO(best_width > 0, fail_init);
1824    EINA_SAFETY_ON_FALSE_GOTO(best_height > 0, fail_init);
1825
1826    /* set the width and the height */
1827    screenshot->width = best_width;
1828    screenshot->height = best_height;
1829
1830    /* create a pixmap */
1831    depth = DefaultDepth(screenshot->dpy, screenshot->screen);
1832    screenshot->pixmap = XCreatePixmap(screenshot->dpy, screenshot->root, screenshot->width, screenshot->height, depth);
1833    EINA_SAFETY_ON_FALSE_GOTO(screenshot->pixmap > 0, fail_init);
1834
1835    screenshot->gc = XCreateGC(screenshot->dpy, screenshot->pixmap, 0, 0);
1836    EINA_SAFETY_ON_NULL_GOTO(screenshot->gc, fail_init);
1837
1838    XSetForeground(screenshot->dpy, screenshot->gc, 0xFF000000);
1839    XFillRectangle(screenshot->dpy, screenshot->pixmap, screenshot->gc, 0, 0, width, height);
1840
1841    /* initialize damage */
1842    if (!XDamageQueryExtension(screenshot->dpy, &screenshot->damage_base, &damage_err_base))
1843      goto fail_init;
1844
1845    screenshot->damage = XDamageCreate(screenshot->dpy, screenshot->pixmap, XDamageReportNonEmpty);
1846    EINA_SAFETY_ON_FALSE_GOTO(screenshot->damage > 0, fail_init);
1847
1848    /* initialize dri3 and dri2 */
1849    if (!DRI2QueryExtension(screenshot->dpy, &screenshot->eventBase, &screenshot->errorBase))
1850      {
1851         fprintf(stderr, "[screenshot] fail: DRI2QueryExtention\n");
1852         goto fail_init;
1853      }
1854
1855    if (!DRI2QueryVersion(screenshot->dpy, &screenshot->dri2Major, &screenshot->dri2Minor))
1856      {
1857         fprintf(stderr, "[screenshot] fail: DRI2QueryVersion\n");
1858         goto fail_init;
1859      }
1860
1861    if (!DRI2Connect(screenshot->dpy, screenshot->root, &screenshot->driver_name, &screenshot->device_name))
1862      {
1863         fprintf(stderr, "[screenshot] fail: DRI2Connect\n");
1864         goto fail_init;
1865      }
1866
1867    screenshot->drm_fd = open(screenshot->device_name, O_RDWR);
1868    EINA_SAFETY_ON_FALSE_GOTO(screenshot->drm_fd >= 0, fail_init);
1869
1870    if (drmGetMagic(screenshot->drm_fd, &screenshot->magic))
1871      {
1872         fprintf(stderr, "[screenshot] fail: drmGetMagic\n");
1873         goto fail_init;
1874      }
1875
1876    if (!DRI2Authenticate(screenshot->dpy, screenshot->root, screenshot->magic))
1877      {
1878         fprintf(stderr, "[screenshot] fail: DRI2Authenticate\n");
1879         goto fail_init;
1880      }
1881
1882    if (!drmAuthMagic(screenshot->drm_fd, screenshot->magic))
1883      {
1884         fprintf(stderr, "[screenshot] fail: drmAuthMagic\n");
1885         goto fail_init;
1886      }
1887
1888    DRI2CreateDrawable(screenshot->dpy, screenshot->pixmap);
1889
1890    /* tbm bufmgr */
1891    screenshot->bufmgr = tbm_bufmgr_init(screenshot->drm_fd);
1892    EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
1893
1894    XFlush(screenshot->dpy);
1895
1896    g_screenshot = screenshot;
1897    set_last_result(EFL_UTIL_ERROR_NONE);
1898
1899    return g_screenshot;
1900 #endif
1901
1902 #if WAYLAND
1903    efl_util_screenshot_h screenshot = NULL;
1904
1905    if (!_eflutil.wl.shot.screenshooter)
1906      {
1907         int ret = 0;
1908         _wl_init();
1909         while (!_eflutil.wl.shot.screenshooter && ret != -1)
1910           ret = wl_display_roundtrip_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
1911         EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.screenshooter, fail_init);
1912
1913        _eflutil.wl.shot.tbm_client = wayland_tbm_client_init(_eflutil.wl.dpy);
1914        EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.tbm_client, fail_init);
1915      }
1916
1917    EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
1918    EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
1919
1920    if (g_screenshot)
1921      {
1922         if (g_screenshot->width != width || g_screenshot->height != height)
1923           {
1924              g_screenshot->width = width;
1925              g_screenshot->height = height;
1926           }
1927
1928         return g_screenshot;
1929      }
1930
1931    screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
1932    EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
1933
1934    screenshot->width = width;
1935    screenshot->height = height;
1936
1937    screenshot->bufmgr = wayland_tbm_client_get_bufmgr(_eflutil.wl.shot.tbm_client);
1938    EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
1939
1940    g_screenshot = screenshot;
1941    set_last_result(EFL_UTIL_ERROR_NONE);
1942
1943    screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, &screenshot->shot_done);
1944
1945    return g_screenshot;
1946 #endif
1947 fail_param:
1948    if (screenshot)
1949      efl_util_screenshot_deinitialize(screenshot);
1950    set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1951    return NULL;
1952 fail_memory:
1953    if (screenshot)
1954      efl_util_screenshot_deinitialize(screenshot);
1955    set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY);
1956    return NULL;
1957 fail_init:
1958    if (screenshot)
1959      efl_util_screenshot_deinitialize(screenshot);
1960    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
1961    return NULL;
1962 }
1963
1964 API int
1965 efl_util_screenshot_deinitialize(efl_util_screenshot_h screenshot)
1966 {
1967 #if X11
1968    if (!screenshot)
1969      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1970
1971    /* tbm bufmgr */
1972    if (screenshot->bufmgr)
1973      tbm_bufmgr_deinit(screenshot->bufmgr);
1974
1975    DRI2DestroyDrawable(screenshot->dpy, screenshot->pixmap);
1976
1977    /* dri2 */
1978    if (screenshot->drm_fd)
1979      close(screenshot->drm_fd);
1980    if (screenshot->driver_name)
1981      free(screenshot->driver_name);
1982    if (screenshot->device_name)
1983      free(screenshot->device_name);
1984
1985    /* xv */
1986    if (screenshot->port > 0 && screenshot->pixmap > 0)
1987      XvStopVideo(screenshot->dpy, screenshot->port, screenshot->pixmap);
1988
1989    /* damage */
1990    if (screenshot->damage)
1991      XDamageDestroy(screenshot->dpy, screenshot->damage);
1992
1993    /* gc */
1994    if (screenshot->gc)
1995      XFreeGC(screenshot->dpy, screenshot->gc);
1996
1997    /* pixmap */
1998    if (screenshot->pixmap > 0)
1999      XFreePixmap(screenshot->dpy, screenshot->pixmap);
2000
2001    /* port */
2002    if (screenshot->port > 0)
2003      XvUngrabPort(screenshot->dpy, screenshot->port, 0);
2004
2005    XSync(screenshot->dpy, False);
2006
2007    /* dpy */
2008    if (screenshot->internal_display ==1 && screenshot->dpy)
2009      XCloseDisplay(screenshot->dpy);
2010
2011    free(screenshot);
2012    g_screenshot = NULL;
2013
2014    return EFL_UTIL_ERROR_NONE;
2015 #endif
2016 #if WAYLAND
2017    if (!screenshot)
2018      return EFL_UTIL_ERROR_INVALID_PARAMETER;
2019
2020    free(screenshot);
2021    g_screenshot = NULL;
2022
2023    if (_eflutil.wl.shot.screenshooter)
2024      screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, NULL);
2025
2026    return EFL_UTIL_ERROR_NONE;
2027 #endif
2028 }
2029
2030
2031 API tbm_surface_h
2032 efl_util_screenshot_take_tbm_surface(efl_util_screenshot_h screenshot)
2033 {
2034 #if X11
2035    XEvent ev = {0,};
2036    XErrorHandler old_handler = NULL;
2037    unsigned int attachment = DRI2BufferFrontLeft;
2038    int nbufs = 0;
2039    DRI2Buffer *bufs = NULL;
2040    tbm_bo t_bo = NULL;
2041    tbm_surface_h t_surface = NULL;
2042    int buf_width = 0;
2043    int buf_height = 0;
2044    tbm_surface_info_s surf_info;
2045    int i;
2046
2047    if (screenshot != g_screenshot)
2048      {
2049         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
2050         return NULL;
2051      }
2052
2053    /* for flush other pending requests and pending events */
2054    XSync(screenshot->dpy, 0);
2055
2056    g_efl_util_x_error_caught = False;
2057    old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
2058
2059    /* dump here */
2060    XvPutStill(screenshot->dpy, screenshot->port, screenshot->pixmap, screenshot->gc,
2061               0, 0, screenshot->width, screenshot->height,
2062               0, 0, screenshot->width, screenshot->height);
2063
2064    XSync(screenshot->dpy, 0);
2065
2066    if (g_efl_util_x_error_caught)
2067      {
2068         g_efl_util_x_error_caught = False;
2069         XSetErrorHandler(old_handler);
2070         goto fail;
2071      }
2072
2073    g_efl_util_x_error_caught = False;
2074    XSetErrorHandler(old_handler);
2075
2076    if (XPending(screenshot->dpy))
2077      XNextEvent(screenshot->dpy, &ev);
2078    else
2079      {
2080         int fd = ConnectionNumber(screenshot->dpy);
2081         fd_set mask;
2082         struct timeval tv;
2083         int ret;
2084
2085         FD_ZERO(&mask);
2086         FD_SET(fd, &mask);
2087
2088         tv.tv_usec = 0;
2089         tv.tv_sec = TIMEOUT_CAPTURE;
2090
2091         ret = select(fd + 1, &mask, 0, 0, &tv);
2092         if (ret < 0)
2093           fprintf(stderr, "[screenshot] fail: select.\n");
2094         else if (ret == 0)
2095           fprintf(stderr, "[screenshot] fail: timeout(%d sec)!\n", TIMEOUT_CAPTURE);
2096         else if (XPending(screenshot->dpy))
2097           XNextEvent(screenshot->dpy, &ev);
2098         else
2099           fprintf(stderr, "[screenshot] fail: not passed a event!\n");
2100      }
2101
2102    /* check if the capture is done by xserver and pixmap has got the captured image */
2103    if (ev.type == (screenshot->damage_base + XDamageNotify))
2104      {
2105         XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
2106         if (damage_ev->drawable == screenshot->pixmap)
2107           {
2108              /* Get DRI2 FrontLeft buffer of the pixmap */
2109              bufs = DRI2GetBuffers(screenshot->dpy, screenshot->pixmap, &buf_width, &buf_height, &attachment, 1, &nbufs);
2110              if (!bufs)
2111                {
2112                   fprintf(stderr, "[screenshot] fail: DRI2GetBuffers\n");
2113                   goto fail;
2114                }
2115
2116              t_bo = tbm_bo_import(screenshot->bufmgr, bufs[0].name);
2117              if (!t_bo)
2118                {
2119                   fprintf(stderr, "[screenshot] fail: import tbm_bo!\n");
2120                   goto fail;
2121                }
2122
2123              surf_info.width = buf_width;
2124              surf_info.height = buf_height;
2125              surf_info.format = TBM_FORMAT_XRGB8888;
2126              surf_info.bpp = 32;
2127              surf_info.size = bufs->pitch * surf_info.height;
2128              surf_info.num_planes = 1;
2129              for (i = 0; i < surf_info.num_planes; i++)
2130                {
2131                   surf_info.planes[i].size = bufs->pitch * surf_info.height;
2132                   surf_info.planes[i].stride = bufs->pitch;
2133                   surf_info.planes[i].offset = 0;
2134                }
2135              t_surface = tbm_surface_internal_create_with_bos(&surf_info, &t_bo, 1);
2136              if (!t_surface)
2137                {
2138                   fprintf(stderr, "[screenshot] fail: get tbm_surface!\n");
2139                   goto fail;
2140                }
2141
2142              tbm_bo_unref(t_bo);
2143              free(bufs);
2144
2145              XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
2146
2147              set_last_result(EFL_UTIL_ERROR_NONE);
2148
2149              return t_surface;
2150           }
2151
2152         XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
2153      }
2154
2155 fail:
2156
2157    if (t_bo)
2158      tbm_bo_unref(t_bo);
2159    if (bufs)
2160      free(bufs);
2161
2162    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
2163
2164    return NULL;
2165 #endif
2166
2167 #if WAYLAND
2168    tbm_surface_h t_surface = NULL;
2169    struct wl_buffer *buffer = NULL;
2170    Efl_Util_Wl_Output_Info *output;
2171    int ret = 0;
2172
2173    if (screenshot != g_screenshot)
2174      {
2175         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
2176         return NULL;
2177      }
2178
2179    output = eina_list_nth(_eflutil.wl.shot.output_list, 0);
2180    if (!output)
2181      {
2182         fprintf(stderr, "[screenshot] fail: no output for screenshot\n");
2183         goto fail;
2184      }
2185
2186    t_surface = tbm_surface_create(screenshot->width, screenshot->height, TBM_FORMAT_XRGB8888);
2187    if (!t_surface)
2188      {
2189         fprintf(stderr, "[screenshot] fail: tbm_surface_create\n");
2190         goto fail;
2191      }
2192
2193    buffer = wayland_tbm_client_create_buffer(_eflutil.wl.shot.tbm_client, t_surface);
2194    if (!buffer)
2195      {
2196         fprintf(stderr, "[screenshot] fail: create wl_buffer for screenshot\n");
2197         goto fail;
2198      }
2199
2200    screenshooter_shoot(_eflutil.wl.shot.screenshooter, output->output, buffer);
2201
2202    screenshot->shot_done = EINA_FALSE;
2203    while (!screenshot->shot_done && ret != -1)
2204      ret = wl_display_roundtrip_queue(_eflutil.wl.dpy, _eflutil.wl.queue);
2205
2206    if (ret == -1)
2207      {
2208         fprintf(stderr, "[screenshot] fail: screenshooter_shoot\n");
2209         goto fail;
2210      }
2211
2212    wl_buffer_destroy(buffer);
2213
2214    /* reset shot_done for next screenshot */
2215    screenshot->shot_done = EINA_FALSE;
2216
2217    return t_surface;
2218
2219 fail:
2220    if (t_surface)
2221      tbm_surface_destroy(t_surface);
2222    if (buffer)
2223      wl_buffer_destroy(buffer);
2224
2225    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
2226
2227    return NULL;
2228 #endif
2229 }