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