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