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