fix build break
[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 "tizen_notification-client-protocol.h"
48 #include "tizen_window_screen-client-protocol.h"
49 #include "tizen-buffer-pool-client-protocol.h"
50 #include "screenshooter-client-protocol.h"
51 #endif /* end of WAYLAND */
52
53 /* callback handler index */
54 #define CBH_NOTI_LEV 0
55 #define CBH_SCR_MODE 1
56 #define CBH_MAX      2
57
58 typedef void (*Efl_Util_Cb)(Evas_Object *, int, void *);
59
60 typedef struct _Efl_Util_Callback_Info
61 {
62    Evas_Object *win;
63    Efl_Util_Cb cb;
64    void *data;
65 } Efl_Util_Callback_Info;
66
67 #if WAYLAND
68 typedef struct _Efl_Util_Wl_Surface_Lv_Info
69 {
70    void *surface; /* wl_surface */
71    int level;
72    Eina_Bool wait_for_done;
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 } Efl_Util_Wl_Surface_Scr_Mode_Info;
81
82 typedef struct _Efl_Util_Wl_Output_Info
83 {
84     struct wl_output *output;
85     int offset_x, offset_y, width, height;
86 } Efl_Util_Wl_Output_Info;
87 #endif
88
89 typedef struct _Efl_Util_Data
90 {
91 #if X11
92    /* x11 related stuffs */
93    struct
94    {
95       Eina_Bool init;
96       Ecore_Event_Handler *handler; /* x11 client message handler */
97       Ecore_X_Display *dpy;
98    } x11;
99 #endif /* end of X11 */
100
101 #if WAYLAND
102    /* wayland related stuffs */
103    struct
104    {
105       Eina_Bool init;
106       struct wl_display *dpy;
107       struct
108       {
109          struct tizen_notification *proto;
110          Eina_Hash *hash;
111       } noti_lv;
112       struct
113       {
114          struct tizen_window_screen *proto;
115          Eina_Hash *hash;
116       } scr_mode;
117       struct
118       {
119          struct screenshooter *screenshooter;
120          struct tizen_buffer_pool *buffer_pool;
121          Eina_List *output_list;
122       } shot;
123    } wl;
124 #endif /* end of WAYLAND */
125
126    struct
127    {
128       Eina_List *info_list; /* list of callback info */
129       unsigned int atom; /* x11 atom */
130    } cb_handler[CBH_MAX];
131 } Efl_Util_Data;
132
133 static Efl_Util_Data _eflutil =
134 {
135 #if X11
136    {
137       EINA_FALSE,
138       NULL,
139       NULL
140    },
141 #endif /* end of X11 */
142 #if WAYLAND
143    {
144       EINA_FALSE,
145       NULL,
146       { NULL, NULL }, /* tizen_notification protocol */
147       { NULL, NULL },  /* tizen_window_screen protocol */
148       { NULL, NULL, NULL }  /* screenshooter protocol */
149    },
150 #endif /* end of WAYLAND */
151    {
152       { NULL, 0 }, /* handler for notification level */
153       { NULL, 0 }  /* handler for screen mode */
154    },
155 };
156
157 static Eina_Bool               _cb_info_add(Evas_Object *win, Efl_Util_Cb cb, void *data, int idx);
158 static Eina_Bool               _cb_info_del_by_win(Evas_Object *win, int idx);
159 static Eina_List              *_cb_info_list_get(int idx);
160 static Efl_Util_Callback_Info *_cb_info_find_by_win(Evas_Object *win, int idx);
161 #if X11
162 static Efl_Util_Callback_Info *_cb_info_find_by_xwin(unsigned int xwin, int idx);
163 static Eina_Bool               _cb_x11_client_msg(void *data, int type, void *event);
164 static Eina_Bool               _x11_init(void);
165 #endif /* end of X11 */
166 #if WAYLAND
167 static Eina_Bool               _wl_init(void);
168 static void                    _cb_wl_reg_global(void *data, struct wl_registry *reg, unsigned int name, const char *interface, unsigned int version);
169 static void                    _cb_wl_reg_global_remove(void *data, struct wl_registry *reg, unsigned int name);
170 static Efl_Util_Callback_Info *_cb_info_find_by_wlsurf(void *wlsurf, int idx);
171 static void                    _cb_wl_tz_noti_lv_done(void *data, struct tizen_notification *proto, struct wl_surface *surface, int32_t level, uint32_t state);
172 static void                    _cb_wl_tz_scr_mode_done(void *data, struct tizen_window_screen *proto, struct wl_surface *surface, uint32_t mode, uint32_t state);
173
174 static const struct wl_registry_listener _wl_reg_listener =
175 {
176    _cb_wl_reg_global,
177    _cb_wl_reg_global_remove
178 };
179
180 struct tizen_notification_listener _wl_tz_noti_lv_listener =
181 {
182    _cb_wl_tz_noti_lv_done
183 };
184
185 struct tizen_window_screen_listener _wl_tz_scr_mode_listener =
186 {
187    _cb_wl_tz_scr_mode_done
188 };
189 #endif /* end of WAYLAND */
190
191 static Eina_Bool
192 _cb_info_add(Evas_Object *win,
193              Efl_Util_Cb cb,
194              void *data,
195              int idx)
196 {
197    Efl_Util_Callback_Info *info;
198
199    info = _cb_info_find_by_win(win, idx);
200    if (info)
201      {
202         _eflutil.cb_handler[idx].info_list
203            = eina_list_remove(_eflutil.cb_handler[idx].info_list,
204                               info);
205         free(info);
206      }
207
208    info = (Efl_Util_Callback_Info *)calloc(1, sizeof(Efl_Util_Callback_Info));
209    if (!info) return EINA_FALSE;
210
211    info->win = win;
212    info->cb = cb;
213    info->data = data;
214
215    _eflutil.cb_handler[idx].info_list
216       = eina_list_append(_eflutil.cb_handler[idx].info_list,
217                          info);
218
219 #if X11
220    if (!_eflutil.x11.handler)
221      _eflutil.x11.handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
222                                                     _cb_x11_client_msg,
223                                                     NULL);
224 #endif /* end of X11 */
225
226    return EINA_TRUE;
227 }
228
229 static Eina_Bool
230 _cb_info_del_by_win(Evas_Object *win,
231                     int idx)
232 {
233    Efl_Util_Callback_Info *info;
234
235    info = _cb_info_find_by_win(win, idx);
236    if (!info) return EINA_FALSE;
237
238    _eflutil.cb_handler[idx].info_list
239       = eina_list_remove(_eflutil.cb_handler[idx].info_list,
240                          info);
241    free(info);
242
243 #if X11
244    unsigned int count = eina_list_count(_eflutil.cb_handler[idx].info_list);
245    if ((count == 0) && (_eflutil.x11.handler))
246      {
247         ecore_event_handler_del(_eflutil.x11.handler);
248         _eflutil.x11.handler = NULL;
249      }
250 #endif
251
252    return EINA_TRUE;
253 }
254
255 static Eina_List *
256 _cb_info_list_get(int idx)
257 {
258    return _eflutil.cb_handler[idx].info_list;
259 }
260
261 static Efl_Util_Callback_Info *
262 _cb_info_find_by_win(Evas_Object *win,
263                      int idx)
264 {
265    Eina_List *l, *ll;
266    Efl_Util_Callback_Info *info;
267
268    l = _cb_info_list_get(idx);
269    EINA_LIST_FOREACH(l, ll, info)
270      {
271         if (info->win == win) return info;
272      }
273
274    return NULL;
275 }
276
277 #if X11
278 static Efl_Util_Callback_Info *
279 _cb_info_find_by_xwin(unsigned int xwin,
280                       int idx)
281 {
282    Eina_List *l, *ll;
283    Efl_Util_Callback_Info *info;
284    unsigned int xwin2;
285
286    l = _cb_info_list_get(idx);
287    EINA_LIST_FOREACH(l, ll, info)
288      {
289         xwin2 = elm_win_xwindow_get(info->win);
290         if (xwin == xwin2) return info;
291      }
292
293    return NULL;
294 }
295
296 static Eina_Bool
297 _cb_x11_client_msg(void *data,
298                    int type,
299                    void *event)
300 {
301    Ecore_X_Event_Client_Message *ev;
302    Ecore_X_Window xwin;
303    Efl_Util_Callback_Info *info;
304
305    ev = event;
306    if (!ev) return ECORE_CALLBACK_PASS_ON;
307
308    xwin = ev->win;
309    if (xwin == 0) return ECORE_CALLBACK_PASS_ON;
310
311    if (ev->message_type == _eflutil.cb_handler[CBH_NOTI_LEV].atom)
312      {
313         info = _cb_info_find_by_xwin(xwin, CBH_NOTI_LEV);
314
315         /* permission denied */
316         if ((ev->data.l[1] == 0) &&
317             (info) &&
318             (info->cb))
319           {
320              info->cb(info->win,
321                       EFL_UTIL_ERROR_PERMISSION_DENIED,
322                       info->data);
323           }
324      }
325    else if (ev->message_type == _eflutil.cb_handler[CBH_SCR_MODE].atom)
326      {
327         info = _cb_info_find_by_xwin(xwin, CBH_SCR_MODE);
328
329         /* permission denied */
330         if ((ev->data.l[1] == 0) &&
331             (info) &&
332             (info->cb))
333           {
334              info->cb(info->win,
335                       EFL_UTIL_ERROR_PERMISSION_DENIED,
336                       info->data);
337           }
338      }
339    return ECORE_CALLBACK_PASS_ON;
340 }
341
342 static Eina_Bool
343 _x11_init(void)
344 {
345    if (_eflutil.x11.init) return EINA_TRUE;
346
347    _eflutil.x11.dpy = ecore_x_display_get();
348    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.x11.dpy, EINA_FALSE);
349
350    _eflutil.x11.init = EINA_TRUE;
351
352    return EINA_TRUE;
353 }
354 #endif /* end of X11 */
355
356 #if WAYLAND
357 static Eina_Bool
358 _wl_init(void)
359 {
360    struct wl_registry *reg;
361
362    if (_eflutil.wl.init) return EINA_TRUE;
363
364    ecore_wl_init(NULL);
365
366    _eflutil.wl.dpy = ecore_wl_display_get();
367    EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.dpy, EINA_FALSE);
368
369    reg = wl_display_get_registry(_eflutil.wl.dpy);
370    EINA_SAFETY_ON_NULL_RETURN_VAL(reg, EINA_FALSE);
371
372    wl_registry_add_listener(reg, &_wl_reg_listener, NULL);
373
374    _eflutil.wl.init = EINA_TRUE;
375
376    return EINA_TRUE;
377 }
378
379 static void
380 _cb_wl_output_geometry(void *data, struct wl_output *wl_output, int x, int y,
381                        int physical_width, int physical_height, int subpixel,
382                        const char *make, const char *model, int transform)
383 {
384    Efl_Util_Wl_Output_Info *output = wl_output_get_user_data(wl_output);
385    if (wl_output == output->output)
386      {
387         output->offset_x = x;
388         output->offset_y = y;
389      }
390 }
391
392 static void
393 _cb_wl_output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
394                    int width, int height, int refresh)
395 {
396    Efl_Util_Wl_Output_Info *output = wl_output_get_user_data(wl_output);
397    if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT))
398      {
399         output->width = width;
400         output->height = height;
401      }
402 }
403
404 static void
405 _cb_wl_output_done(void *data, struct wl_output *wl_output)
406 {
407 }
408
409 static void
410 _cb_wl_output_scale(void *data, struct wl_output *wl_output, int32_t factor)
411 {
412 }
413
414 static const struct wl_output_listener output_listener =
415 {
416     _cb_wl_output_geometry,
417     _cb_wl_output_mode,
418     _cb_wl_output_done,
419     _cb_wl_output_scale
420 };
421
422 static void
423 _cb_wl_screenshot_done(void *data, struct screenshooter *screenshooter)
424 {
425    Eina_Bool *shot_done = (Eina_Bool*)data;
426    if (shot_done)
427      *shot_done = EINA_TRUE;
428 }
429
430 static const struct screenshooter_listener screenshooter_listener =
431 {
432     _cb_wl_screenshot_done
433 };
434
435 static void
436 _cb_wl_reg_global(void *data,
437                   struct wl_registry *reg,
438                   unsigned int name,
439                   const char *interface,
440                   unsigned int version)
441 {
442    if (!strcmp(interface, "tizen_notification"))
443      {
444         struct tizen_notification *proto;
445         proto = wl_registry_bind(reg,
446                                  name,
447                                  &tizen_notification_interface,
448                                  1);
449         if (!proto) return;
450
451         tizen_notification_add_listener(proto,
452                                         &_wl_tz_noti_lv_listener,
453                                         NULL);
454
455         _eflutil.wl.noti_lv.hash = eina_hash_pointer_new(free);
456         _eflutil.wl.noti_lv.proto = proto;
457      }
458    else if (!strcmp(interface, "tizen_window_screen"))
459      {
460         struct tizen_window_screen *proto;
461         proto = wl_registry_bind(reg,
462                                  name,
463                                  &tizen_window_screen_interface,
464                                  1);
465         if (!proto) return;
466
467         tizen_window_screen_add_listener(proto,
468                                          &_wl_tz_scr_mode_listener,
469                                          NULL);
470
471         _eflutil.wl.scr_mode.hash = eina_hash_pointer_new(free);
472         _eflutil.wl.scr_mode.proto = proto;
473      }
474    else if (strcmp(interface, "wl_output") == 0)
475      {
476         Efl_Util_Wl_Output_Info *output = calloc(1, sizeof(Efl_Util_Wl_Output_Info));
477         EINA_SAFETY_ON_NULL_RETURN(output);
478
479         _eflutil.wl.shot.output_list = eina_list_append(_eflutil.wl.shot.output_list, output);
480
481         output->output = wl_registry_bind(reg, name, &wl_output_interface, version);
482         wl_output_add_listener(output->output, &output_listener, output);
483      }
484    else if (strcmp(interface, "tizen_buffer_pool") == 0)
485      {
486         _eflutil.wl.shot.buffer_pool = wl_registry_bind(reg, name, &tizen_buffer_pool_interface, 1);
487      }
488    else if (strcmp(interface, "screenshooter") == 0)
489      {
490         _eflutil.wl.shot.screenshooter = wl_registry_bind(reg, name, &screenshooter_interface, version);
491         screenshooter_add_listener(_eflutil.wl.shot.screenshooter, &screenshooter_listener, NULL);
492      }
493 }
494
495 static void
496 _cb_wl_reg_global_remove(void *data,
497                          struct wl_registry *reg,
498                          unsigned int name)
499 {
500    _eflutil.wl.noti_lv.proto = NULL;
501    eina_hash_free(_eflutil.wl.noti_lv.hash);
502    _eflutil.wl.scr_mode.proto = NULL;
503    eina_hash_free(_eflutil.wl.scr_mode.hash);
504 }
505
506 static Efl_Util_Callback_Info *
507 _cb_info_find_by_wlsurf(void *wlsurf,
508                         int idx)
509 {
510    Eina_List *l, *ll;
511    Efl_Util_Callback_Info *info;
512    Ecore_Wl_Window *wlwin2 = NULL;
513    void *wlsurf2 = NULL;
514
515    l = _cb_info_list_get(idx);
516    EINA_LIST_FOREACH(l, ll, info)
517      {
518         wlwin2 = elm_win_wl_window_get(info->win);
519         wlsurf2 = ecore_wl_window_surface_get(wlwin2);
520         if (wlsurf== wlsurf2) return info;
521      }
522
523    return NULL;
524 }
525
526 static void
527 _cb_wl_tz_noti_lv_done(void *data,
528                        struct tizen_notification *proto,
529                        struct wl_surface *surface,
530                        int32_t level,
531                        uint32_t state)
532 {
533    Efl_Util_Wl_Surface_Lv_Info *lv_info;
534    Efl_Util_Callback_Info *cb_info;
535
536    lv_info = eina_hash_find(_eflutil.wl.noti_lv.hash, &surface);
537    if (lv_info)
538      {
539         lv_info->level = level;
540         lv_info->wait_for_done = EINA_FALSE;
541      }
542
543    if (state != TIZEN_NOTIFICATION_ERROR_STATE_PERMISSION_DENIED) return;
544
545    cb_info = _cb_info_find_by_wlsurf((void *)surface, CBH_NOTI_LEV);
546    if (!cb_info) return;
547    if (!cb_info->cb) return;
548
549    cb_info->cb(cb_info->win,
550                EFL_UTIL_ERROR_PERMISSION_DENIED,
551                cb_info->data);
552 }
553
554 static void
555 _cb_wl_tz_scr_mode_done(void *data,
556                         struct tizen_window_screen *proto,
557                         struct wl_surface *surface,
558                         uint32_t mode,
559                         uint32_t state)
560 {
561
562    Efl_Util_Wl_Surface_Scr_Mode_Info *scr_mode_info;
563    Efl_Util_Callback_Info *cb_info;
564
565    scr_mode_info = eina_hash_find(_eflutil.wl.scr_mode.hash, &surface);
566    if (scr_mode_info)
567      {
568         scr_mode_info->mode = mode;
569         scr_mode_info->wait_for_done = EINA_FALSE;
570      }
571
572    if (state != TIZEN_WINDOW_SCREEN_ERROR_STATE_PERMISSION_DENIED) return;
573
574    cb_info = _cb_info_find_by_wlsurf((void *)surface, CBH_SCR_MODE);
575    if (!cb_info) return;
576    if (!cb_info->cb) return;
577
578    cb_info->cb(cb_info->win,
579                EFL_UTIL_ERROR_PERMISSION_DENIED,
580                cb_info->data);
581 }
582 #endif /* end of WAYLAND */
583
584 API int
585 efl_util_set_notification_window_level(Evas_Object *window,
586                                        efl_util_notification_level_e level)
587 {
588    Eina_Bool res;
589
590    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
591    EINA_SAFETY_ON_FALSE_RETURN_VAL((level >= EFL_UTIL_NOTIFICATION_LEVEL_1) &&
592                                    (level <= EFL_UTIL_NOTIFICATION_LEVEL_TOP),
593                                    EFL_UTIL_ERROR_INVALID_PARAMETER);
594
595 #if X11
596    Ecore_X_Window_Type window_type;
597    Ecore_X_Window xwin;
598
599    res = _x11_init();
600    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
601
602    xwin = elm_win_xwindow_get(window);
603    if (xwin)
604      {
605         if (ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
606           {
607              // success to get window type
608              if (window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
609                {
610                   // given EFL window's type is not notification type.
611                   return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
612                }
613           }
614         else
615           return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
616
617         utilx_set_system_notification_level(_eflutil.x11.dpy,
618                                             xwin,
619                                             level);
620         return EFL_UTIL_ERROR_NONE;
621      }
622 #endif /* end of X11 */
623
624 #if WAYLAND
625    Elm_Win_Type type;
626    Ecore_Wl_Window *wlwin;
627    struct wl_surface *surface;
628    Efl_Util_Wl_Surface_Lv_Info *lv_info;
629
630    res = _wl_init();
631    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
632
633    type = elm_win_type_get(window);
634    EINA_SAFETY_ON_FALSE_RETURN_VAL((type == ELM_WIN_NOTIFICATION),
635                                    EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
636
637    wlwin = elm_win_wl_window_get(window);
638    if (wlwin)
639      {
640         while (!_eflutil.wl.noti_lv.proto)
641           wl_display_dispatch(_eflutil.wl.dpy);
642
643         surface = ecore_wl_window_surface_get(wlwin);
644         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
645                                        EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
646
647         lv_info = eina_hash_find(_eflutil.wl.noti_lv.hash, &surface);
648         if (!lv_info)
649           {
650              lv_info = calloc(1, sizeof(Efl_Util_Wl_Surface_Lv_Info));
651              EINA_SAFETY_ON_NULL_RETURN_VAL(lv_info, EFL_UTIL_ERROR_OUT_OF_MEMORY);
652
653              lv_info->surface = surface;
654              lv_info->level = (int)level;
655              lv_info->wait_for_done = EINA_TRUE;
656
657              eina_hash_add(_eflutil.wl.noti_lv.hash,
658                            &surface,
659                            lv_info);
660           }
661         else
662           {
663              lv_info->level = (int)level;
664              lv_info->wait_for_done = EINA_TRUE;
665           }
666
667         tizen_notification_set_level(_eflutil.wl.noti_lv.proto,
668                                      surface,
669                                      (int)level);
670
671         return EFL_UTIL_ERROR_NONE;
672      }
673 #endif /* end of WAYLAND */
674
675    return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
676 }
677
678 API int
679 efl_util_get_notification_window_level(Evas_Object *window,
680                                        efl_util_notification_level_e *level)
681 {
682    Eina_Bool res;
683
684    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
685    EINA_SAFETY_ON_NULL_RETURN_VAL(level, EFL_UTIL_ERROR_INVALID_PARAMETER);
686
687 #if X11
688    Ecore_X_Window_Type window_type;
689    Utilx_Notification_Level utilx_level;
690    Ecore_X_Window xwin;
691
692    res = _x11_init();
693    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
694
695    xwin = elm_win_xwindow_get(window);
696    if (xwin)
697      {
698         if (ecore_x_netwm_window_type_get(xwin, &window_type) == EINA_TRUE)
699           {
700              // success to get window type
701              if (window_type != ECORE_X_WINDOW_TYPE_NOTIFICATION)
702                {
703                   // given EFL window's type is not notification type.
704                   return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
705                }
706
707              utilx_level = utilx_get_system_notification_level(_eflutil.x11.dpy, xwin);
708              if (utilx_level == UTILX_NOTIFICATION_LEVEL_LOW)
709                *level = EFL_UTIL_NOTIFICATION_LEVEL_1;
710              else if(utilx_level == UTILX_NOTIFICATION_LEVEL_NORMAL)
711                *level = EFL_UTIL_NOTIFICATION_LEVEL_2;
712              else if(utilx_level == UTILX_NOTIFICATION_LEVEL_HIGH)
713                *level = EFL_UTIL_NOTIFICATION_LEVEL_3;
714              else
715                return EFL_UTIL_ERROR_INVALID_PARAMETER;
716           }
717         else
718           return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
719
720         return EFL_UTIL_ERROR_NONE;
721      }
722 #endif /* end of X11 */
723
724 #if WAYLAND
725    Elm_Win_Type type;
726    Ecore_Wl_Window *wlwin;
727    struct wl_surface *surface;
728    Efl_Util_Wl_Surface_Lv_Info *lv_info;
729
730    res = _wl_init();
731    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
732
733    type = elm_win_type_get(window);
734    EINA_SAFETY_ON_FALSE_RETURN_VAL((type == ELM_WIN_NOTIFICATION),
735                                    EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
736
737    wlwin = elm_win_wl_window_get(window);
738    if (wlwin)
739      {
740         while (!_eflutil.wl.noti_lv.proto)
741           wl_display_dispatch(_eflutil.wl.dpy);
742
743         surface = ecore_wl_window_surface_get(wlwin);
744         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
745                                        EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE);
746
747         lv_info = eina_hash_find(_eflutil.wl.noti_lv.hash, &surface);
748         if (lv_info)
749           {
750              if (lv_info->wait_for_done)
751                {
752                   if (ecore_wl_window_shell_surface_get(wlwin) ||
753                       ecore_wl_window_xdg_surface_get(wlwin))
754                     {
755                        while (lv_info->wait_for_done)
756                          {
757                             ecore_wl_flush();
758                             wl_display_dispatch(_eflutil.wl.dpy);
759                          }
760                     }
761                   else
762                     {
763                        *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
764                        return EFL_UTIL_ERROR_INVALID_PARAMETER;
765                     }
766                }
767
768              switch (lv_info->level)
769                {
770                 case TIZEN_NOTIFICATION_LEVEL_1:       *level = EFL_UTIL_NOTIFICATION_LEVEL_1;       break;
771                 case TIZEN_NOTIFICATION_LEVEL_2:       *level = EFL_UTIL_NOTIFICATION_LEVEL_2;       break;
772                 case TIZEN_NOTIFICATION_LEVEL_3:       *level = EFL_UTIL_NOTIFICATION_LEVEL_3;       break;
773                 case TIZEN_NOTIFICATION_LEVEL_NONE:    *level = EFL_UTIL_NOTIFICATION_LEVEL_NONE;    break;
774                 case TIZEN_NOTIFICATION_LEVEL_DEFAULT: *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT; break;
775                 case TIZEN_NOTIFICATION_LEVEL_MEDIUM:  *level = EFL_UTIL_NOTIFICATION_LEVEL_MEDIUM;  break;
776                 case TIZEN_NOTIFICATION_LEVEL_HIGH:    *level = EFL_UTIL_NOTIFICATION_LEVEL_HIGH;    break;
777                 case TIZEN_NOTIFICATION_LEVEL_TOP:     *level = EFL_UTIL_NOTIFICATION_LEVEL_TOP;     break;
778                 default:                               *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
779                                                        return EFL_UTIL_ERROR_INVALID_PARAMETER;
780                }
781              return EFL_UTIL_ERROR_NONE;
782           }
783         else
784           *level = EFL_UTIL_NOTIFICATION_LEVEL_DEFAULT;
785
786         return EFL_UTIL_ERROR_NONE;
787      }
788 #endif /* end of WAYLAND */
789    return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
790 }
791
792 API int
793 efl_util_set_notification_window_level_error_cb(Evas_Object *window,
794                                                 efl_util_notification_window_level_error_cb callback,
795                                                 void *user_data)
796 {
797    Eina_Bool ret = EINA_FALSE;
798
799    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
800    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EFL_UTIL_ERROR_INVALID_PARAMETER);
801
802    ret = _cb_info_add(window,
803                       (Efl_Util_Cb)callback,
804                       user_data,
805                       CBH_NOTI_LEV);
806    if (!ret) return EFL_UTIL_ERROR_OUT_OF_MEMORY;
807
808 #if X11
809    if (!_eflutil.cb_handler[CBH_NOTI_LEV].atom)
810      _eflutil.cb_handler[CBH_NOTI_LEV].atom = ecore_x_atom_get("_E_NOTIFICATION_LEVEL_ACCESS_RESULT");
811 #endif /* end of X11 */
812
813    return EFL_UTIL_ERROR_NONE;
814 }
815
816 API int
817 efl_util_unset_notification_window_level_error_cb(Evas_Object *window)
818 {
819    Eina_Bool ret = EINA_FALSE;
820
821    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
822
823    ret = _cb_info_del_by_win(window, CBH_NOTI_LEV);
824    if (!ret) return EFL_UTIL_ERROR_INVALID_PARAMETER;
825
826    return EFL_UTIL_ERROR_NONE;
827 }
828
829 API int
830 efl_util_set_window_opaque_state(Evas_Object *window,
831                                  int opaque)
832 {
833    Eina_Bool res;
834
835    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
836    EINA_SAFETY_ON_FALSE_RETURN_VAL(((opaque >= 0) && (opaque <= 1)),
837                                    EFL_UTIL_ERROR_INVALID_PARAMETER);
838
839 #if X11
840    Ecore_X_Window xwin;
841    Utilx_Opaque_State state;
842    int ret;
843
844    res = _x11_init();
845    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
846
847    xwin = elm_win_xwindow_get(window);
848    EINA_SAFETY_ON_FALSE_RETURN_VAL(xwin > 0, EFL_UTIL_ERROR_INVALID_PARAMETER);
849
850    if (opaque)
851      state = UTILX_OPAQUE_STATE_ON;
852    else
853      state = UTILX_OPAQUE_STATE_OFF;
854
855    ret = utilx_set_window_opaque_state(_eflutil.x11.dpy,
856                                        xwin,
857                                        state);
858
859    if (!ret)
860      return EFL_UTIL_ERROR_INVALID_PARAMETER;
861    else
862      return EFL_UTIL_ERROR_NONE;
863 #endif /* end of X11 */
864
865 #if WAYLAND
866    Ecore_Wl_Window *wlwin;
867    int x, y, w, h;
868
869    res = _wl_init();
870    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
871
872    wlwin = elm_win_wl_window_get(window);
873    if (wlwin)
874      {
875         evas_object_geometry_get(window, &x, &y, &w, &h);
876
877         if (opaque)
878           ecore_wl_window_opaque_region_set(wlwin, x, y, w, h);
879         else
880           ecore_wl_window_opaque_region_set(wlwin, 0, 0, 0, 0);
881
882         return EFL_UTIL_ERROR_NONE;
883      }
884
885    return EFL_UTIL_ERROR_NOT_SUPPORTED_WINDOW_TYPE;
886 #endif /* end of WAYLAND */
887 }
888
889 API int
890 efl_util_set_window_screen_mode(Evas_Object *window,
891                                 efl_util_screen_mode_e mode)
892 {
893    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
894    EINA_SAFETY_ON_FALSE_RETURN_VAL(((mode >= EFL_UTIL_SCREEN_MODE_DEFAULT) &&
895                                     (mode <= EFL_UTIL_SCREEN_MODE_ALWAYS_ON)),
896                                    EFL_UTIL_ERROR_INVALID_PARAMETER);
897
898 #if X11
899    Evas *e;
900    Ecore_Evas *ee;
901    int id;
902
903    e = evas_object_evas_get(window);
904    EINA_SAFETY_ON_NULL_RETURN_VAL(e, EFL_UTIL_ERROR_INVALID_PARAMETER);
905
906    ee = ecore_evas_ecore_evas_get(e);
907    EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EFL_UTIL_ERROR_INVALID_PARAMETER);
908
909    id = ecore_evas_aux_hint_id_get(ee, "wm.policy.win.lcd.lock");
910    if (mode == EFL_UTIL_SCREEN_MODE_ALWAYS_ON)
911      {
912         if (id == -1)
913           ecore_evas_aux_hint_add(ee, "wm.policy.win.lcd.lock", "1");
914         else
915           ecore_evas_aux_hint_val_set(ee, id, "1");
916      }
917    else if (mode == EFL_UTIL_SCREEN_MODE_DEFAULT)
918      {
919         if (id == -1)
920           ecore_evas_aux_hint_add(ee, "wm.policy.win.lcd.lock", "0");
921         else
922           ecore_evas_aux_hint_val_set(ee, id, "0");
923      }
924    else
925      return EFL_UTIL_ERROR_INVALID_PARAMETER;
926
927    return EFL_UTIL_ERROR_NONE;
928 #endif /* end of X11 */
929
930 #if WAYLAND
931    Ecore_Wl_Window *wlwin;
932    struct wl_surface *surface;
933    Efl_Util_Wl_Surface_Scr_Mode_Info *scr_mode_info;
934    Eina_Bool res;
935
936    res = _wl_init();
937    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
938
939    wlwin = elm_win_wl_window_get(window);
940    if (wlwin)
941      {
942         while (!_eflutil.wl.scr_mode.proto)
943           wl_display_dispatch(_eflutil.wl.dpy);
944
945         surface = ecore_wl_window_surface_get(wlwin);
946         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
947                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
948
949         scr_mode_info = eina_hash_find(_eflutil.wl.scr_mode.hash, &surface);
950         if (!scr_mode_info)
951           {
952              scr_mode_info = calloc(1, sizeof(Efl_Util_Wl_Surface_Scr_Mode_Info));
953              EINA_SAFETY_ON_NULL_RETURN_VAL(scr_mode_info, EFL_UTIL_ERROR_OUT_OF_MEMORY);
954
955              scr_mode_info->surface = surface;
956              scr_mode_info->mode = (unsigned int)mode;
957              scr_mode_info->wait_for_done = EINA_TRUE;
958
959              eina_hash_add(_eflutil.wl.scr_mode.hash,
960                            &surface,
961                            scr_mode_info);
962           }
963         else
964           {
965              scr_mode_info->mode = (unsigned int)mode;
966              scr_mode_info->wait_for_done = EINA_TRUE;
967           }
968
969         tizen_window_screen_set_mode(_eflutil.wl.scr_mode.proto,
970                                      surface,
971                                      (unsigned int)mode);
972
973         return EFL_UTIL_ERROR_NONE;
974      }
975    else
976      return EFL_UTIL_ERROR_INVALID_PARAMETER;
977 #endif /* end of WAYLAND */
978 }
979
980 API int
981 efl_util_get_window_screen_mode(Evas_Object *window,
982                                 efl_util_screen_mode_e *mode)
983 {
984    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
985    EINA_SAFETY_ON_NULL_RETURN_VAL(mode, EFL_UTIL_ERROR_INVALID_PARAMETER);
986
987 #if X11
988    Evas *e;
989    Ecore_Evas *ee;
990    const char *str;
991    int id;
992
993    e = evas_object_evas_get(window);
994    EINA_SAFETY_ON_NULL_RETURN_VAL(e, EFL_UTIL_ERROR_INVALID_PARAMETER);
995
996    ee = ecore_evas_ecore_evas_get(e);
997    EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EFL_UTIL_ERROR_INVALID_PARAMETER);
998
999    id = ecore_evas_aux_hint_id_get(ee, "wm.policy.win.lcd.lock");
1000    EINA_SAFETY_ON_TRUE_RETURN_VAL((id == -1), EFL_UTIL_ERROR_INVALID_PARAMETER);
1001
1002    str = ecore_evas_aux_hint_val_get(ee, id);
1003    EINA_SAFETY_ON_NULL_RETURN_VAL(str, EFL_UTIL_ERROR_INVALID_PARAMETER);
1004
1005    if (strncmp(str, "1", strlen("1")) == 0)
1006      *mode = EFL_UTIL_SCREEN_MODE_ALWAYS_ON;
1007    else
1008      *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;
1009
1010    return EFL_UTIL_ERROR_NONE;
1011 #endif /* end of X11 */
1012
1013 #if WAYLAND
1014    Ecore_Wl_Window *wlwin;
1015    struct wl_surface *surface;
1016    Efl_Util_Wl_Surface_Scr_Mode_Info *scr_mode_info;
1017    Eina_Bool res;
1018
1019    res = _wl_init();
1020    EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EFL_UTIL_ERROR_INVALID_PARAMETER);
1021
1022    wlwin = elm_win_wl_window_get(window);
1023    if (wlwin)
1024      {
1025         while (!_eflutil.wl.scr_mode.proto)
1026           wl_display_dispatch(_eflutil.wl.dpy);
1027
1028         surface = ecore_wl_window_surface_get(wlwin);
1029         EINA_SAFETY_ON_NULL_RETURN_VAL(surface,
1030                                        EFL_UTIL_ERROR_INVALID_PARAMETER);
1031
1032         scr_mode_info = eina_hash_find(_eflutil.wl.scr_mode.hash, &surface);
1033         if (scr_mode_info)
1034           {
1035              if (scr_mode_info->wait_for_done)
1036                {
1037                   while (scr_mode_info->wait_for_done)
1038                     {
1039                        ecore_wl_flush();
1040                        wl_display_dispatch(_eflutil.wl.dpy);
1041                     }
1042                }
1043
1044              switch (scr_mode_info->mode)
1045                {
1046                 case TIZEN_WINDOW_SCREEN_MODE_DEFAULT:   *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;   break;
1047                 case TIZEN_WINDOW_SCREEN_MODE_ALWAYS_ON: *mode = EFL_UTIL_SCREEN_MODE_ALWAYS_ON; break;
1048                 default:                                 *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;
1049                   return EFL_UTIL_ERROR_INVALID_PARAMETER;
1050                }
1051              return EFL_UTIL_ERROR_NONE;
1052           }
1053         else
1054           {
1055              *mode = EFL_UTIL_SCREEN_MODE_DEFAULT;
1056              return EFL_UTIL_ERROR_INVALID_PARAMETER;
1057           }
1058      }
1059    else
1060      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1061 #endif /* end of WAYLAND */
1062 }
1063
1064 API int
1065 efl_util_set_window_screen_mode_error_cb(Evas_Object *window,
1066                                          efl_util_window_screen_mode_error_cb callback,
1067                                          void *user_data)
1068 {
1069    Eina_Bool ret = EINA_FALSE;
1070
1071    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1072    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EFL_UTIL_ERROR_INVALID_PARAMETER);
1073
1074    ret = _cb_info_add(window,
1075                       (Efl_Util_Cb)callback,
1076                       user_data,
1077                       CBH_SCR_MODE);
1078    if (!ret) return EFL_UTIL_ERROR_OUT_OF_MEMORY;
1079
1080 #if X11
1081    if (!_eflutil.cb_handler[CBH_SCR_MODE].atom)
1082      _eflutil.cb_handler[CBH_SCR_MODE].atom = ecore_x_atom_get("_E_SCREEN_MODE_ACCESS_RESULT");
1083 #endif /* end of X11 */
1084
1085    return EFL_UTIL_ERROR_NONE;
1086 }
1087
1088 API int
1089 efl_util_unset_window_screen_mode_error_cb(Evas_Object *window)
1090 {
1091    Eina_Bool ret = EINA_FALSE;
1092
1093    EINA_SAFETY_ON_NULL_RETURN_VAL(window, EFL_UTIL_ERROR_INVALID_PARAMETER);
1094
1095    ret = _cb_info_del_by_win(window, CBH_SCR_MODE);
1096    if (!ret) return EFL_UTIL_ERROR_INVALID_PARAMETER;
1097
1098    return EFL_UTIL_ERROR_NONE;
1099 }
1100
1101 API int
1102 efl_util_input_initialize_generator(efl_util_input_device_type_e dev_type)
1103 {
1104    return EFL_UTIL_ERROR_NONE;
1105 }
1106
1107 API void
1108 efl_util_input_deinitialize_generator(void)
1109 {
1110    return;
1111 }
1112
1113 API int
1114 efl_util_input_generate_key(const char *key_name,
1115                             int pressed)
1116 {
1117    return EFL_UTIL_ERROR_NONE;
1118 }
1119
1120 API int
1121 efl_util_input_generate_touch(int idx,
1122                               efl_util_input_touch_type_e touch_type,
1123                               int x,
1124                               int y)
1125 {
1126    return EFL_UTIL_ERROR_NONE;
1127 }
1128
1129 struct _efl_util_screenshot_h
1130 {
1131    int width;
1132    int height;
1133
1134 #if X11
1135    Ecore_X_Display *dpy;
1136    int internal_display;
1137    int screen;
1138    Window root;
1139    Pixmap pixmap;
1140    GC gc;
1141    Atom atom_capture;
1142
1143    /* port */
1144    int port;
1145
1146    /* damage */
1147    Damage   damage;
1148    int      damage_base;
1149
1150    /* dri2 */
1151    int eventBase, errorBase;
1152    int dri2Major, dri2Minor;
1153    char *driver_name, *device_name;
1154    drm_magic_t magic;
1155
1156    /* drm */
1157    int drm_fd;
1158 #endif
1159
1160    Eina_Bool shot_done;
1161
1162    /* tbm bufmgr */
1163    tbm_bufmgr bufmgr;
1164 };
1165
1166 /* scrrenshot handle */
1167 static efl_util_screenshot_h g_screenshot;
1168
1169 #if X11
1170 #define FOURCC(a,b,c,d) (((unsigned)d&0xff)<<24 | ((unsigned)c&0xff)<<16 | ((unsigned)b&0xff)<<8 | ((unsigned)a&0xff))
1171 #define FOURCC_RGB32    FOURCC('R','G','B','4')
1172 #define TIMEOUT_CAPTURE 3
1173
1174 /* x error handling */
1175 static Bool g_efl_util_x_error_caught;
1176
1177 static int
1178 _efl_util_screenshot_x_error_handle(Display *dpy, XErrorEvent *ev)
1179 {
1180    if (!g_screenshot || (dpy != g_screenshot->dpy))
1181      return 0;
1182
1183    g_efl_util_x_error_caught = True;
1184
1185    return 0;
1186 }
1187
1188 static int
1189 _efl_util_screenshot_get_port(Display *dpy, unsigned int id, Window win)
1190 {
1191    unsigned int ver, rev, req_base, evt_base, err_base;
1192    unsigned int adaptors;
1193    XvAdaptorInfo *ai = NULL;
1194    XvImageFormatValues *fo = NULL;
1195    int formats;
1196    int i, j, p;
1197
1198    if (XvQueryExtension(dpy, &ver, &rev, &req_base, &evt_base, &err_base) != Success)
1199      {
1200         fprintf(stderr, "[screenshot] fail: no XV extension. \n");
1201         return -1;
1202      }
1203
1204    if (XvQueryAdaptors(dpy, win, &adaptors, &ai) != Success)
1205      {
1206         fprintf(stderr, "[screenshot] fail: query adaptors. \n");
1207         return -1;
1208      }
1209
1210    EINA_SAFETY_ON_NULL_RETURN_VAL(ai, -1);
1211
1212    for (i = 0; i < adaptors; i++)
1213      {
1214         int support_format = False;
1215
1216         if (!(ai[i].type & XvInputMask) ||
1217             !(ai[i].type & XvStillMask))
1218           continue;
1219
1220         p = ai[i].base_id;
1221
1222         fo = XvListImageFormats(dpy, p, &formats);
1223         for (j = 0; j < formats; j++)
1224           if (fo[j].id == (int)id)
1225             support_format = True;
1226
1227         if (fo)
1228           XFree(fo);
1229
1230         if (!support_format)
1231           continue;
1232
1233         for (; p < ai[i].base_id + ai[i].num_ports; p++)
1234           {
1235              if (XvGrabPort(dpy, p, 0) == Success)
1236                {
1237                   XvFreeAdaptorInfo(ai);
1238                   return p;
1239                }
1240           }
1241      }
1242
1243    XvFreeAdaptorInfo(ai);
1244
1245    XSync(dpy, False);
1246
1247    return -1;
1248 }
1249
1250 static int _efl_util_screenshot_get_best_size(Display *dpy, int port, int width, int height, unsigned int *best_width, unsigned int *best_height)
1251 {
1252    XErrorHandler old_handler = NULL;
1253
1254    Atom atom_capture = XInternAtom(dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
1255
1256    g_efl_util_x_error_caught = False;
1257    old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
1258
1259    XvSetPortAttribute(dpy, port, atom_capture, 1);
1260    XSync(dpy, False);
1261
1262    g_efl_util_x_error_caught = False;
1263    XSetErrorHandler(old_handler);
1264
1265    XvQueryBestSize(dpy, port, 0, 0, 0, width, height, best_width, best_height);
1266    if (best_width <= 0 || best_height <= 0)
1267      return 0;
1268
1269    return 1;
1270 }
1271 #endif
1272
1273 API efl_util_screenshot_h efl_util_screenshot_initialize(int width, int height)
1274 {
1275 #if X11
1276    efl_util_screenshot_h screenshot = NULL;
1277    int depth = 0;
1278    int damage_err_base = 0;
1279    unsigned int best_width = 0;
1280    unsigned int best_height = 0;
1281
1282    EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
1283    EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
1284
1285    if (g_screenshot != NULL)
1286      {
1287         if (g_screenshot->width != width || g_screenshot->height != height)
1288           {
1289              // TODO: recreate pixmap and update information
1290              if (!_efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height))
1291                {
1292                   set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
1293                   return NULL;
1294                }
1295
1296              g_screenshot->width = width;
1297              g_screenshot->height = height;
1298           }
1299
1300         return g_screenshot;
1301      }
1302
1303    screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
1304    EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
1305
1306    /* set dpy */
1307    screenshot->dpy = ecore_x_display_get();
1308    if (!screenshot->dpy)
1309      {
1310         screenshot->dpy = XOpenDisplay(0);
1311         EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_init);
1312
1313         /* for XCloseDisplay at denitialization */
1314         screenshot->internal_display = 1;
1315      }
1316
1317    /* set screen */
1318    screenshot->screen = DefaultScreen(screenshot->dpy);
1319
1320    /* set root window */
1321    screenshot->root = DefaultRootWindow(screenshot->dpy);
1322
1323    /* initialize capture adaptor */
1324    screenshot->port = _efl_util_screenshot_get_port(screenshot->dpy, FOURCC_RGB32, screenshot->root);
1325    EINA_SAFETY_ON_FALSE_GOTO(screenshot->port > 0, fail_init);
1326
1327    /* get the best size */
1328    _efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height);
1329    EINA_SAFETY_ON_FALSE_GOTO(best_width > 0, fail_init);
1330    EINA_SAFETY_ON_FALSE_GOTO(best_height > 0, fail_init);
1331
1332    /* set the width and the height */
1333    screenshot->width = best_width;
1334    screenshot->height = best_height;
1335
1336    /* create a pixmap */
1337    depth = DefaultDepth(screenshot->dpy, screenshot->screen);
1338    screenshot->pixmap = XCreatePixmap(screenshot->dpy, screenshot->root, screenshot->width, screenshot->height, depth);
1339    EINA_SAFETY_ON_FALSE_GOTO(screenshot->pixmap > 0, fail_init);
1340
1341    screenshot->gc = XCreateGC(screenshot->dpy, screenshot->pixmap, 0, 0);
1342    EINA_SAFETY_ON_NULL_GOTO(screenshot->gc, fail_init);
1343
1344    XSetForeground(screenshot->dpy, screenshot->gc, 0xFF000000);
1345    XFillRectangle(screenshot->dpy, screenshot->pixmap, screenshot->gc, 0, 0, width, height);
1346
1347    /* initialize damage */
1348    if (!XDamageQueryExtension(screenshot->dpy, &screenshot->damage_base, &damage_err_base))
1349      goto fail_init;
1350
1351    screenshot->damage = XDamageCreate(screenshot->dpy, screenshot->pixmap, XDamageReportNonEmpty);
1352    EINA_SAFETY_ON_FALSE_GOTO(screenshot->damage > 0, fail_init);
1353
1354    /* initialize dri3 and dri2 */
1355    if (!DRI2QueryExtension(screenshot->dpy, &screenshot->eventBase, &screenshot->errorBase))
1356      {
1357         fprintf(stderr, "[screenshot] fail: DRI2QueryExtention\n");
1358         goto fail_init;
1359      }
1360
1361    if (!DRI2QueryVersion(screenshot->dpy, &screenshot->dri2Major, &screenshot->dri2Minor))
1362      {
1363         fprintf(stderr, "[screenshot] fail: DRI2QueryVersion\n");
1364         goto fail_init;
1365      }
1366
1367    if (!DRI2Connect(screenshot->dpy, screenshot->root, &screenshot->driver_name, &screenshot->device_name))
1368      {
1369         fprintf(stderr, "[screenshot] fail: DRI2Connect\n");
1370         goto fail_init;
1371      }
1372
1373    screenshot->drm_fd = open(screenshot->device_name, O_RDWR);
1374    EINA_SAFETY_ON_FALSE_GOTO(screenshot->drm_fd >= 0, fail_init);
1375
1376    if (drmGetMagic(screenshot->drm_fd, &screenshot->magic))
1377      {
1378         fprintf(stderr, "[screenshot] fail: drmGetMagic\n");
1379         goto fail_init;
1380      }
1381
1382    if (!DRI2Authenticate(screenshot->dpy, screenshot->root, screenshot->magic))
1383      {
1384         fprintf(stderr, "[screenshot] fail: DRI2Authenticate\n");
1385         goto fail_init;
1386      }
1387
1388    if (!drmAuthMagic(screenshot->drm_fd, screenshot->magic))
1389      {
1390         fprintf(stderr, "[screenshot] fail: drmAuthMagic\n");
1391         goto fail_init;
1392      }
1393
1394    DRI2CreateDrawable(screenshot->dpy, screenshot->pixmap);
1395
1396    /* tbm bufmgr */
1397    screenshot->bufmgr = tbm_bufmgr_init(screenshot->drm_fd);
1398    EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
1399
1400    XFlush(screenshot->dpy);
1401
1402    g_screenshot = screenshot;
1403    set_last_result(EFL_UTIL_ERROR_NONE);
1404
1405    return g_screenshot;
1406 #endif
1407
1408 #if WAYLAND
1409    efl_util_screenshot_h screenshot = NULL;
1410
1411    if (!_eflutil.wl.shot.screenshooter)
1412      {
1413         int ret = 0;
1414         _wl_init();
1415         while (!_eflutil.wl.shot.screenshooter && ret != -1)
1416           ret = wl_display_dispatch(_eflutil.wl.dpy);
1417         EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.screenshooter, fail_init);
1418         EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.buffer_pool, fail_init);
1419      }
1420
1421    EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
1422    EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
1423
1424    if (g_screenshot)
1425      {
1426         if (g_screenshot->width != width || g_screenshot->height != height)
1427           {
1428              g_screenshot->width = width;
1429              g_screenshot->height = height;
1430           }
1431
1432         return g_screenshot;
1433      }
1434
1435    screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
1436    EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
1437
1438    screenshot->width = width;
1439    screenshot->height = height;
1440
1441    screenshot->bufmgr = tbm_bufmgr_init(-1);
1442    EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
1443
1444    g_screenshot = screenshot;
1445    set_last_result(EFL_UTIL_ERROR_NONE);
1446
1447    screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, &screenshot->shot_done);
1448
1449    return g_screenshot;
1450 #endif
1451 fail_param:
1452    if (screenshot)
1453      efl_util_screenshot_deinitialize(screenshot);
1454    set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1455    return NULL;
1456 fail_memory:
1457    if (screenshot)
1458      efl_util_screenshot_deinitialize(screenshot);
1459    set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY);
1460    return NULL;
1461 fail_init:
1462    if (screenshot)
1463      efl_util_screenshot_deinitialize(screenshot);
1464    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
1465    return NULL;
1466 }
1467
1468 API int efl_util_screenshot_deinitialize(efl_util_screenshot_h screenshot)
1469 {
1470 #if X11
1471    if (!screenshot)
1472      return EFL_UTIL_ERROR_INVALID_PARAMETER;
1473
1474    /* tbm bufmgr */
1475    if (screenshot->bufmgr)
1476      tbm_bufmgr_deinit(screenshot->bufmgr);
1477
1478    DRI2DestroyDrawable(screenshot->dpy, screenshot->pixmap);
1479
1480    /* dri2 */
1481    if (screenshot->drm_fd)
1482      close(screenshot->drm_fd);
1483    if (screenshot->driver_name)
1484      free(screenshot->driver_name);
1485    if (screenshot->device_name)
1486      free(screenshot->device_name);
1487
1488    /* xv */
1489    if (screenshot->port > 0 && screenshot->pixmap > 0)
1490      XvStopVideo(screenshot->dpy, screenshot->port, screenshot->pixmap);
1491
1492    /* damage */
1493    if (screenshot->damage)
1494      XDamageDestroy(screenshot->dpy, screenshot->damage);
1495
1496    /* gc */
1497    if (screenshot->gc)
1498      XFreeGC(screenshot->dpy, screenshot->gc);
1499
1500    /* pixmap */
1501    if (screenshot->pixmap > 0)
1502      XFreePixmap(screenshot->dpy, screenshot->pixmap);
1503
1504    /* port */
1505    if (screenshot->port > 0)
1506      XvUngrabPort(screenshot->dpy, screenshot->port, 0);
1507
1508    XSync(screenshot->dpy, False);
1509
1510    /* dpy */
1511    if (screenshot->internal_display ==1 && screenshot->dpy)
1512      XCloseDisplay(screenshot->dpy);
1513
1514    free(screenshot);
1515    g_screenshot = NULL;
1516
1517    return EFL_UTIL_ERROR_NONE;
1518 #endif
1519 #if WAYLAND
1520    if (!screenshot)
1521      return EFL_UTIL_ERROR_NONE;
1522
1523    if (screenshot->bufmgr)
1524      tbm_bufmgr_deinit(screenshot->bufmgr);
1525
1526    free(screenshot);
1527    g_screenshot = NULL;
1528
1529    if (_eflutil.wl.shot.screenshooter)
1530      screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, NULL);
1531
1532    return EFL_UTIL_ERROR_NONE;
1533 #endif
1534 }
1535
1536
1537 API tbm_surface_h efl_util_screenshot_take_tbm_surface(efl_util_screenshot_h screenshot)
1538 {
1539 #if X11
1540    XEvent ev = {0,};
1541    XErrorHandler old_handler = NULL;
1542    unsigned int attachment = DRI2BufferFrontLeft;
1543    int nbufs = 0;
1544    DRI2Buffer *bufs = NULL;
1545    tbm_bo t_bo = NULL;
1546    tbm_surface_h t_surface = NULL;
1547    int buf_width = 0;
1548    int buf_height = 0;
1549    tbm_surface_info_s surf_info;
1550    int i;
1551
1552    if (screenshot != g_screenshot)
1553      {
1554         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1555         return NULL;
1556      }
1557
1558    /* for flush other pending requests and pending events */
1559    XSync(screenshot->dpy, 0);
1560
1561    g_efl_util_x_error_caught = False;
1562    old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
1563
1564    /* dump here */
1565    XvPutStill(screenshot->dpy, screenshot->port, screenshot->pixmap, screenshot->gc,
1566               0, 0, screenshot->width, screenshot->height,
1567               0, 0, screenshot->width, screenshot->height);
1568
1569    XSync(screenshot->dpy, 0);
1570
1571    if (g_efl_util_x_error_caught)
1572      {
1573         g_efl_util_x_error_caught = False;
1574         XSetErrorHandler(old_handler);
1575         goto fail;
1576      }
1577
1578    g_efl_util_x_error_caught = False;
1579    XSetErrorHandler(old_handler);
1580
1581    if (XPending(screenshot->dpy))
1582      XNextEvent(screenshot->dpy, &ev);
1583    else
1584      {
1585         int fd = ConnectionNumber(screenshot->dpy);
1586         fd_set mask;
1587         struct timeval tv;
1588         int ret;
1589
1590         FD_ZERO(&mask);
1591         FD_SET(fd, &mask);
1592
1593         tv.tv_usec = 0;
1594         tv.tv_sec = TIMEOUT_CAPTURE;
1595
1596         ret = select(fd + 1, &mask, 0, 0, &tv);
1597         if (ret < 0)
1598           fprintf(stderr, "[screenshot] fail: select.\n");
1599         else if (ret == 0)
1600           fprintf(stderr, "[screenshot] fail: timeout(%d sec)!\n", TIMEOUT_CAPTURE);
1601         else if (XPending(screenshot->dpy))
1602           XNextEvent(screenshot->dpy, &ev);
1603         else
1604           fprintf(stderr, "[screenshot] fail: not passed a event!\n");
1605      }
1606
1607    /* check if the capture is done by xserver and pixmap has got the captured image */
1608    if (ev.type == (screenshot->damage_base + XDamageNotify))
1609      {
1610         XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
1611         if (damage_ev->drawable == screenshot->pixmap)
1612           {
1613              /* Get DRI2 FrontLeft buffer of the pixmap */
1614              bufs = DRI2GetBuffers(screenshot->dpy, screenshot->pixmap, &buf_width, &buf_height, &attachment, 1, &nbufs);
1615              if (!bufs)
1616                {
1617                   fprintf(stderr, "[screenshot] fail: DRI2GetBuffers\n");
1618                   goto fail;
1619                }
1620
1621              t_bo = tbm_bo_import(screenshot->bufmgr, bufs[0].name);
1622              if (!t_bo)
1623                {
1624                   fprintf(stderr, "[screenshot] fail: import tbm_bo!\n");
1625                   goto fail;
1626                }
1627
1628              surf_info.width = buf_width;
1629              surf_info.height = buf_height;
1630              surf_info.format = TBM_FORMAT_XRGB8888;
1631              surf_info.bpp = 32;
1632              surf_info.size = bufs->pitch * surf_info.height;
1633              surf_info.num_planes = 1;
1634              for (i = 0; i < surf_info.num_planes; i++)
1635                {
1636                   surf_info.planes[i].size = bufs->pitch * surf_info.height;
1637                   surf_info.planes[i].stride = bufs->pitch;
1638                   surf_info.planes[i].offset = 0;
1639                }
1640              t_surface = tbm_surface_internal_create_with_bos(&surf_info, &t_bo, 1);
1641              if (!t_surface)
1642                {
1643                   fprintf(stderr, "[screenshot] fail: get tbm_surface!\n");
1644                   goto fail;
1645                }
1646
1647              tbm_bo_unref(t_bo);
1648              free(bufs);
1649
1650              XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
1651
1652              set_last_result(EFL_UTIL_ERROR_NONE);
1653
1654              return t_surface;
1655           }
1656
1657         XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
1658      }
1659
1660 fail:
1661
1662    if (t_bo)
1663      tbm_bo_unref(t_bo);
1664    if (bufs)
1665      free(bufs);
1666
1667    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
1668
1669    return NULL;
1670 #endif
1671
1672 #if WAYLAND
1673    tbm_bo t_bo = NULL;
1674    tbm_surface_h t_surface = NULL;
1675    struct wl_buffer *buffer = NULL;
1676    tbm_surface_info_s info;
1677    Efl_Util_Wl_Output_Info *output;
1678    int ret = 0;
1679
1680    if (screenshot != g_screenshot)
1681      {
1682         set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
1683         return NULL;
1684      }
1685
1686    output = eina_list_nth(_eflutil.wl.shot.output_list, 0);
1687    if (!output)
1688      {
1689         fprintf(stderr, "[screenshot] fail: no output for screenshot\n");
1690         goto fail;
1691      }
1692
1693    t_surface = tbm_surface_create(screenshot->width, screenshot->height, TBM_FORMAT_XRGB8888);
1694    if (!t_surface)
1695      {
1696         fprintf(stderr, "[screenshot] fail: tbm_surface_create\n");
1697         goto fail;
1698      }
1699
1700    t_bo = tbm_surface_internal_get_bo(t_surface, 0);
1701    if (!t_bo)
1702      {
1703         fprintf(stderr, "[screenshot] fail: no tbm_bo for screenshot\n");
1704         goto fail;
1705      }
1706
1707    tbm_surface_get_info(t_surface, &info);
1708
1709    buffer =
1710      tizen_buffer_pool_create_buffer(_eflutil.wl.shot.buffer_pool,
1711                                      tbm_bo_export(t_bo),
1712                                      info.width, info.height,
1713                                      info.planes[0].stride,
1714                                      TIZEN_BUFFER_POOL_FORMAT_XRGB8888);
1715    if (!buffer)
1716      {
1717         fprintf(stderr, "[screenshot] fail: create wl_buffer for screenshot\n");
1718         goto fail;
1719      }
1720
1721    screenshooter_shoot(_eflutil.wl.shot.screenshooter, output->output, buffer);
1722
1723    screenshot->shot_done = EINA_FALSE;
1724    while (!screenshot->shot_done && ret != -1)
1725      ret = wl_display_dispatch(_eflutil.wl.dpy);
1726
1727    if (ret == -1)
1728      {
1729         fprintf(stderr, "[screenshot] fail: screenshooter_shoot\n");
1730         goto fail;
1731      }
1732
1733    wl_buffer_destroy(buffer);
1734
1735    return t_surface;
1736
1737 fail:
1738    if (t_surface)
1739      tbm_surface_destroy(t_surface);
1740    if (buffer);
1741      wl_buffer_destroy(buffer);
1742
1743    set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
1744
1745    return NULL;
1746 #endif
1747 }