tizen 2.4 release
[framework/uifw/libeom.git] / src / wayland / eom-wayland.c
1 /**************************************************************************
2
3 eom (external output manager)
4
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact:
8 SooChan Lim <sc1.lim@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include <config.h>
33 #include "eom.h"
34 #include "eom_internal.h"
35 #include "eom-log.h"
36 #include "eom-wayland.h"
37 #include "eom-private.h"
38 #include "eom-client-protocol.h"
39 #include "xdg-shell-client-protocol.h"
40 #include <Ecore_Wayland.h>
41
42 typedef struct _EomWaylandClientInfo {
43         /* wl */
44         struct wl_display *display;
45         struct wl_registry *registry;
46
47         struct wl_eom *eom;
48
49         /* eom wayland output list */
50         struct wl_list eom_wl_output_list;
51         int num_outputs;
52
53         notify_func func;
54 } EomWaylandClientInfo;
55
56 typedef struct _EomWaylandOutput {
57         eom_output_id id;
58         struct wl_output *output;
59
60         /* current output data */
61         int32_t x;
62         int32_t y;
63         int32_t physical_width;
64         int32_t physical_height;
65         enum wl_output_subpixel subpixel;
66         const char *make;
67         const char *model;
68         enum wl_output_transform transform;
69
70         uint32_t flags;
71         int32_t width;
72         int32_t height;
73         int32_t refresh;
74
75         int32_t factor;
76
77         /* current eom data */
78         enum wl_eom_type eom_type;
79         enum wl_eom_status eom_status;
80         enum wl_eom_mode eom_mode;
81         enum wl_eom_attribute eom_attribute;
82         enum wl_eom_attribute_state eom_attribute_state;
83
84         /* client info */
85         EomWaylandClientInfo *client_info;
86
87         struct wl_list link;
88 } EomWaylandOutput;
89
90 static EomWaylandClientInfo wl_client_info;
91 static int eom_wayland_init = 0;
92
93 static eom_output_type_e
94 _convert_to_eom_output_type(enum wl_eom_type eom_type)
95 {
96         eom_output_type_e output_type = EOM_OUTPUT_TYPE_UNKNOWN;
97         switch (eom_type) {
98         case WL_EOM_TYPE_NONE:
99                 output_type = EOM_OUTPUT_TYPE_UNKNOWN;
100                 break;
101         case WL_EOM_TYPE_VGA:
102                 output_type = EOM_OUTPUT_TYPE_VGA;
103                 break;
104         case WL_EOM_TYPE_DIVI:
105                 output_type = EOM_OUTPUT_TYPE_DVII;;
106                 break;
107         case WL_EOM_TYPE_DIVD:
108                 output_type = EOM_OUTPUT_TYPE_DVID;
109                 break;
110         case WL_EOM_TYPE_DIVA:
111                 output_type = EOM_OUTPUT_TYPE_DVIA;
112                 break;
113         case WL_EOM_TYPE_COMPOSITE:
114                 output_type = EOM_OUTPUT_TYPE_COMPOSITE;
115                 break;
116         case WL_EOM_TYPE_SVIDEO:
117                 output_type = EOM_OUTPUT_TYPE_SVIDEO;
118                 break;
119         case WL_EOM_TYPE_LVDS:
120                 output_type = EOM_OUTPUT_TYPE_LVDS;
121                 break;
122         case WL_EOM_TYPE_COMPONENT:
123                 output_type = EOM_OUTPUT_TYPE_COMPONENT;
124                 break;
125         case WL_EOM_TYPE_9PINDIN:
126                 output_type = EOM_OUTPUT_TYPE_9PINDIN;
127                 break;
128         case WL_EOM_TYPE_DISPLAYPORT:
129                 output_type = EOM_OUTPUT_TYPE_DISPLAYPORT;
130                 break;
131         case WL_EOM_TYPE_HDMIA:
132                 output_type = EOM_OUTPUT_TYPE_HDMIA;
133                 break;
134         case WL_EOM_TYPE_HDMIB:
135                 output_type = EOM_OUTPUT_TYPE_HDMIB;
136                 break;
137         case WL_EOM_TYPE_TV:
138                 output_type = EOM_OUTPUT_TYPE_TV;
139                 break;
140         case WL_EOM_TYPE_EDP:
141                 output_type = EOM_OUTPUT_TYPE_EDP;
142                 break;
143         case WL_EOM_TYPE_VIRTUAL:
144                 output_type = EOM_OUTPUT_TYPE_VIRTUAL;
145                 break;
146         case WL_EOM_TYPE_DSI:
147                 output_type = EOM_OUTPUT_TYPE_DSI;
148                 break;
149         default:
150                 ERR("no type.");
151                 break;
152         }
153
154         return output_type;
155 }
156
157 static eom_output_mode_e
158 _convert_to_eom_output_mode(enum wl_eom_mode eom_mode)
159 {
160         eom_output_mode_e output_mode = EOM_OUTPUT_MODE_NONE;
161         switch (eom_mode) {
162         case WL_EOM_MODE_NONE:
163                 output_mode = EOM_OUTPUT_MODE_NONE;
164                 break;
165         case WL_EOM_MODE_MIRROR:
166                 output_mode = EOM_OUTPUT_MODE_MIRROR;
167                 break;
168         case WL_EOM_MODE_PRESENTATION:
169                 output_mode = EOM_OUTPUT_MODE_PRESENTATION;
170                 break;
171         default:
172                 ERR("no mode.");
173                 break;
174         }
175
176         return output_mode;
177 }
178
179 static eom_output_attribute_e
180 _convert_to_eom_output_attribute(enum wl_eom_attribute eom_attribute)
181 {
182         eom_output_attribute_e output_attribute = EOM_OUTPUT_ATTRIBUTE_NONE;
183         switch (eom_attribute) {
184         case WL_EOM_ATTRIBUTE_NONE:
185                 output_attribute = EOM_OUTPUT_ATTRIBUTE_NONE;
186                 break;
187         case WL_EOM_ATTRIBUTE_NORMAL:
188                 output_attribute = EOM_OUTPUT_ATTRIBUTE_NORMAL;
189                 break;
190         case WL_EOM_ATTRIBUTE_EXCLUSIVE_SHARED:
191                 output_attribute = EOM_OUTPUT_ATTRIBUTE_EXCLUSIVE_SHARE;
192                 break;
193         case WL_EOM_ATTRIBUTE_EXCLUSIVE:
194                 output_attribute = EOM_OUTPUT_ATTRIBUTE_EXCLUSIVE;
195                 break;
196         default:
197                 ERR("no attribute.");
198                 break;
199         }
200
201         return output_attribute;
202 }
203
204 static eom_output_attribute_state_e
205 _convert_to_eom_output_attribute_state(enum wl_eom_attribute_state eom_attribute_state)
206 {
207         eom_output_attribute_state_e output_attribute_state = EOM_OUTPUT_ATTRIBUTE_STATE_NONE;
208         switch (eom_attribute_state) {
209         case WL_EOM_ATTRIBUTE_STATE_NONE:
210                 output_attribute_state = EOM_OUTPUT_ATTRIBUTE_STATE_NONE;
211                 break;
212         case WL_EOM_ATTRIBUTE_STATE_ACTIVE:
213                 output_attribute_state = EOM_OUTPUT_ATTRIBUTE_STATE_ACTIVE;
214                 break;
215         case WL_EOM_ATTRIBUTE_STATE_INACTIVE:
216                 output_attribute_state = EOM_OUTPUT_ATTRIBUTE_STATE_INACTIVE;
217                 break;
218         case WL_EOM_ATTRIBUTE_STATE_LOST:
219                 output_attribute_state = EOM_OUTPUT_ATTRIBUTE_STATE_LOST;
220                 break;
221         default:
222                 ERR("no attribute state.");
223                 break;
224         }
225
226         return output_attribute_state;
227 }
228
229 static enum wl_eom_attribute
230 _convert_to_wl_eom_attribute(eom_output_attribute_e attr)
231 {
232         enum wl_eom_attribute eom_attribute = WL_EOM_ATTRIBUTE_NONE;
233         switch (attr) {
234         case EOM_OUTPUT_ATTRIBUTE_NONE:
235                 eom_attribute = WL_EOM_ATTRIBUTE_NONE;
236                 break;
237         case EOM_OUTPUT_ATTRIBUTE_NORMAL:
238                 eom_attribute = WL_EOM_ATTRIBUTE_NORMAL;
239                 break;
240         case EOM_OUTPUT_ATTRIBUTE_EXCLUSIVE_SHARE:
241                 eom_attribute = WL_EOM_ATTRIBUTE_EXCLUSIVE_SHARED;
242                 break;
243         case EOM_OUTPUT_ATTRIBUTE_EXCLUSIVE:
244                 eom_attribute = WL_EOM_ATTRIBUTE_EXCLUSIVE;
245                 break;
246         default:
247                 ERR("no wl attribute.");
248                 break;
249         }
250
251         return eom_attribute;
252 }
253
254
255 static void
256 _eom_wayland_client_call_notify(EomWaylandOutput *eom_wl_output, eom_output_notify_type_e type)
257 {
258         GArray *array = NULL;
259         GValue v = G_VALUE_INIT;
260
261         array = g_array_new(FALSE, FALSE, sizeof(GValue));
262
263         /* 11 args 0: notify_type 1:output_id, 2:output_type, 3:output_mode, 4:w, 5:h, 6:w_mm, 7:h_mm, 8:pid, 9:attri, 10:state */
264         /* 0: notify_type */
265         g_value_init(&v, G_TYPE_INT);
266         g_value_set_int(&v, type);
267         array = g_array_append_val(array, v);
268         g_value_unset(&v);
269
270         /* 1:output_id */
271         g_value_init(&v, G_TYPE_INT);
272         g_value_set_int(&v, eom_wl_output->id);
273         array = g_array_append_val(array, v);
274         g_value_unset(&v);
275
276         /* 2:output_type */
277         g_value_init(&v, G_TYPE_INT);
278         g_value_set_int(&v, _convert_to_eom_output_type(eom_wl_output->eom_type));
279         array = g_array_append_val(array, v);
280         g_value_unset(&v);
281
282         /* 3:output_mode */
283         g_value_init(&v, G_TYPE_INT);
284         g_value_set_int(&v, _convert_to_eom_output_mode(eom_wl_output->eom_mode));
285         array = g_array_append_val(array, v);
286         g_value_unset(&v);
287
288         /* 4:w */
289         g_value_init(&v, G_TYPE_INT);
290         g_value_set_int(&v, eom_wl_output->width);
291         array = g_array_append_val(array, v);
292         g_value_unset(&v);
293
294         /* 5:h */
295         g_value_init(&v, G_TYPE_INT);
296         g_value_set_int(&v, eom_wl_output->height);
297         array = g_array_append_val(array, v);
298         g_value_unset(&v);
299
300         /* 6:w_mm */
301         g_value_init(&v, G_TYPE_INT);
302         g_value_set_int(&v, eom_wl_output->physical_width);
303         array = g_array_append_val(array, v);
304         g_value_unset(&v);
305
306         /* 7:h_mm */
307         g_value_init(&v, G_TYPE_INT);
308         g_value_set_int(&v, eom_wl_output->physical_height);
309         array = g_array_append_val(array, v);
310         g_value_unset(&v);
311
312         /* 8:pid */
313         g_value_init(&v, G_TYPE_INT);
314         g_value_set_int(&v, eom_wl_output->physical_width);
315         array = g_array_append_val(array, v);
316         g_value_unset(&v);
317
318         /* 9:attri */
319         g_value_init(&v, G_TYPE_INT);
320         g_value_set_int(&v, _convert_to_eom_output_attribute(eom_wl_output->eom_attribute));
321         array = g_array_append_val(array, v);
322         g_value_unset(&v);
323
324         /* 10:state */
325         g_value_init(&v, G_TYPE_INT);
326         g_value_set_int(&v, _convert_to_eom_output_attribute_state(eom_wl_output->eom_attribute_state));
327         array = g_array_append_val(array, v);
328         g_value_unset(&v);
329
330         if (eom_wl_output->client_info->func)
331                 eom_wl_output->client_info->func(NULL, array);
332
333         if (array)
334                 g_array_free(array, FALSE);
335
336 }
337
338
339 static EomWaylandOutput *
340 _eom_wayland_client_find_output_from_wl_output(struct wl_list *eom_wl_output_list, struct wl_output *output)
341 {
342         EomWaylandOutput *eom_wl_output = NULL;
343         EomWaylandOutput *tmp = NULL;
344         EomWaylandOutput *ret = NULL;
345
346         /* remove all eom_wl_outputs */
347         if (!wl_list_empty(eom_wl_output_list)) {
348                 wl_list_for_each_safe(eom_wl_output, tmp, eom_wl_output_list, link) {
349                         if (eom_wl_output->output == output) {
350                                 ret = eom_wl_output;
351                                 break;
352                         }
353                 }
354         }
355
356         return ret;
357 }
358
359 static EomWaylandOutput *
360 _eom_wayland_client_find_output_from_eom_output(struct wl_list *eom_wl_output_list, eom_output_id id)
361 {
362         EomWaylandOutput *eom_wl_output = NULL;
363         EomWaylandOutput *tmp = NULL;
364         EomWaylandOutput *ret = NULL;
365
366         /* remove all eom_wl_outputs */
367         if (!wl_list_empty(eom_wl_output_list)) {
368                 wl_list_for_each_safe(eom_wl_output, tmp, eom_wl_output_list, link) {
369                         if (eom_wl_output->id == id) {
370                                 ret = eom_wl_output;
371                                 break;
372                         }
373                 }
374         }
375
376         return ret;
377 }
378
379
380 static void
381 _eom_wl_output_handle_geometry(void *data,
382                         struct wl_output *wl_output,
383                         int32_t x,
384                         int32_t y,
385                         int32_t physical_width,
386                         int32_t physical_height,
387                         int32_t subpixel,
388                         const char *make,
389                         const char *model,
390                         int32_t transform)
391 {
392         EomWaylandOutput *eom_wl_output = (EomWaylandOutput *) data;
393
394         INFO("wl_output:%p x:%d y:%d phy_w:%d phy_h:%d subpixel:%d make:%s model:%s transform:%d\n",
395                 wl_output, x, y, physical_width, physical_height, subpixel, make, model, transform);
396
397         /* save vaules if it is different before */
398         if (eom_wl_output->x != x)
399                 eom_wl_output->x = x;
400         if (eom_wl_output->y != y)
401                 eom_wl_output->y = y;
402         if (eom_wl_output->physical_height)
403                 eom_wl_output->physical_height = physical_height;
404         if (eom_wl_output->physical_width)
405                 eom_wl_output->physical_width = physical_width;
406         if (eom_wl_output->subpixel)
407                 eom_wl_output->subpixel = subpixel;
408         if (eom_wl_output->transform)
409                 eom_wl_output->transform = transform;
410
411 }
412
413
414 static void
415 _eom_wl_output_handle_mode(void *data,
416                         struct wl_output *wl_output,
417                         uint32_t flags,
418                         int32_t width,
419                         int32_t height,
420                         int32_t refresh)
421 {
422         EomWaylandOutput *eom_wl_output = (EomWaylandOutput *) data;
423
424         INFO("wl_output:%p flags:%d width:%d height:%d refresh:%d\n",
425                 wl_output, flags, width, height, refresh);
426
427         /* save vaules if it is different before */
428         if (eom_wl_output->flags != flags)
429                 eom_wl_output->flags = flags;
430         if (eom_wl_output->width != width)
431                 eom_wl_output->width = width;
432         if (eom_wl_output->height != height)
433                 eom_wl_output->height = height;
434         if (eom_wl_output->refresh != refresh)
435                 eom_wl_output->refresh = refresh;
436 }
437
438 static void
439 _eom_wl_output_handle_done(void *data,
440                         struct wl_output *wl_output)
441 {
442         INFO("wl_output:%p\n", wl_output);
443 }
444
445 static void
446 _eom_wl_output_handle_scale(void *data,
447                         struct wl_output *wl_output,
448                         int32_t factor)
449 {
450         EomWaylandOutput *eom_wl_output = (EomWaylandOutput *) data;
451
452         INFO("wl_output:%p factor:%d\n", wl_output, factor);
453
454         /* save vaules if it is different before */
455         if (eom_wl_output->factor != factor)
456                 eom_wl_output->factor = factor;
457 }
458
459 static const struct wl_output_listener eom_wl_output_listener = {
460         _eom_wl_output_handle_geometry,
461         _eom_wl_output_handle_mode,
462         _eom_wl_output_handle_done,
463         _eom_wl_output_handle_scale,
464 };
465
466 static void
467 _eom_wl_eom_output_type(void *data,
468                         struct wl_eom *wl_eom,
469                         struct wl_output *output,
470                         uint32_t type,
471                         uint32_t status)
472 {
473         EomWaylandClientInfo *eom_client_info = (EomWaylandClientInfo *) data;
474         EomWaylandOutput *eom_wl_output = NULL;
475
476         eom_wl_output = _eom_wayland_client_find_output_from_wl_output(&eom_client_info->eom_wl_output_list, output);
477         RET_IF_FAIL(eom_wl_output != NULL);
478
479         /* save the output type */
480         if (eom_wl_output->eom_type != type)
481                 eom_wl_output->eom_type = type;
482
483         /* check the connection status and call the notify */
484         if (eom_wl_output->eom_status != status) {
485                 eom_wl_output->eom_status = status;
486
487                 if (status == WL_EOM_STATUS_CONNECTION)
488                         _eom_wayland_client_call_notify(eom_wl_output, EOM_OUTPUT_NOTIFY_ADD);
489                 else if (status == WL_EOM_STATUS_DISCONNECTION)
490                         _eom_wayland_client_call_notify(eom_wl_output, EOM_OUTPUT_NOTIFY_REMOVE);
491         }
492 }
493
494 static void
495 _eom_wl_eom_output_mode(void *data,
496                         struct wl_eom *wl_eom,
497                         struct wl_output *output,
498                         uint32_t mode)
499 {
500         EomWaylandClientInfo *eom_client_info = (EomWaylandClientInfo *) data;
501         EomWaylandOutput *eom_wl_output = NULL;
502
503         eom_wl_output = _eom_wayland_client_find_output_from_wl_output(&eom_client_info->eom_wl_output_list, output);
504         RET_IF_FAIL(eom_wl_output != NULL);
505
506         /* check the eom mode and call the notify */
507         if (eom_wl_output->eom_mode != mode) {
508                 eom_wl_output->eom_mode = mode;
509
510                 _eom_wayland_client_call_notify(eom_wl_output, EOM_OUTPUT_NOTIFY_MODE_CHANGED);
511         }
512 }
513
514 static void
515 _eom_wl_eom_output_attribute(void *data,
516                          struct wl_eom *wl_eom,
517                          struct wl_output *output,
518                          uint32_t attribute,
519                          uint32_t attribute_state,
520                          uint32_t error)
521 {
522         EomWaylandClientInfo *eom_client_info = (EomWaylandClientInfo *) data;
523         EomWaylandOutput *eom_wl_output = NULL;
524
525         eom_wl_output = _eom_wayland_client_find_output_from_wl_output(&eom_client_info->eom_wl_output_list, output);
526         RET_IF_FAIL(eom_wl_output != NULL);
527
528         /* check the eom attribute and call the notify */
529         if (eom_wl_output->eom_attribute != attribute || eom_wl_output->eom_attribute_state != attribute_state) {
530                 eom_wl_output->eom_attribute = attribute;
531                 eom_wl_output->eom_attribute_state = attribute_state;
532
533                 _eom_wayland_client_call_notify(eom_wl_output, EOM_OUTPUT_NOTIFY_ATTRIBUTE_CHANGED);
534         }
535 }
536
537
538 static const struct wl_eom_listener eom_wl_eom_listener = {
539         _eom_wl_eom_output_type,
540         _eom_wl_eom_output_mode,
541         _eom_wl_eom_output_attribute,
542 };
543
544
545 static void
546 _eom_wl_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
547 {
548         EomWaylandClientInfo *ci = (EomWaylandClientInfo *)data;
549         EomWaylandOutput *eom_wl_output = NULL;
550         struct wl_output *output = NULL;
551         struct wl_eom *eom = NULL;
552
553         if (strcmp(interface, "wl_output") == 0) {
554                 output = wl_registry_bind(registry, name, &wl_output_interface, 1);
555                 if (!output)
556                         ERR("Error. fail to bind  %s.\n", interface);
557                 else {
558                         INFO("bind %s.\n", interface);
559
560                         /* create the eom_wl_output */
561                         eom_wl_output = calloc(1, sizeof(EomWaylandOutput));
562                         if (!eom_wl_output) {
563                                 ERR("error. fail to allocate the eom_output.\n");
564                                 return;
565                         }
566                         ci->num_outputs++;
567                         eom_wl_output->id = ci->num_outputs;
568                         eom_wl_output->output = output;
569                         wl_list_insert(&ci->eom_wl_output_list, &eom_wl_output->link);
570
571                         /* add listener */
572                         wl_output_add_listener(eom_wl_output->output, &eom_wl_output_listener, eom_wl_output);
573                 }
574         } else if (strcmp(interface, "wl_eom") == 0) {
575                 eom = wl_registry_bind(registry, name, &wl_eom_interface, 1);
576                 if (!eom)
577                         ERR("Error. fail to bind  %s.\n", interface);
578                 else {
579                         INFO("bind %s.\n", interface);
580
581                         ci->eom = eom;
582
583                         /* add listener */
584                         wl_eom_add_listener(ci->eom, &eom_wl_eom_listener, ci);
585                 }
586         } else
587                 INFO("Not bind %s.\n", interface);
588 }
589
590 static void
591 _eom_wl_registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
592 {
593
594 }
595
596 static const struct wl_registry_listener eom_registry_listener = {
597         _eom_wl_registry_handle_global,
598         _eom_wl_registry_handle_global_remove
599 };
600
601 static bool
602 _eom_wayland_client_initialize()
603 {
604         int ecore_count = -1;
605
606         ecore_count = ecore_wl_init(NULL);
607         GOTO_IF_FAIL(ecore_count > 0, fail);
608
609         wl_list_init(&wl_client_info.eom_wl_output_list);
610
611         wl_client_info.display = ecore_wl_display_get();
612         GOTO_IF_FAIL(wl_client_info.display != NULL, fail);
613
614         /* get the registry */
615         wl_client_info.registry = wl_display_get_registry(wl_client_info.display);
616         GOTO_IF_FAIL(wl_client_info.registry != NULL, fail);
617
618         /* get the global objects */
619         wl_registry_add_listener(wl_client_info.registry, &eom_registry_listener, &wl_client_info);
620         wl_display_dispatch(wl_client_info.display);
621         wl_display_roundtrip(wl_client_info.display);
622
623         /* remove type none eom_wl_outputs */
624         if (!wl_list_empty(&wl_client_info.eom_wl_output_list)) {
625                 EomWaylandOutput *eom_wl_output = NULL;
626                 EomWaylandOutput *tmp = NULL;
627
628                 wl_list_for_each_safe(eom_wl_output, tmp, &wl_client_info.eom_wl_output_list, link) {
629                         if (eom_wl_output->eom_type == WL_EOM_TYPE_NONE) {
630                                 WARN("[EOM_CLIENT] eom_type is NONE. remove.\n");
631                                 wl_output_destroy(eom_wl_output->output);
632                                 wl_list_remove(&eom_wl_output->link);
633                                 free(eom_wl_output);
634                                 eom_wl_output = NULL;
635                         }
636                 }
637         }
638
639         /* output list */
640         if (wl_list_empty(&wl_client_info.eom_wl_output_list))
641                 WARN("[EOM_CLIENT] no wl output at this device.\n");
642
643         INFO("[EOM_CLIENT] wayland client init.");
644
645         return true;
646 fail:
647         return false;
648 }
649
650 static void
651 _eom_wayland_client_deinitialize()
652 {
653         EomWaylandOutput *eom_wl_output = NULL;
654         EomWaylandOutput *tmp = NULL;
655
656         /* remove all eom_wl_outputs */
657         if (!wl_list_empty(&wl_client_info.eom_wl_output_list)) {
658                 wl_list_for_each_safe(eom_wl_output, tmp, &wl_client_info.eom_wl_output_list, link) {
659                         if (eom_wl_output->output)
660                                 wl_output_destroy(eom_wl_output->output);
661                         free(eom_wl_output);
662                         eom_wl_output = NULL;
663                 }
664         }
665
666         ecore_wl_shutdown();
667
668         INFO("[EOM_CLIENT] wayland client deinit.");
669 }
670
671 bool
672 eom_wayland_client_init(notify_func func)
673 {
674         bool ret = false;
675
676         if (eom_wayland_init) return true;
677
678         ret = _eom_wayland_client_initialize();
679         GOTO_IF_FAIL(ret != false, fail);
680
681         wl_client_info.func = func;
682
683         eom_wayland_init = 1;
684
685         return ret;
686 fail:
687         return false;
688 }
689
690 void
691 eom_wayland_client_deinit(GList *cb_info_list)
692 {
693         if (!eom_wayland_init)
694                 return;
695
696         _eom_wayland_client_deinitialize();
697
698         eom_wayland_init = 0;
699
700         memset(&wl_client_info, 0x0, sizeof(EomWaylandClientInfo));
701 }
702
703 GArray *
704 eom_wayland_client_get_output_ids(void)
705 {
706         GArray *array = NULL;
707         GValue v = G_VALUE_INIT;
708         EomWaylandOutput *eom_wl_output = NULL;
709         EomWaylandOutput *tmp = NULL;
710
711         if (wl_list_empty(&wl_client_info.eom_wl_output_list)) {
712                 ERR("error. no outputs.\n");
713                 return NULL;
714         }
715
716         array = g_array_new(FALSE, FALSE, sizeof(GValue));
717
718         /* remove all eom_wl_outputs */
719         wl_list_for_each_safe(eom_wl_output, tmp, &wl_client_info.eom_wl_output_list, link) {
720                 if (eom_wl_output->output) {
721                         g_value_init(&v, G_TYPE_INT);
722                         g_value_set_int(&v, eom_wl_output->id);
723                         array = g_array_append_val(array, v);
724                         g_value_unset(&v);
725                 }
726         }
727
728         /* returned array will be freed by caller */
729         return array;
730 }
731
732 GArray *
733 eom_wayland_client_get_output_info(eom_output_id output_id)
734 {
735         GArray *array = NULL;
736         GValue v = G_VALUE_INIT;
737         EomWaylandOutput *eom_wl_output = NULL;
738
739         eom_wl_output = _eom_wayland_client_find_output_from_eom_output(&wl_client_info.eom_wl_output_list, output_id);
740         RETV_IF_FAIL(eom_wl_output != NULL, NULL);
741
742         array = g_array_new(FALSE, FALSE, sizeof(GValue));
743
744         /* 0:output_id, 1:output_type, 2:output_mode, 3:w, 4:h, 5:w_mm, 6:h_mm */
745         /* 0:output_id */
746         g_value_init(&v, G_TYPE_INT);
747         g_value_set_int(&v, eom_wl_output->id);
748         array = g_array_append_val(array, v);
749         g_value_unset(&v);
750
751         /* 1:output_type */
752         g_value_init(&v, G_TYPE_INT);
753         g_value_set_int(&v, eom_wl_output->eom_type);
754         array = g_array_append_val(array, v);
755         g_value_unset(&v);
756
757         /* 2:output_mode */
758         g_value_init(&v, G_TYPE_INT);
759         g_value_set_int(&v, eom_wl_output->eom_mode);
760         array = g_array_append_val(array, v);
761         g_value_unset(&v);
762
763         /* 3:w */
764         g_value_init(&v, G_TYPE_INT);
765         g_value_set_int(&v, eom_wl_output->width);
766         array = g_array_append_val(array, v);
767         g_value_unset(&v);
768
769         /* 4:h */
770         g_value_init(&v, G_TYPE_INT);
771         g_value_set_int(&v, eom_wl_output->height);
772         array = g_array_append_val(array, v);
773         g_value_unset(&v);
774
775         /* 5:w_mm */
776         g_value_init(&v, G_TYPE_INT);
777         g_value_set_int(&v, eom_wl_output->physical_width);
778         array = g_array_append_val(array, v);
779         g_value_unset(&v);
780
781         /* 6:h_mm */
782         g_value_init(&v, G_TYPE_INT);
783         g_value_set_int(&v, eom_wl_output->physical_height);
784         array = g_array_append_val(array, v);
785         g_value_unset(&v);
786
787         /* returned array will be freed by caller */
788         return array;
789 }
790
791 GArray *
792 eom_wayland_client_set_attribute(eom_output_id output_id, eom_output_attribute_e attr)
793 {
794         GArray *array = NULL;
795         GValue v = G_VALUE_INIT;
796         EomWaylandOutput *eom_wl_output = NULL;
797         int ret = 0;
798
799         eom_wl_output = _eom_wayland_client_find_output_from_eom_output(&wl_client_info.eom_wl_output_list, output_id);
800         GOTO_IF_FAIL(eom_wl_output != NULL, fail);
801
802         wl_eom_set_attribute(wl_client_info.eom, eom_wl_output->output, _convert_to_wl_eom_attribute(attr));
803
804         /* TODO: wait for the result of set_attribute. this should be the blocking call. */
805         wl_display_dispatch(wl_client_info.display);
806         wl_display_roundtrip(wl_client_info.display);
807
808         ret = 1;
809
810         array = g_array_new(FALSE, FALSE, sizeof(GValue));
811         g_value_init(&v, G_TYPE_INT);
812         g_value_set_int(&v, ret);
813         array = g_array_append_val(array, v);
814         g_value_unset(&v);
815
816         /* returned array will be freed by caller */
817         return array;
818 fail:
819
820         return NULL;
821 }
822
823 GArray *
824 eom_wayland_client_set_window(eom_output_id output_id, Evas_Object *win)
825 {
826         GArray *array = NULL;
827         GValue v = G_VALUE_INIT;
828         Ecore_Wl_Window *e_wl_win = NULL;
829         EomWaylandOutput *eom_wl_output = NULL;
830         struct wl_shell_surface *shell_surface = NULL;
831         struct xdg_surface *xdg_shell_surface = NULL;
832         int ret = 0;
833
834         e_wl_win = elm_win_wl_window_get(win);
835         GOTO_IF_FAIL(e_wl_win != NULL, fail);
836
837         eom_wl_output = _eom_wayland_client_find_output_from_eom_output(&wl_client_info.eom_wl_output_list, output_id);
838         GOTO_IF_FAIL(eom_wl_output != NULL, fail);
839
840         /* set full screen at output */
841         xdg_shell_surface = ecore_wl_window_xdg_surface_get(e_wl_win);
842         if (xdg_shell_surface) {
843                 xdg_surface_set_fullscreen(xdg_shell_surface, eom_wl_output->output);
844         } else {
845                 shell_surface = ecore_wl_window_shell_surface_get(e_wl_win);
846                 if (shell_surface) {
847                         wl_shell_surface_set_fullscreen(shell_surface,
848                                                                                   WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
849                                                                                   0, eom_wl_output->output);
850                 } else {
851                         ERR("no wl surface.\n");
852                         goto fail;
853                 }
854         }
855
856         ret = 1;
857
858         array = g_array_new(FALSE, FALSE, sizeof(GValue));
859         g_value_init(&v, G_TYPE_INT);
860         g_value_set_int(&v, ret);
861         array = g_array_append_val(array, v);
862         g_value_unset(&v);
863
864         /* returned array will be freed by caller */
865         return array;
866 fail:
867
868         return NULL;
869 }
870