• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright (C) 2013 DENSO CORPORATION
4  * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <memory.h>
23 #include <errno.h>
24 #include <signal.h>
25 #include <stdbool.h>
26 
27 #include <unistd.h>
28 #include <poll.h>
29 
30 #include <sys/mman.h>
31 #include <sys/eventfd.h>
32 
33 #include "writepng.h"
34 #include "bitmap.h"
35 #include "ilm_common.h"
36 #include "ilm_control_platform.h"
37 #include "wayland-util.h"
38 #include "ivi-wm-client-protocol.h"
39 #include "ivi-input-client-protocol.h"
40 
41 // #define USE_DUMMY_SCREEN
42 
43 struct layer_context {
44     struct wl_list link;
45 
46     t_ilm_uint id_layer;
47 
48     struct ilmLayerProperties prop;
49     layerNotificationFunc notification;
50 
51     struct wl_array render_order;
52 
53     struct wayland_context *ctx;
54 };
55 
56 struct screen_context {
57     struct wl_list link;
58 
59     struct wl_output *output;
60     struct ivi_wm_screen *controller;
61     t_ilm_uint id_screen;
62     t_ilm_uint name;
63     int32_t transform;
64 
65     struct ilmScreenProperties prop;
66 
67     struct wl_array render_order;
68 
69     struct wayland_context *ctx;
70 };
71 
72 struct screenshot_context {
73     const char *filename;
74     ilmErrorTypes result;
75     shotdoneNotificationFunc done_cb;
76 };
77 
78 struct screenshot_buffer_context {
79     bool isshotdone;
80     ilmErrorTypes result;
81     shotdoneNotificationFunc done_cb;
82 };
83 
84 
lock_context(struct ilm_control_context * ctx)85 static inline void lock_context(struct ilm_control_context *ctx)
86 {
87    pthread_mutex_lock(&ctx->mutex);
88 }
89 
unlock_context(struct ilm_control_context * ctx)90 static inline void unlock_context(struct ilm_control_context *ctx)
91 {
92    pthread_mutex_unlock(&ctx->mutex);
93 }
94 
95 static int init_control(void);
96 
97 static struct surface_context* get_surface_context(struct wayland_context *, uint32_t);
98 
99 void release_instance(void);
100 
101 static int32_t
wayland_controller_is_inside_layer_list(struct wl_list * list,uint32_t id_layer)102 wayland_controller_is_inside_layer_list(struct wl_list *list,
103                                         uint32_t id_layer)
104 {
105     struct layer_context *ctx_layer = NULL;
106     wl_list_for_each(ctx_layer, list, link) {
107         if (ctx_layer->id_layer == id_layer) {
108             return 1;
109         }
110     }
111 
112     return 0;
113 }
114 
115 static struct layer_context*
wayland_controller_get_layer_context(struct wayland_context * ctx,uint32_t id_layer)116 wayland_controller_get_layer_context(struct wayland_context *ctx,
117                                      uint32_t id_layer)
118 {
119     struct layer_context *ctx_layer = NULL;
120 
121     if (ctx->controller == NULL) {
122         fprintf(stderr, "controller is not initialized in ilmControl\n");
123         return NULL;
124     }
125 
126     wl_list_for_each(ctx_layer, &ctx->list_layer, link) {
127         if (ctx_layer->id_layer == id_layer) {
128             return ctx_layer;
129         }
130     }
131 
132     return NULL;
133 }
134 
135 static void
output_listener_geometry(void * data,struct wl_output * output,int32_t x,int32_t y,int32_t physical_width,int32_t physical_height,int32_t subpixel,const char * make,const char * model,int32_t transform)136 output_listener_geometry(void *data,
137                          struct wl_output *output,
138                          int32_t x,
139                          int32_t y,
140                          int32_t physical_width,
141                          int32_t physical_height,
142                          int32_t subpixel,
143                          const char *make,
144                          const char *model,
145                          int32_t transform)
146 {
147     (void)output;
148     (void)x;
149     (void)y;
150     (void)subpixel;
151     (void)make;
152     (void)model;
153 
154     struct screen_context *ctx_scrn = data;
155     ctx_scrn->transform = transform;
156 }
157 
158 static void
output_listener_mode(void * data,struct wl_output * output,uint32_t flags,int32_t width,int32_t height,int32_t refresh)159 output_listener_mode(void *data,
160                      struct wl_output *output,
161                      uint32_t flags,
162                      int32_t width,
163                      int32_t height,
164                      int32_t refresh)
165 {
166     (void)output;
167     (void)refresh;
168 
169     if (flags & WL_OUTPUT_MODE_CURRENT)
170     {
171         struct screen_context *ctx_scrn = data;
172         if (ctx_scrn->transform == WL_OUTPUT_TRANSFORM_90 ||
173             ctx_scrn->transform == WL_OUTPUT_TRANSFORM_270 ||
174             ctx_scrn->transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 ||
175             ctx_scrn->transform == WL_OUTPUT_TRANSFORM_FLIPPED_270) {
176             ctx_scrn->prop.screenWidth = height;
177             ctx_scrn->prop.screenHeight = width;
178         } else {
179             ctx_scrn->prop.screenWidth = width;
180             ctx_scrn->prop.screenHeight = height;
181         }
182     }
183 }
184 
185 static void
output_listener_done(void * data,struct wl_output * output)186 output_listener_done(void *data,
187                      struct wl_output *output)
188 {
189     (void)data;
190     (void)output;
191 }
192 
193 static void
output_listener_scale(void * data,struct wl_output * output,int32_t factor)194 output_listener_scale(void *data,
195                       struct wl_output *output,
196                       int32_t factor)
197 {
198     (void)data;
199     (void)output;
200     (void)factor;
201 }
202 
203 static struct wl_output_listener output_listener = {
204     output_listener_geometry,
205     output_listener_mode,
206     output_listener_done,
207     output_listener_scale
208 };
209 
210 static void
wm_listener_layer_visibility(void * data,struct ivi_wm * controller,uint32_t layer_id,int32_t visibility)211 wm_listener_layer_visibility(void *data, struct ivi_wm *controller,
212                              uint32_t layer_id, int32_t visibility)
213 {
214     struct wayland_context *ctx = data;
215     struct layer_context *ctx_layer;
216 
217     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
218     if(!ctx_layer)
219         return;
220 
221     if (ctx_layer->prop.visibility == (t_ilm_bool)visibility)
222         return;
223 
224     ctx_layer->prop.visibility = (t_ilm_bool)visibility;
225 
226     if (ctx_layer->notification != NULL) {
227         ctx_layer->notification(ctx_layer->id_layer,
228                                 &ctx_layer->prop,
229                                 ILM_NOTIFICATION_VISIBILITY);
230     }
231 }
232 
233 static void
wm_listener_layer_opacity(void * data,struct ivi_wm * controller,uint32_t layer_id,wl_fixed_t opacity)234 wm_listener_layer_opacity(void *data, struct ivi_wm *controller,
235                           uint32_t layer_id, wl_fixed_t opacity)
236 {
237     struct wayland_context *ctx = data;
238     struct layer_context *ctx_layer;
239 
240     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
241     if(!ctx_layer)
242         return;
243 
244     if (ctx_layer->prop.opacity == (t_ilm_float)wl_fixed_to_double(opacity))
245         return;
246 
247     ctx_layer->prop.opacity = (t_ilm_float)wl_fixed_to_double(opacity);
248 
249     if (ctx_layer->notification != NULL) {
250         ctx_layer->notification(ctx_layer->id_layer,
251                                 &ctx_layer->prop,
252                                 ILM_NOTIFICATION_OPACITY);
253     }
254 }
255 
256 static void
wm_listener_layer_source_rectangle(void * data,struct ivi_wm * controller,uint32_t layer_id,int32_t x,int32_t y,int32_t width,int32_t height)257 wm_listener_layer_source_rectangle(void *data, struct ivi_wm *controller,
258                                    uint32_t layer_id, int32_t x, int32_t y,
259                                    int32_t width, int32_t height)
260 {
261     struct wayland_context *ctx = data;
262     struct layer_context *ctx_layer;
263 
264     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
265     if(!ctx_layer)
266         return;
267 
268     if ((ctx_layer->prop.sourceX == (t_ilm_uint)x) &&
269         (ctx_layer->prop.sourceY == (t_ilm_uint)y) &&
270         (ctx_layer->prop.sourceWidth == (t_ilm_uint)width &&
271         (ctx_layer->prop.sourceHeight == (t_ilm_uint)height)))
272         return;
273 
274     ctx_layer->prop.sourceX = (t_ilm_uint)x;
275     ctx_layer->prop.sourceY = (t_ilm_uint)y;
276     ctx_layer->prop.sourceWidth = (t_ilm_uint)width;
277     ctx_layer->prop.sourceHeight = (t_ilm_uint)height;
278 
279     if (ctx_layer->notification != NULL) {
280         ctx_layer->notification(ctx_layer->id_layer,
281                                 &ctx_layer->prop,
282                                 ILM_NOTIFICATION_SOURCE_RECT);
283     }
284 }
285 
286 static void
wm_listener_layer_destination_rectangle(void * data,struct ivi_wm * controller,uint32_t layer_id,int32_t x,int32_t y,int32_t width,int32_t height)287 wm_listener_layer_destination_rectangle(void *data, struct ivi_wm *controller,
288                                         uint32_t layer_id, int32_t x, int32_t y,
289                                         int32_t width, int32_t height)
290 {
291     struct wayland_context *ctx = data;
292     struct layer_context *ctx_layer;
293 
294     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
295     if(!ctx_layer)
296         return;
297 
298     if ((ctx_layer->prop.destX == (t_ilm_uint)x) &&
299         (ctx_layer->prop.destY == (t_ilm_uint)y) &&
300         (ctx_layer->prop.destWidth == (t_ilm_uint)width &&
301         (ctx_layer->prop.destHeight == (t_ilm_uint)height)))
302         return;
303 
304     ctx_layer->prop.destX = (t_ilm_uint)x;
305     ctx_layer->prop.destY = (t_ilm_uint)y;
306     ctx_layer->prop.destWidth = (t_ilm_uint)width;
307     ctx_layer->prop.destHeight = (t_ilm_uint)height;
308 
309     if (ctx_layer->notification != NULL) {
310         ctx_layer->notification(ctx_layer->id_layer,
311                                 &ctx_layer->prop,
312                                 ILM_NOTIFICATION_DEST_RECT);
313     }
314 }
315 
316 static void
wm_listener_layer_created(void * data,struct ivi_wm * controller,uint32_t layer_id)317 wm_listener_layer_created(void *data, struct ivi_wm *controller, uint32_t layer_id)
318 {
319     struct wayland_context *ctx = data;
320     struct layer_context *ctx_layer;
321 
322     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
323     if(ctx_layer)
324         return;
325 
326     ctx_layer = calloc(1, sizeof *ctx_layer);
327     if (!ctx_layer) {
328         fprintf(stderr, "Failed to allocate memory for layer_context\n");
329         return;
330     }
331 
332     ctx_layer->id_layer = layer_id;
333     ctx_layer->ctx = ctx;
334 
335     wl_list_insert(&ctx->list_layer, &ctx_layer->link);
336 
337     if (ctx->notification != NULL) {
338        ilmObjectType layer = ILM_LAYER;
339        ctx->notification(layer, ctx_layer->id_layer, ILM_TRUE,
340                          ctx->notification_user_data);
341     }
342 }
343 
344 static void
wm_listener_layer_destroyed(void * data,struct ivi_wm * controller,uint32_t layer_id)345 wm_listener_layer_destroyed(void *data, struct ivi_wm *controller, uint32_t layer_id)
346 {
347     struct wayland_context *ctx = data;
348     struct layer_context *ctx_layer;
349 
350     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
351     if(!ctx_layer)
352         return;
353 
354     wl_list_remove(&ctx_layer->link);
355 
356     if (ctx_layer->ctx->notification != NULL) {
357         ilmObjectType layer = ILM_LAYER;
358         ctx_layer->ctx->notification(layer, ctx_layer->id_layer, ILM_FALSE,
359                                      ctx_layer->ctx->notification_user_data);
360     }
361 
362     free(ctx_layer);
363 }
364 
365 static void
wm_listener_layer_surface_added(void * data,struct ivi_wm * controller,uint32_t layer_id,uint32_t surface_id)366 wm_listener_layer_surface_added(void *data, struct ivi_wm *controller,
367                                 uint32_t layer_id, uint32_t surface_id)
368 {
369     struct wayland_context *ctx = data;
370     struct layer_context *ctx_layer;
371     (void)controller;
372 
373     ctx_layer = wayland_controller_get_layer_context(ctx, layer_id);
374     if(!ctx_layer)
375         return;
376 
377     uint32_t *add_id = wl_array_add(&ctx_layer->render_order, sizeof(*add_id));
378     *add_id = surface_id;
379 }
380 
381 static void
wm_listener_layer_error(void * data,struct ivi_wm * controller,uint32_t object_id,uint32_t code,const char * message)382 wm_listener_layer_error(void *data, struct ivi_wm *controller, uint32_t object_id,
383                         uint32_t code, const char *message)
384 {
385     struct wayland_context *ctx = data;
386     ilmErrorTypes error_code;
387 
388     switch (code) {
389     case IVI_WM_LAYER_ERROR_NO_SURFACE:
390         error_code = ILM_ERROR_RESOURCE_NOT_FOUND;
391         fprintf(stderr, "The surface with id: %d does not exist\n", object_id);
392         break;
393     case IVI_WM_LAYER_ERROR_NO_LAYER:
394         error_code = ILM_ERROR_RESOURCE_NOT_FOUND;
395         fprintf(stderr, "The layer with id: %d does not exist\n", object_id);
396         break;
397     case IVI_WM_LAYER_ERROR_BAD_PARAM:
398         error_code = ILM_ERROR_INVALID_ARGUMENTS;
399         fprintf(stderr, "The layer with id: %d is used with invalid parameter\n",
400                 object_id);
401         break;
402     default:
403         error_code = ILM_ERROR_ON_CONNECTION;
404     }
405 
406     fprintf(stderr, "%s", message);
407     fprintf(stderr, "\n");
408 
409     /*Do not override old error message*/
410     if (ctx->error_flag == ILM_SUCCESS)
411         ctx->error_flag = error_code;
412 }
413 
414 static void
wm_listener_surface_visibility(void * data,struct ivi_wm * controller,uint32_t surface_id,int32_t visibility)415 wm_listener_surface_visibility(void *data, struct ivi_wm *controller,
416                                uint32_t surface_id, int32_t visibility)
417 {
418     struct wayland_context *ctx = data;
419     struct surface_context *ctx_surf;
420 
421     ctx_surf = get_surface_context(ctx, surface_id);
422     if(!ctx_surf)
423         return;
424 
425     if (ctx_surf->prop.visibility == (t_ilm_bool)visibility)
426         return;
427 
428     ctx_surf->prop.visibility = (t_ilm_bool)visibility;
429 
430     if (ctx_surf->notification != NULL) {
431         ctx_surf->notification(ctx_surf->id_surface,
432                                 &ctx_surf->prop,
433                                 ILM_NOTIFICATION_VISIBILITY);
434     }
435 }
436 
437 static void
wm_listener_surface_opacity(void * data,struct ivi_wm * controller,uint32_t surface_id,wl_fixed_t opacity)438 wm_listener_surface_opacity(void *data, struct ivi_wm *controller,
439                             uint32_t surface_id, wl_fixed_t opacity)
440 {
441     struct wayland_context *ctx = data;
442     struct surface_context *ctx_surf;
443 
444     ctx_surf = get_surface_context(ctx, surface_id);
445     if(!ctx_surf)
446         return;
447 
448     if (ctx_surf->prop.opacity == (t_ilm_float)wl_fixed_to_double(opacity))
449         return;
450 
451     ctx_surf->prop.opacity = (t_ilm_float)wl_fixed_to_double(opacity);
452 
453     if (ctx_surf->notification != NULL) {
454         ctx_surf->notification(ctx_surf->id_surface,
455                                 &ctx_surf->prop,
456                                 ILM_NOTIFICATION_OPACITY);
457     }
458 }
459 
460 static void
wm_listener_surface_size(void * data,struct ivi_wm * controller,uint32_t surface_id,int32_t width,int32_t height)461 wm_listener_surface_size(void *data, struct ivi_wm *controller,
462                          uint32_t surface_id, int32_t width, int32_t height)
463 {
464     struct wayland_context *ctx = data;
465     struct surface_context *ctx_surf;
466 
467     ctx_surf = get_surface_context(ctx, surface_id);
468     if(!ctx_surf)
469         return;
470 
471     if ((ctx_surf->prop.origSourceWidth == (t_ilm_uint)width) &&
472         (ctx_surf->prop.origSourceHeight == (t_ilm_uint)height))
473         return;
474 
475     ctx_surf->prop.origSourceWidth = (t_ilm_uint)width;
476     ctx_surf->prop.origSourceHeight = (t_ilm_uint)height;
477 
478     if (ctx_surf->notification != NULL) {
479         ctx_surf->notification(ctx_surf->id_surface,
480                                 &ctx_surf->prop,
481                                 ILM_NOTIFICATION_CONFIGURED);
482     }
483 }
484 
485 static void
wm_listener_surface_source_rectangle(void * data,struct ivi_wm * controller,uint32_t surface_id,int32_t x,int32_t y,int32_t width,int32_t height)486 wm_listener_surface_source_rectangle(void *data, struct ivi_wm *controller,
487                                      uint32_t surface_id, int32_t x, int32_t y,
488                                      int32_t width, int32_t height)
489 {
490     struct wayland_context *ctx = data;
491     struct surface_context *ctx_surf;
492 
493     ctx_surf = get_surface_context(ctx, surface_id);
494     if(!ctx_surf)
495         return;
496 
497     if ((ctx_surf->prop.sourceX == (t_ilm_uint)x) &&
498         (ctx_surf->prop.sourceY == (t_ilm_uint)y) &&
499         (ctx_surf->prop.sourceWidth == (t_ilm_uint)width &&
500         (ctx_surf->prop.sourceHeight == (t_ilm_uint)height)))
501         return;
502 
503     ctx_surf->prop.sourceX = (t_ilm_uint)x;
504     ctx_surf->prop.sourceY = (t_ilm_uint)y;
505     ctx_surf->prop.sourceWidth = (t_ilm_uint)width;
506     ctx_surf->prop.sourceHeight = (t_ilm_uint)height;
507 
508     if (ctx_surf->notification != NULL) {
509         ctx_surf->notification(ctx_surf->id_surface,
510                                 &ctx_surf->prop,
511                                 ILM_NOTIFICATION_SOURCE_RECT);
512     }
513 }
514 
515 static void
wm_listener_surface_destination_rectangle(void * data,struct ivi_wm * controller,uint32_t surface_id,int32_t x,int32_t y,int32_t width,int32_t height)516 wm_listener_surface_destination_rectangle(void *data, struct ivi_wm *controller,
517                                           uint32_t surface_id, int32_t x,
518                                           int32_t y, int32_t width, int32_t height)
519 {
520     struct wayland_context *ctx = data;
521     struct surface_context *ctx_surf;
522 
523     ctx_surf = get_surface_context(ctx, surface_id);
524     if(!ctx_surf)
525         return;
526 
527     if ((ctx_surf->prop.destX == (t_ilm_uint)x) &&
528         (ctx_surf->prop.destY == (t_ilm_uint)y) &&
529         (ctx_surf->prop.destWidth == (t_ilm_uint)width &&
530         (ctx_surf->prop.destHeight == (t_ilm_uint)height)))
531         return;
532 
533     ctx_surf->prop.destX = (t_ilm_uint)x;
534     ctx_surf->prop.destY = (t_ilm_uint)y;
535     ctx_surf->prop.destWidth = (t_ilm_uint)width;
536     ctx_surf->prop.destHeight = (t_ilm_uint)height;
537 
538     if (ctx_surf->notification != NULL) {
539         ctx_surf->notification(ctx_surf->id_surface,
540                                 &ctx_surf->prop,
541                                 ILM_NOTIFICATION_DEST_RECT);
542     }
543 }
544 
545 static void
wm_listener_surface_stats(void * data,struct ivi_wm * controller,uint32_t surface_id,uint32_t frame_count,uint32_t pid)546 wm_listener_surface_stats(void *data, struct ivi_wm *controller,
547                           uint32_t surface_id, uint32_t frame_count,
548                           uint32_t pid)
549 {
550     struct wayland_context *ctx = data;
551     struct surface_context *ctx_surf;
552 
553     ctx_surf = get_surface_context(ctx, surface_id);
554     if(!ctx_surf)
555         return;
556 
557     ctx_surf->prop.frameCounter = (t_ilm_uint)frame_count;
558     ctx_surf->prop.creatorPid = (t_ilm_uint)pid;
559 }
560 
561 static void
wm_listener_surface_created(void * data,struct ivi_wm * controller,uint32_t surface_id)562 wm_listener_surface_created(void *data, struct ivi_wm *controller,
563                             uint32_t surface_id)
564 {
565     struct wayland_context *ctx = data;
566     struct surface_context *ctx_surf;
567 
568     ctx_surf = get_surface_context(ctx, surface_id);
569     if(ctx_surf)
570         return;
571 
572     ctx_surf = calloc(1, sizeof *ctx_surf);
573     if (ctx_surf == NULL) {
574         fprintf(stderr, "Failed to allocate memory for surface_context\n");
575         return;
576     }
577 
578     ctx_surf->id_surface = surface_id;
579     ctx_surf->ctx = ctx;
580 
581     wl_list_insert(&ctx->list_surface, &ctx_surf->link);
582     wl_list_init(&ctx_surf->list_accepted_seats);
583 
584     if (ctx->notification != NULL) {
585         ilmObjectType surface = ILM_SURFACE;
586         ctx->notification(surface, ctx_surf->id_surface, ILM_TRUE,
587                           ctx->notification_user_data);
588     }
589 }
590 
591 static void
wm_listener_surface_destroyed(void * data,struct ivi_wm * controller,uint32_t surface_id)592 wm_listener_surface_destroyed(void *data, struct ivi_wm *controller,
593                               uint32_t surface_id)
594 {
595     struct wayland_context *ctx = data;
596     struct surface_context *ctx_surf;
597     struct accepted_seat *seat, *seat_next;
598 
599     ctx_surf = get_surface_context(ctx, surface_id);
600     if(!ctx_surf)
601         return;
602 
603     if (ctx_surf->notification != NULL) {
604         ctx_surf->notification(ctx_surf->id_surface,
605                                &ctx_surf->prop,
606                                ILM_NOTIFICATION_CONTENT_REMOVED);
607     }
608 
609     if (ctx_surf->ctx->notification != NULL) {
610         ilmObjectType surface = ILM_SURFACE;
611         ctx_surf->ctx->notification(surface, ctx_surf->id_surface, ILM_FALSE,
612                                     ctx_surf->ctx->notification_user_data);
613     }
614 
615     wl_list_for_each_safe(seat, seat_next, &ctx_surf->list_accepted_seats, link) {
616         wl_list_remove(&seat->link);
617         free(seat->seat_name);
618         free(seat);
619     }
620 
621     wl_list_remove(&ctx_surf->link);
622     free(ctx_surf);
623 }
624 
625 static void
wm_listener_surface_error(void * data,struct ivi_wm * controller,uint32_t object_id,uint32_t code,const char * message)626 wm_listener_surface_error(void *data, struct ivi_wm *controller,
627                           uint32_t object_id, uint32_t code, const char *message)
628 {
629     struct wayland_context *ctx = data;
630     ilmErrorTypes error_code;
631 
632     switch (code) {
633     case IVI_WM_SURFACE_ERROR_NO_SURFACE:
634         error_code = ILM_ERROR_RESOURCE_NOT_FOUND;
635         fprintf(stderr, "The surface with id: %d does not exist\n", object_id);
636         break;
637     case IVI_WM_SURFACE_ERROR_NOT_SUPPORTED:
638         error_code = ILM_ERROR_NOT_IMPLEMENTED;
639         fprintf(stderr, "The surface with id: %d is used for unsupported operation\n", object_id);
640         break;
641     case IVI_WM_SURFACE_ERROR_BAD_PARAM:
642         error_code = ILM_ERROR_INVALID_ARGUMENTS;
643         fprintf(stderr, "The surface with id: %d is used with invalid parameter\n",
644                 object_id);
645         break;
646     default:
647         error_code = ILM_ERROR_ON_CONNECTION;
648         break;
649     }
650 
651     fprintf(stderr, "%s", message);
652     fprintf(stderr, "\n");
653 
654     if (ctx->error_flag == ILM_SUCCESS)
655         ctx->error_flag = error_code;
656 }
657 
658 static struct ivi_wm_listener wm_listener=
659 {
660     wm_listener_surface_visibility,
661     wm_listener_layer_visibility,
662     wm_listener_surface_opacity,
663     wm_listener_layer_opacity,
664     wm_listener_surface_source_rectangle,
665     wm_listener_layer_source_rectangle,
666     wm_listener_surface_destination_rectangle,
667     wm_listener_layer_destination_rectangle,
668     wm_listener_surface_created,
669     wm_listener_layer_created,
670     wm_listener_surface_destroyed,
671     wm_listener_layer_destroyed,
672     wm_listener_surface_error,
673     wm_listener_layer_error,
674     wm_listener_surface_size,
675     wm_listener_surface_stats,
676     wm_listener_layer_surface_added,
677 };
678 
679 static void
wm_screen_listener_screen_id(void * data,struct ivi_wm_screen * controller,uint32_t screen_id)680 wm_screen_listener_screen_id(void *data, struct ivi_wm_screen *controller,
681                              uint32_t screen_id)
682 {
683     struct screen_context *ctx_screen = data;
684 
685     ctx_screen->id_screen = screen_id;
686 }
687 
688 static void
wm_screen_listener_layer_added(void * data,struct ivi_wm_screen * controller,uint32_t layer_id)689 wm_screen_listener_layer_added(void *data, struct ivi_wm_screen *controller,
690                                uint32_t layer_id)
691 {
692     struct screen_context *ctx_screen = data;
693     (void) controller;
694 
695     uint32_t *add_id = wl_array_add(&ctx_screen->render_order, sizeof(*add_id));
696     *add_id = layer_id;
697 }
698 
699 static void
wm_screen_listener_connector_name(void * data,struct ivi_wm_screen * controller,const char * connector_name)700 wm_screen_listener_connector_name(void *data, struct ivi_wm_screen *controller,
701                                   const char *connector_name)
702 {
703     struct screen_context *ctx_screen = data;
704     (void) controller;
705 
706     strcpy(ctx_screen->prop.connectorName, connector_name);
707 }
708 
709 static void
wm_screen_listener_error(void * data,struct ivi_wm_screen * controller,uint32_t code,const char * message)710 wm_screen_listener_error(void *data, struct ivi_wm_screen *controller,
711                          uint32_t code, const char *message)
712 {
713     struct screen_context *ctx_screen = data;
714     ilmErrorTypes error_code;
715 
716     switch (code) {
717     case IVI_WM_SCREEN_ERROR_NO_LAYER:
718         error_code = ILM_ERROR_RESOURCE_NOT_FOUND;
719         fprintf(stderr, "A non-existing layer is used with the screen: %d\n",
720                 ctx_screen->id_screen);
721         break;
722     case IVI_WM_SCREEN_ERROR_NO_SCREEN:
723         error_code = ILM_ERROR_RESOURCE_NOT_FOUND;
724         fprintf(stderr, "The screen with id: %d does not exist\n",
725                 ctx_screen->id_screen);
726         break;
727     case IVI_WM_SCREEN_ERROR_BAD_PARAM:
728         error_code = ILM_ERROR_INVALID_ARGUMENTS;
729         fprintf(stderr, "The screen with id: %d is used with invalid parameter\n",
730                          ctx_screen->id_screen);
731         break;
732     default:
733         error_code = ILM_ERROR_ON_CONNECTION;
734         break;
735     }
736 
737     fprintf(stderr, "%s", message);
738     fprintf(stderr, "\n");
739 
740     if (ctx_screen->ctx->error_flag == ILM_SUCCESS)
741         ctx_screen->ctx->error_flag = error_code;
742 }
743 
744 static struct ivi_wm_screen_listener wm_screen_listener=
745 {
746     wm_screen_listener_screen_id,
747     wm_screen_listener_layer_added,
748     wm_screen_listener_connector_name,
749     wm_screen_listener_error
750 };
751 
752 static struct seat_context *
find_seat(struct wl_list * list,const char * name)753 find_seat(struct wl_list *list, const char *name)
754 {
755     struct seat_context *seat;
756     wl_list_for_each(seat, list, link) {
757         if (strcmp(name, seat->seat_name) == 0)
758             return seat;
759     }
760     return NULL;
761 }
762 
763 static void
input_listener_seat_created(void * data,struct ivi_input * ivi_input,const char * name,uint32_t capabilities)764 input_listener_seat_created(void *data,
765                             struct ivi_input *ivi_input,
766                             const char *name,
767                             uint32_t capabilities)
768 {
769     struct wayland_context *ctx = data;
770     struct seat_context *seat;
771     seat = find_seat(&ctx->list_seat, name);
772     if (seat) {
773         fprintf(stderr, "Warning: seat context was created twice!\n");
774         seat->capabilities = capabilities;
775         return;
776     }
777     seat = calloc(1, sizeof *seat);
778     if (seat == NULL) {
779         fprintf(stderr, "Failed to allocate memory for seat context\n");
780         return;
781     }
782     seat->seat_name = strdup(name);
783     seat->capabilities = capabilities;
784     wl_list_insert(&ctx->list_seat, &seat->link);
785 }
786 
787 static void
input_listener_seat_capabilities(void * data,struct ivi_input * ivi_input,const char * name,uint32_t capabilities)788 input_listener_seat_capabilities(void *data,
789                                  struct ivi_input *ivi_input,
790                                  const char *name,
791                                  uint32_t capabilities)
792 {
793     struct wayland_context *ctx = data;
794     struct seat_context *seat = find_seat(&ctx->list_seat, name);
795     if (seat == NULL) {
796         fprintf(stderr, "Warning: Cannot find seat for name %s\n", name);
797         return;
798     }
799     seat->capabilities = capabilities;
800 }
801 
802 static void
input_listener_seat_destroyed(void * data,struct ivi_input * ivi_input,const char * name)803 input_listener_seat_destroyed(void *data,
804                               struct ivi_input *ivi_input,
805                               const char *name)
806 {
807     struct wayland_context *ctx = data;
808     struct seat_context *seat = find_seat(&ctx->list_seat, name);
809     if (seat == NULL) {
810         fprintf(stderr, "Warning: Cannot find seat %s to delete it\n", name);
811         return;
812     }
813     free(seat->seat_name);
814     wl_list_remove(&seat->link);
815     free(seat);
816 }
817 
818 static void
input_listener_input_focus(void * data,struct ivi_input * ivi_input,uint32_t surface,uint32_t device,int32_t enabled)819 input_listener_input_focus(void *data,
820                            struct ivi_input *ivi_input,
821                            uint32_t surface, uint32_t device, int32_t enabled)
822 {
823     struct wayland_context *ctx = data;
824     struct surface_context *surf_ctx;
825     wl_list_for_each(surf_ctx, &ctx->list_surface, link) {
826         if (surface != surf_ctx->id_surface)
827             continue;
828 
829         if (enabled == ILM_TRUE)
830             surf_ctx->prop.focus |= device;
831         else
832             surf_ctx->prop.focus &= ~device;
833     }
834 }
835 
836 static void
input_listener_input_acceptance(void * data,struct ivi_input * ivi_input,uint32_t surface,const char * seat,int32_t accepted)837 input_listener_input_acceptance(void *data,
838                                 struct ivi_input *ivi_input,
839                                 uint32_t surface,
840                                 const char *seat,
841                                 int32_t accepted)
842 {
843     struct accepted_seat *accepted_seat, *next;
844     struct wayland_context *ctx = data;
845     struct surface_context *surface_ctx = NULL;
846     int surface_found = 1;
847     int accepted_seat_found = 0;
848 
849     wl_list_for_each(surface_ctx, &ctx->list_surface, link) {
850         if (surface_ctx->id_surface == surface) {
851             surface_found = 1;
852             break;
853         }
854     }
855 
856     if (!surface_found) {
857         fprintf(stderr, "Warning: input acceptance event received for "
858                 "nonexistent surface %d\n", surface);
859         return;
860     }
861 
862     wl_list_for_each_safe(accepted_seat, next,
863                           &surface_ctx->list_accepted_seats, link) {
864         if (strcmp(accepted_seat->seat_name, seat) != 0)
865             continue;
866 
867         if (accepted != ILM_TRUE) {
868             /* Remove this from the accepted seats */
869             free(accepted_seat->seat_name);
870             wl_list_remove(&accepted_seat->link);
871             free(accepted_seat);
872             return;
873         }
874         accepted_seat_found = 1;
875     }
876 
877     if (accepted_seat_found && accepted == ILM_TRUE) {
878         fprintf(stderr, "Warning: input acceptance event trying to add seat "
879                 "%s, that is already in surface %d\n", seat, surface);
880         return;
881     }
882     if (!accepted_seat_found && accepted != ILM_TRUE) {
883         fprintf(stderr, "Warning: input acceptance event trying to remove "
884                 "seat %s, that is not in surface %d\n", seat, surface);
885         return;
886     }
887 
888     accepted_seat = calloc(1, sizeof(*accepted_seat));
889     if (accepted_seat == NULL) {
890         fprintf(stderr, "Failed to allocate memory for accepted seat\n");
891         return;
892     }
893     accepted_seat->seat_name = strdup(seat);
894     wl_list_insert(&surface_ctx->list_accepted_seats, &accepted_seat->link);
895 }
896 
897 static struct ivi_input_listener input_listener = {
898     input_listener_seat_created,
899     input_listener_seat_capabilities,
900     input_listener_seat_destroyed,
901     input_listener_input_focus,
902     input_listener_input_acceptance
903 };
904 
905 static void
registry_handle_control(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)906 registry_handle_control(void *data,
907                        struct wl_registry *registry,
908                        uint32_t name, const char *interface,
909                        uint32_t version)
910 {
911     struct wayland_context *ctx = data;
912     (void)version;
913 
914     if (strcmp(interface, "ivi_wm") == 0) {
915         ctx->controller = wl_registry_bind(registry, name,
916                                            &ivi_wm_interface, 1);
917         if (ctx->controller == NULL) {
918             fprintf(stderr, "Failed to registry bind ivi_wm\n");
919             return;
920         }
921 
922         ivi_wm_add_listener(ctx->controller, &wm_listener, ctx);
923 
924     } else if (strcmp(interface, "ivi_input") == 0) {
925         ctx->input_controller =
926             wl_registry_bind(registry, name, &ivi_input_interface, 1);
927 
928         if (ctx->input_controller == NULL) {
929             fprintf(stderr, "Failed to registry bind input controller\n");
930             return;
931         }
932         ivi_input_add_listener(ctx->input_controller, &input_listener, ctx);
933 
934     } else if (strcmp(interface, "wl_output") == 0) {
935         struct screen_context *ctx_scrn = calloc(1, sizeof *ctx_scrn);
936 
937         if (ctx_scrn == NULL) {
938             fprintf(stderr, "Failed to allocate memory for screen_context\n");
939             return;
940         }
941         ctx_scrn->output = wl_registry_bind(registry, name,
942                                            &wl_output_interface, 1);
943         if (ctx_scrn->output == NULL) {
944             free(ctx_scrn);
945             fprintf(stderr, "Failed to registry bind wl_output\n");
946             return;
947         }
948 
949         if (wl_output_add_listener(ctx_scrn->output,
950                                    &output_listener,
951                                    ctx_scrn)) {
952             free(ctx_scrn);
953             fprintf(stderr, "Failed to add wl_output listener\n");
954             return;
955         }
956 
957         if (ctx->controller) {
958             ctx_scrn->controller = ivi_wm_create_screen(ctx->controller, ctx_scrn->output);
959             ivi_wm_screen_add_listener(ctx_scrn->controller, &wm_screen_listener,
960                                        ctx_scrn);
961         }
962 
963         ctx_scrn->ctx = ctx;
964         ctx_scrn->name = name;
965         wl_list_insert(&ctx->list_screen, &ctx_scrn->link);
966     }
967 }
968 
969 static void
registry_handle_control_remove(void * data,struct wl_registry * registry,uint32_t name)970 registry_handle_control_remove(void *data, struct wl_registry *registry, uint32_t name)
971 {
972     struct wayland_context *ctx = data;
973     struct screen_context *ctx_scrn, *next;
974 
975     /*remove wl_output and corresponding screen context*/
976     wl_list_for_each_safe(ctx_scrn, next, &ctx->list_screen, link) {
977         if(ctx_scrn->name == name)
978         { fprintf(stderr,"output_removed \n");
979             if (ctx_scrn->controller != NULL) {
980                 ivi_wm_screen_destroy(ctx_scrn->controller);
981             }
982 
983             if (ctx_scrn->output != NULL) {
984                 wl_output_destroy(ctx_scrn->output);
985             }
986 
987             wl_list_remove(&ctx_scrn->link);
988             wl_array_release(&ctx_scrn->render_order);
989             free(ctx_scrn);
990         }
991     }
992 }
993 
994 static const struct wl_registry_listener
995 registry_control_listener= {
996     registry_handle_control,
997     registry_handle_control_remove
998 };
999 
1000 struct ilm_control_context ilm_context;
1001 
destroy_control_resources(void)1002 static void destroy_control_resources(void)
1003 {
1004     struct ilm_control_context *ctx = &ilm_context;
1005 
1006     // free resources of output objects
1007     if (ctx->wl.controller) {
1008         struct screen_context *ctx_scrn;
1009         struct screen_context *next;
1010 
1011         wl_list_for_each_safe(ctx_scrn, next, &ctx->wl.list_screen, link) {
1012             if (ctx_scrn->controller != NULL) {
1013                 ivi_wm_screen_destroy(ctx_scrn->controller);
1014             }
1015 
1016             if (ctx_scrn->output != NULL) {
1017                 wl_output_destroy(ctx_scrn->output);
1018             }
1019 
1020             wl_list_remove(&ctx_scrn->link);
1021             wl_array_release(&ctx_scrn->render_order);
1022             free(ctx_scrn);
1023         }
1024     }
1025 
1026     if (ctx->wl.controller != NULL) {
1027         {
1028             struct surface_context *l;
1029             struct surface_context *n;
1030             struct accepted_seat *seat, *seat_next;
1031             wl_list_for_each_safe(l, n, &ctx->wl.list_surface, link) {
1032                 wl_list_for_each_safe(seat, seat_next, &l->list_accepted_seats, link) {
1033                     wl_list_remove(&seat->link);
1034                     free(seat->seat_name);
1035                     free(seat);
1036                 }
1037 
1038                 wl_list_remove(&l->link);
1039                 free(l);
1040             }
1041         }
1042 
1043         {
1044             struct layer_context *l;
1045             struct layer_context *n;
1046             wl_list_for_each_safe(l, n, &ctx->wl.list_layer, link) {
1047                 wl_list_remove(&l->link);
1048                 wl_array_release(&l->render_order);
1049                 free(l);
1050             }
1051         }
1052 
1053         ivi_wm_destroy(ctx->wl.controller);
1054         ctx->wl.controller = NULL;
1055     }
1056 
1057     {
1058         struct seat_context *s, *n;
1059         wl_list_for_each_safe(s, n, &ctx->wl.list_seat, link) {
1060             wl_list_remove(&s->link);
1061             free(s->seat_name);
1062             free(s);
1063         }
1064     }
1065 
1066     if (ctx->wl.display) {
1067         wl_display_flush(ctx->wl.display);
1068     }
1069 
1070     if (ctx->wl.registry) {
1071         wl_registry_destroy(ctx->wl.registry);
1072         ctx->wl.registry = NULL;
1073     }
1074 
1075     if (ctx->wl.queue) {
1076         wl_event_queue_destroy(ctx->wl.queue);
1077         ctx->wl.queue = NULL;
1078     }
1079 
1080     if (ctx->wl.input_controller) {
1081         ivi_input_destroy(ctx->wl.input_controller);
1082         ctx->wl.input_controller = NULL;
1083     }
1084 
1085     if (0 != pthread_mutex_destroy(&ctx->mutex)) {
1086         fprintf(stderr, "failed to destroy pthread_mutex\n");
1087     }
1088 }
1089 
send_shutdown_event(struct ilm_control_context * ctx)1090 static void send_shutdown_event(struct ilm_control_context *ctx)
1091 {
1092     uint64_t buf = 1;
1093     while (write(ctx->shutdown_fd, &buf, sizeof buf) == -1 && errno == EINTR)
1094        ;
1095 }
1096 
1097 ILM_EXPORT ilmErrorTypes
ilmControl_registerShutdownNotification(shutdownNotificationFunc callback,void * user_data)1098 ilmControl_registerShutdownNotification(shutdownNotificationFunc callback, void *user_data)
1099 {
1100     ilmErrorTypes returnValue = ILM_FAILED;
1101     struct ilm_control_context *ctx = sync_and_acquire_instance();
1102 
1103     if (!callback)
1104     {
1105         fprintf(stderr, "[Error] shutdownNotificationFunc is invalid\n");
1106         goto error;
1107     }
1108 
1109     ctx->notification = callback;
1110     ctx->notification_user_data = user_data;
1111 
1112     returnValue = ILM_SUCCESS;
1113 
1114 error:
1115     release_instance();
1116     return returnValue;
1117 }
1118 
1119 ILM_EXPORT void
ilmControl_destroy(void)1120 ilmControl_destroy(void)
1121 {
1122     struct ilm_control_context *ctx = &ilm_context;
1123 
1124     if (!ctx->initialized)
1125     {
1126         fprintf(stderr, "[Warning] The ilm_control_context is already destroyed\n");
1127         return;
1128     }
1129 
1130     if (ctx->shutdown_fd > -1)
1131         send_shutdown_event(ctx);
1132 
1133     // OHOS fix: ctx->thread maybe less than 0 and it's right
1134     if (0 != pthread_join(ctx->thread, NULL)) {
1135         fprintf(stderr, "failed to join control thread\n");
1136     }
1137 
1138     destroy_control_resources();
1139 
1140     if (ctx->shutdown_fd > -1)
1141         close(ctx->shutdown_fd);
1142 
1143     memset(ctx, 0, sizeof *ctx);
1144 }
1145 
1146 ILM_EXPORT ilmErrorTypes
ilmControl_init(t_ilm_nativedisplay nativedisplay)1147 ilmControl_init(t_ilm_nativedisplay nativedisplay)
1148 {
1149     struct ilm_control_context *ctx = &ilm_context;
1150 
1151     if (ctx->initialized)
1152     {
1153         fprintf(stderr, "Already initialized!\n");
1154         return ILM_FAILED;
1155     }
1156 
1157     if (nativedisplay == 0) {
1158         return ILM_ERROR_INVALID_ARGUMENTS;
1159     }
1160 
1161     ctx->shutdown_fd = -1;
1162     ctx->notification = NULL;
1163     ctx->notification_user_data = NULL;
1164 
1165     ctx->wl.display = (struct wl_display*)nativedisplay;
1166 
1167     wl_list_init(&ctx->wl.list_screen);
1168     wl_list_init(&ctx->wl.list_layer);
1169     wl_list_init(&ctx->wl.list_surface);
1170     wl_list_init(&ctx->wl.list_seat);
1171 
1172     {
1173        pthread_mutexattr_t a;
1174        if (pthread_mutexattr_init(&a) != 0)
1175        {
1176           return ILM_FAILED;
1177        }
1178 
1179        if (pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE) != 0)
1180        {
1181           pthread_mutexattr_destroy(&a);
1182           return ILM_FAILED;
1183        }
1184 
1185        if (pthread_mutex_init(&ctx->mutex, &a) != 0)
1186        {
1187            pthread_mutexattr_destroy(&a);
1188            fprintf(stderr, "failed to initialize pthread_mutex\n");
1189            return ILM_FAILED;
1190        }
1191 
1192        pthread_mutexattr_destroy(&a);
1193     }
1194 
1195     if (init_control() != 0)
1196     {
1197         ilmControl_destroy();
1198         return ILM_FAILED;
1199     }
1200 
1201     return ILM_SUCCESS;
1202 }
1203 
1204 static void
handle_shutdown(struct ilm_control_context * ctx,t_ilm_shutdown_error_type error_type)1205 handle_shutdown(struct ilm_control_context *ctx,
1206                 t_ilm_shutdown_error_type error_type)
1207 {
1208     struct wayland_context *wl_ctx = &ctx->wl;
1209     struct wl_display *display = wl_ctx->display;
1210     int errornum;
1211 
1212     switch (error_type)
1213     {
1214         case ILM_ERROR_WAYLAND:
1215             if (display == NULL) {
1216                 errornum = errno;
1217             } else {
1218                 errornum = wl_display_get_error(display);
1219             }
1220             break;
1221         case ILM_ERROR_POLL:
1222         default:
1223             errornum = errno;
1224     }
1225 
1226     fprintf(stderr, "[Error] ilm services shutdown due to error %s\n",
1227             strerror(errornum));
1228 
1229     if (!ctx->notification)
1230         return;
1231 
1232     ctx->notification(error_type, errornum, ctx->notification_user_data);
1233 }
1234 
1235 
1236 static void*
control_thread(void * p_ret)1237 control_thread(void *p_ret)
1238 {
1239     struct ilm_control_context *const ctx = &ilm_context;
1240     struct wayland_context *const wl = &ctx->wl;
1241     struct wl_display *const display = wl->display;
1242     struct wl_event_queue *const queue = wl->queue;
1243     int const fd = wl_display_get_fd(display);
1244     int const shutdown_fd = ctx->shutdown_fd;
1245     (void) p_ret;
1246 
1247     while (1)
1248     {
1249         while (wl_display_prepare_read_queue(display, queue) != 0)
1250         {
1251             lock_context(ctx);
1252             wl_display_dispatch_queue_pending(display, queue);
1253             unlock_context(ctx);
1254         }
1255 
1256         if (wl_display_flush(display) == -1)
1257         {
1258             handle_shutdown(ctx, ILM_ERROR_WAYLAND);
1259             break;
1260         }
1261 
1262         struct pollfd pfd[2] = {
1263            { .fd = fd,          .events = POLLIN },
1264            { .fd = shutdown_fd, .events = POLLIN }
1265         };
1266 
1267         int pollret = poll(pfd, 2, -1);
1268         if (pollret != -1 && (pfd[0].revents & POLLIN))
1269         {
1270             wl_display_read_events(display);
1271 
1272             lock_context(ctx);
1273             int ret = wl_display_dispatch_queue_pending(display, queue);
1274             unlock_context(ctx);
1275 
1276             if (ret == -1)
1277             {
1278                 handle_shutdown(ctx, ILM_ERROR_WAYLAND);
1279                 break;
1280             }
1281         }
1282         else
1283         {
1284             if (pollret == -1)
1285                 handle_shutdown(ctx, ILM_ERROR_POLL);
1286 
1287             wl_display_cancel_read(display);
1288 
1289             if (pollret == -1 || (pfd[1].revents & POLLIN))
1290             {
1291                 break;
1292             }
1293         }
1294     }
1295 
1296     return NULL;
1297 }
1298 
1299 static int
init_control(void)1300 init_control(void)
1301 {
1302     struct ilm_control_context *ctx = &ilm_context;
1303     struct wayland_context *wl = &ctx->wl;
1304     struct screen_context *ctx_scrn;
1305     int ret = 0;
1306 
1307     wl->queue = wl_display_create_queue(wl->display);
1308     if (! wl->queue) {
1309         fprintf(stderr, "Could not create wayland event queue\n");
1310         return -1;
1311     }
1312 
1313     /* registry_add_listener for request by ivi-controller */
1314     wl->registry = wl_display_get_registry(wl->display);
1315     if (wl->registry == NULL) {
1316         wl_event_queue_destroy(wl->queue);
1317         wl->queue = NULL;
1318         fprintf(stderr, "Failed to get registry\n");
1319         return -1;
1320     }
1321     wl_proxy_set_queue((void*)wl->registry, wl->queue);
1322 
1323     if (wl_registry_add_listener(wl->registry,
1324                              &registry_control_listener, ctx)) {
1325         fprintf(stderr, "Failed to add registry listener\n");
1326         return -1;
1327     }
1328 
1329     // get globals
1330     if (wl_display_roundtrip_queue(wl->display, wl->queue) == -1)
1331     {
1332         fprintf(stderr, "Failed to initialize wayland connection: %s\n", strerror(errno));
1333         return -1;
1334     }
1335 
1336     if (! wl->controller)
1337     {
1338         fprintf(stderr, "ivi_wm not available\n");
1339         return -1;
1340     }
1341 
1342 #ifdef USE_DUMMY_SCREEN
1343     ctx_scrn = calloc(1, sizeof *ctx_scrn);
1344     if (ctx_scrn == NULL) {
1345         fprintf(stderr, "Failed to allocate memory for screen_context\n");
1346         return -1;
1347     }
1348     ctx_scrn->ctx = wl;
1349     wl_list_insert(&wl->list_screen, &ctx_scrn->link);
1350 
1351     wl_list_for_each(ctx_scrn, &ctx->wl.list_screen, link) {
1352         if (!ctx_scrn->controller) {
1353             if (ctx_scrn->output) {
1354                 printf("for dummy output screen, output = !NULL\n");
1355                 ctx_scrn->controller = ivi_wm_create_screen(wl->controller, ctx_scrn->output);
1356                 ivi_wm_screen_add_listener(ctx_scrn->controller, &wm_screen_listener,
1357                                        ctx_scrn);
1358             }
1359             else {
1360                 printf("for dummy output screen, output = NULL\n");
1361                 //for dummy output screen.
1362                 ctx_scrn->controller = ivi_wm_create_screen2(wl->controller, 1);
1363                 ivi_wm_screen_add_listener(ctx_scrn->controller, &wm_screen_listener,
1364                                         ctx_scrn);
1365                 ctx_scrn->prop.screenWidth = 240;
1366                 ctx_scrn->prop.screenHeight = 480;
1367             }
1368         }
1369 
1370         // get screen-ids
1371         if (wl_display_roundtrip_queue(wl->display, wl->queue) == -1)
1372         {
1373             fprintf(stderr, "Failed to do roundtrip queue: %s\n", strerror(errno));
1374             return -1;
1375         }
1376     }
1377 #else
1378      wl_list_for_each(ctx_scrn, &ctx->wl.list_screen, link) {
1379          if (!ctx_scrn->controller) {
1380              ctx_scrn->controller = ivi_wm_create_screen(wl->controller, ctx_scrn->output);
1381                 ivi_wm_screen_add_listener(ctx_scrn->controller, &wm_screen_listener,
1382                                        ctx_scrn);
1383          }
1384      }
1385 #endif
1386 
1387     // get screen-ids
1388     if (wl_display_roundtrip_queue(wl->display, wl->queue) == -1)
1389     {
1390         fprintf(stderr, "Failed to do roundtrip queue: %s\n", strerror(errno));
1391         return -1;
1392     }
1393 
1394     ctx->shutdown_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
1395 
1396     if (ctx->shutdown_fd == -1)
1397     {
1398         fprintf(stderr, "Could not setup shutdown-fd: %s\n", strerror(errno));
1399         return ILM_FAILED;
1400     }
1401 
1402     ret = pthread_create(&ctx->thread, NULL, control_thread, NULL);
1403 
1404     if (ret != 0) {
1405         fprintf(stderr, "Failed to start internal receive thread. returned %d\n", ret);
1406         return -1;
1407     }
1408 
1409     ctx->initialized = true;
1410 
1411     return 0;
1412 }
1413 
impl_sync_and_acquire_instance(struct ilm_control_context * ctx)1414 ilmErrorTypes impl_sync_and_acquire_instance(struct ilm_control_context *ctx)
1415 {
1416     if (! ctx->initialized) {
1417         fprintf(stderr, "Not initialized\n");
1418         return ILM_FAILED;
1419     }
1420 
1421     lock_context(ctx);
1422 
1423     if (wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) == -1) {
1424         int err = wl_display_get_error(ctx->wl.display);
1425         fprintf(stderr, "Error communicating with wayland: %s\n", strerror(err));
1426         unlock_context(ctx);
1427         return ILM_FAILED;
1428     }
1429 
1430     return ILM_SUCCESS;
1431 }
1432 
release_instance(void)1433 void release_instance(void)
1434 {
1435     struct ilm_control_context *ctx = &ilm_context;
1436     unlock_context(ctx);
1437 }
1438 
1439 static uint32_t
gen_layer_id(struct ilm_control_context * ctx)1440 gen_layer_id(struct ilm_control_context *ctx)
1441 {
1442     struct layer_context *ctx_layer = NULL;
1443     do {
1444         int found = 0;
1445         if (wl_list_length(&ctx->wl.list_layer) == 0) {
1446             ctx->internal_id_layer++;
1447             return ctx->internal_id_layer;
1448         }
1449         wl_list_for_each(ctx_layer, &ctx->wl.list_layer, link) {
1450             if (ctx_layer->id_layer == ctx->internal_id_layer) {
1451                 found = 1;
1452                 break;
1453             }
1454 
1455             if (found == 0) {
1456                 return ctx->internal_id_layer;
1457             }
1458         }
1459         ctx->internal_id_layer++;
1460     } while(1);
1461 }
1462 
1463 static struct surface_context*
get_surface_context(struct wayland_context * ctx,uint32_t id_surface)1464 get_surface_context(struct wayland_context *ctx,
1465                           uint32_t id_surface)
1466 {
1467     struct surface_context *ctx_surf = NULL;
1468 
1469     if (ctx->controller == NULL) {
1470         fprintf(stderr, "controller is not initialized in ilmControl\n");
1471         return NULL;
1472     }
1473 
1474     wl_list_for_each(ctx_surf, &ctx->list_surface, link) {
1475         if (ctx_surf->id_surface == id_surface) {
1476             return ctx_surf;
1477         }
1478     }
1479 
1480     return NULL;
1481 }
1482 
1483 static struct screen_context*
get_screen_context_by_id(struct wayland_context * ctx,uint32_t id_screen)1484 get_screen_context_by_id(struct wayland_context *ctx, uint32_t id_screen)
1485 {
1486     struct screen_context *ctx_scrn = NULL;
1487 
1488     if (ctx->controller == NULL) {
1489         fprintf(stderr, "get_screen_context_by_id: controller is NULL\n");
1490         return NULL;
1491     }
1492 
1493     wl_list_for_each(ctx_scrn, &ctx->list_screen, link) {
1494         if (ctx_scrn->id_screen == id_screen) {
1495             return ctx_scrn;
1496         }
1497     }
1498     return NULL;
1499 }
1500 
1501 ILM_EXPORT ilmErrorTypes
ilm_getPropertiesOfLayer(t_ilm_uint layerID,struct ilmLayerProperties * pLayerProperties)1502 ilm_getPropertiesOfLayer(t_ilm_uint layerID,
1503                          struct ilmLayerProperties* pLayerProperties)
1504 {
1505     ilmErrorTypes returnValue = ILM_FAILED;
1506     struct ilm_control_context *const ctx = &ilm_context;
1507     struct layer_context *ctx_layer = NULL;
1508     int32_t mask;
1509 
1510     mask = IVI_WM_PARAM_OPACITY | IVI_WM_PARAM_VISIBILITY | IVI_WM_PARAM_SIZE;
1511 
1512     if (pLayerProperties != NULL) {
1513         lock_context(ctx);
1514 
1515         ivi_wm_layer_get(ctx->wl.controller, layerID, mask);
1516         int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
1517 
1518         ctx_layer = (struct layer_context*)
1519                     wayland_controller_get_layer_context(
1520                         &ctx->wl, (uint32_t)layerID);
1521 
1522         if ((ret != -1) && (ctx_layer != NULL))
1523         {
1524             *pLayerProperties = ctx_layer->prop;
1525             returnValue = ILM_SUCCESS;
1526         }
1527 
1528         unlock_context(ctx);
1529     }
1530 
1531     return returnValue;
1532 }
1533 
1534 static void
create_layerids(struct screen_context * ctx_screen,t_ilm_layer ** layer_ids,t_ilm_uint * layer_count)1535 create_layerids(struct screen_context *ctx_screen,
1536                 t_ilm_layer **layer_ids, t_ilm_uint *layer_count)
1537 {
1538     t_ilm_layer *ids = NULL;
1539     uint32_t *id = NULL;
1540 
1541     if (ctx_screen->render_order.size == 0) {
1542         *layer_ids = NULL;
1543         *layer_count = 0;
1544         return;
1545     }
1546 
1547     *layer_ids = malloc(ctx_screen->render_order.size);
1548     if (*layer_ids == NULL) {
1549         fprintf(stderr, "memory insufficient for layerids\n");
1550         *layer_count = 0;
1551         wl_array_release(&ctx_screen->render_order);
1552         wl_array_init(&ctx_screen->render_order);
1553         return;
1554     }
1555 
1556     ids = *layer_ids;
1557     wl_array_for_each(id, &ctx_screen->render_order) {
1558         *ids = (t_ilm_layer) *id;
1559         ids++;
1560         (*layer_count)++;
1561     }
1562 
1563     wl_array_release(&ctx_screen->render_order);
1564     wl_array_init(&ctx_screen->render_order);
1565 }
1566 
1567 ILM_EXPORT ilmErrorTypes
ilm_getPropertiesOfScreen(t_ilm_display screenID,struct ilmScreenProperties * pScreenProperties)1568 ilm_getPropertiesOfScreen(t_ilm_display screenID,
1569                               struct ilmScreenProperties* pScreenProperties)
1570 {
1571     ilmErrorTypes returnValue = ILM_FAILED;
1572     struct ilm_control_context *const ctx = &ilm_context;
1573 
1574     if (! pScreenProperties)
1575     {
1576         return ILM_ERROR_INVALID_ARGUMENTS;
1577     }
1578 
1579     lock_context(ctx);
1580     struct screen_context *ctx_screen = NULL;
1581     ctx_screen = get_screen_context_by_id(&ctx->wl, (uint32_t)screenID);
1582     if (ctx_screen != NULL) {
1583         ivi_wm_screen_get(ctx_screen->controller, IVI_WM_PARAM_RENDER_ORDER);
1584 
1585         if (wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) != -1 ) {
1586             *pScreenProperties = ctx_screen->prop;
1587             create_layerids(ctx_screen, &pScreenProperties->layerIds,
1588                                         &pScreenProperties->layerCount);
1589             returnValue = ILM_SUCCESS;
1590         }
1591     }
1592 
1593     unlock_context(ctx);
1594     return returnValue;
1595 }
1596 
1597 ILM_EXPORT ilmErrorTypes
ilm_getScreenIDs(t_ilm_uint * pNumberOfIDs,t_ilm_uint ** ppIDs)1598 ilm_getScreenIDs(t_ilm_uint* pNumberOfIDs, t_ilm_uint** ppIDs)
1599 {
1600     ilmErrorTypes returnValue = ILM_FAILED;
1601     struct ilm_control_context *ctx = sync_and_acquire_instance();
1602 
1603     if ((pNumberOfIDs != NULL) && (ppIDs != NULL)) {
1604         struct screen_context *ctx_scrn = NULL;
1605         t_ilm_uint length = wl_list_length(&ctx->wl.list_screen);
1606         *pNumberOfIDs = 0;
1607 
1608         *ppIDs = (t_ilm_uint*)malloc(length * sizeof **ppIDs);
1609         if (*ppIDs != NULL) {
1610             t_ilm_uint* ids = *ppIDs;
1611             // compositor sends screens in opposite order
1612             // write ids from back to front to turn them around
1613             wl_list_for_each_reverse(ctx_scrn, &ctx->wl.list_screen, link) {
1614                 *ids = ctx_scrn->id_screen;
1615                 ids++;
1616             }
1617             *pNumberOfIDs = length;
1618 
1619             returnValue = ILM_SUCCESS;
1620         }
1621     }
1622 
1623     release_instance();
1624     return returnValue;
1625 }
1626 
1627 ILM_EXPORT ilmErrorTypes
ilm_getScreenResolution(t_ilm_uint screenID,t_ilm_uint * pWidth,t_ilm_uint * pHeight)1628 ilm_getScreenResolution(t_ilm_uint screenID, t_ilm_uint* pWidth, t_ilm_uint* pHeight)
1629 {
1630     ilmErrorTypes returnValue = ILM_FAILED;
1631     struct ilm_control_context *ctx = sync_and_acquire_instance();
1632 
1633     if ((pWidth != NULL) && (pHeight != NULL))
1634     {
1635         struct screen_context *ctx_scrn;
1636         wl_list_for_each(ctx_scrn, &ctx->wl.list_screen, link) {
1637             if (screenID == ctx_scrn->id_screen) {
1638                 *pWidth = ctx_scrn->prop.screenWidth;
1639                 *pHeight = ctx_scrn->prop.screenHeight;
1640                 returnValue = ILM_SUCCESS;
1641                 break;
1642             }
1643         }
1644     }
1645 
1646     release_instance();
1647     return returnValue;
1648 }
1649 
1650 ILM_EXPORT ilmErrorTypes
ilm_getLayerIDs(t_ilm_int * pLength,t_ilm_layer ** ppArray)1651 ilm_getLayerIDs(t_ilm_int* pLength, t_ilm_layer** ppArray)
1652 {
1653     ilmErrorTypes returnValue = ILM_FAILED;
1654     struct ilm_control_context *ctx = sync_and_acquire_instance();
1655 
1656     if ((pLength != NULL) && (ppArray != NULL)) {
1657         struct layer_context *ctx_layer = NULL;
1658         t_ilm_uint length = wl_list_length(&ctx->wl.list_layer);
1659         *pLength = 0;
1660 
1661         *ppArray = (t_ilm_layer*)malloc(length * sizeof **ppArray);
1662         if (*ppArray != NULL) {
1663             // compositor sends layers in opposite order
1664             // write ids from back to front to turn them around
1665             t_ilm_layer* ids = *ppArray;
1666             wl_list_for_each_reverse(ctx_layer, &ctx->wl.list_layer, link)
1667             {
1668                 *ids = ctx_layer->id_layer;
1669                 ++ids;
1670             }
1671             *pLength = length;
1672 
1673             returnValue = ILM_SUCCESS;
1674         }
1675     }
1676 
1677     release_instance();
1678     return returnValue;
1679 }
1680 
1681 ILM_EXPORT ilmErrorTypes
ilm_getLayerIDsOnScreen(t_ilm_uint screenId,t_ilm_int * pLength,t_ilm_layer ** ppArray)1682 ilm_getLayerIDsOnScreen(t_ilm_uint screenId,
1683                             t_ilm_int* pLength,
1684                             t_ilm_layer** ppArray)
1685 {
1686     ilmErrorTypes returnValue = ILM_FAILED;
1687     struct ilm_control_context *const ctx = &ilm_context;
1688 
1689     if ((pLength != NULL) && (ppArray != NULL)) {
1690         lock_context(ctx);
1691         struct screen_context *ctx_screen = NULL;
1692         ctx_screen = get_screen_context_by_id(&ctx->wl, screenId);
1693         if (ctx_screen != NULL) {
1694             *pLength = 0;
1695             *ppArray = NULL;
1696 
1697             ivi_wm_screen_get(ctx_screen->controller, IVI_WM_PARAM_RENDER_ORDER);
1698 
1699             if (wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) != -1 ) {
1700                 create_layerids(ctx_screen, ppArray, (t_ilm_uint*)pLength);
1701                 returnValue = ILM_SUCCESS;
1702             }
1703         }
1704     }
1705 
1706     unlock_context(ctx);
1707     return returnValue;
1708 }
1709 
1710 ILM_EXPORT ilmErrorTypes
ilm_getSurfaceIDs(t_ilm_int * pLength,t_ilm_surface ** ppArray)1711 ilm_getSurfaceIDs(t_ilm_int* pLength, t_ilm_surface** ppArray)
1712 {
1713     ilmErrorTypes returnValue = ILM_FAILED;
1714     struct ilm_control_context *ctx = sync_and_acquire_instance();
1715 
1716     if ((pLength != NULL) && (ppArray != NULL)) {
1717         struct surface_context *ctx_surf = NULL;
1718         t_ilm_uint length = wl_list_length(&ctx->wl.list_surface);
1719         *pLength = 0;
1720 
1721         *ppArray = (t_ilm_surface*)malloc(length * sizeof **ppArray);
1722         if (*ppArray != NULL) {
1723             t_ilm_surface* ids = *ppArray;
1724             wl_list_for_each_reverse(ctx_surf, &ctx->wl.list_surface, link) {
1725                 *ids = ctx_surf->id_surface;
1726                 ids++;
1727             }
1728             *pLength = length;
1729 
1730             returnValue = ILM_SUCCESS;
1731         }
1732     }
1733 
1734     release_instance();
1735     return returnValue;
1736 }
1737 
1738 ILM_EXPORT ilmErrorTypes
ilm_getSurfaceIDsOnLayer(t_ilm_layer layer,t_ilm_int * pLength,t_ilm_surface ** ppArray)1739 ilm_getSurfaceIDsOnLayer(t_ilm_layer layer,
1740                              t_ilm_int* pLength,
1741                              t_ilm_surface** ppArray)
1742 {
1743     struct ilm_control_context *const ctx = &ilm_context;
1744     struct layer_context *ctx_layer = NULL;
1745     t_ilm_uint length = 0;
1746     t_ilm_surface* ids = NULL;
1747     uint32_t *id = NULL;
1748 
1749     if ((pLength == NULL) || (ppArray == NULL)) {
1750         release_instance();
1751         return ILM_FAILED;
1752     }
1753 
1754     lock_context(ctx);
1755 
1756     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
1757                     &ctx->wl, (uint32_t)layer);
1758 
1759     if (ctx_layer == NULL) {
1760         unlock_context(ctx);
1761         return ILM_FAILED;
1762     }
1763 
1764     ivi_wm_layer_get(ctx->wl.controller, layer, IVI_WM_PARAM_RENDER_ORDER);
1765     int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
1766 
1767     if (ret < 0) {
1768         wl_array_release(&ctx_layer->render_order);
1769         wl_array_init(&ctx_layer->render_order);
1770         unlock_context(ctx);
1771         return ILM_FAILED;
1772     }
1773 
1774     *ppArray = (t_ilm_surface*)malloc(ctx_layer->render_order.size);
1775     if (*ppArray == NULL) {
1776         wl_array_release(&ctx_layer->render_order);
1777         wl_array_init(&ctx_layer->render_order);
1778         unlock_context(ctx);
1779         return ILM_FAILED;
1780     }
1781 
1782     ids = *ppArray;
1783     wl_array_for_each(id, &ctx_layer->render_order) {
1784         *ids = (t_ilm_surface) *id;
1785         ids++;
1786         length++;
1787     }
1788 
1789     wl_array_release(&ctx_layer->render_order);
1790     wl_array_init(&ctx_layer->render_order);
1791     *pLength = length;
1792 
1793     unlock_context(ctx);
1794     return ILM_SUCCESS;
1795 }
1796 
1797 ILM_EXPORT ilmErrorTypes
ilm_layerCreateWithDimension(t_ilm_layer * pLayerId,t_ilm_uint width,t_ilm_uint height)1798 ilm_layerCreateWithDimension(t_ilm_layer* pLayerId,
1799                                  t_ilm_uint width,
1800                                  t_ilm_uint height)
1801 {
1802     ilmErrorTypes returnValue = ILM_FAILED;
1803     struct ilm_control_context *ctx = sync_and_acquire_instance();
1804     uint32_t layerid = 0;
1805     int32_t is_inside = 0;
1806 
1807     do {
1808         if (pLayerId == NULL) {
1809             break;
1810         }
1811 
1812         if (*pLayerId != INVALID_ID) {
1813             /* Return failed, if layerid is already inside list_layer */
1814             is_inside = wayland_controller_is_inside_layer_list(
1815                             &ctx->wl.list_layer, *pLayerId);
1816             if (0 != is_inside) {
1817                 fprintf(stderr, "layerid=%d is already used.\n", *pLayerId);
1818                 break;
1819             }
1820             layerid = *pLayerId;
1821         }
1822         else {
1823             /* Generate ID, if layerid is INVALID_ID */
1824             layerid = gen_layer_id(ctx);
1825             *pLayerId = layerid;
1826         }
1827 
1828         ivi_wm_create_layout_layer(ctx->wl.controller, layerid, width, height);
1829         wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
1830 
1831         returnValue = ILM_SUCCESS;
1832     } while(0);
1833 
1834     release_instance();
1835     return returnValue;
1836 }
1837 
1838 ILM_EXPORT ilmErrorTypes
ilm_layerRemove(t_ilm_layer layerId)1839 ilm_layerRemove(t_ilm_layer layerId)
1840 {
1841     ilmErrorTypes returnValue = ILM_FAILED;
1842     struct ilm_control_context *const ctx = &ilm_context;
1843 
1844     lock_context(ctx);
1845     if (ctx->wl.controller) {
1846         ivi_wm_destroy_layout_layer(ctx->wl.controller, layerId);
1847         wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
1848         returnValue = ILM_SUCCESS;
1849     }
1850     unlock_context(ctx);
1851 
1852     return returnValue;
1853 }
1854 
1855 ILM_EXPORT ilmErrorTypes
ilm_layerSetVisibility(t_ilm_layer layerId,t_ilm_bool newVisibility)1856 ilm_layerSetVisibility(t_ilm_layer layerId, t_ilm_bool newVisibility)
1857 {
1858     ilmErrorTypes returnValue = ILM_FAILED;
1859     struct ilm_control_context *const ctx = &ilm_context;
1860     uint32_t visibility = 0;
1861 
1862     if (newVisibility == ILM_TRUE) {
1863         visibility = 1;
1864     }
1865 
1866     lock_context(ctx);
1867     if (ctx->wl.controller) {
1868         ivi_wm_set_layer_visibility(ctx->wl.controller, layerId, visibility);
1869         wl_display_flush(ctx->wl.display);
1870         returnValue = ILM_SUCCESS;
1871     }
1872     unlock_context(ctx);
1873 
1874     return returnValue;
1875 }
1876 
1877 ILM_EXPORT ilmErrorTypes
ilm_layerGetVisibility(t_ilm_layer layerId,t_ilm_bool * pVisibility)1878 ilm_layerGetVisibility(t_ilm_layer layerId, t_ilm_bool *pVisibility)
1879 {
1880     ilmErrorTypes returnValue = ILM_FAILED;
1881     struct ilm_control_context *const ctx = &ilm_context;
1882     struct layer_context *ctx_layer = NULL;
1883 
1884     if (pVisibility != NULL) {
1885         lock_context(ctx);
1886 
1887         ivi_wm_layer_get(ctx->wl.controller, layerId, IVI_WM_PARAM_VISIBILITY);
1888         int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
1889 
1890         ctx_layer = (struct layer_context*)
1891                     wayland_controller_get_layer_context(
1892                         &ctx->wl, (uint32_t)layerId);
1893 
1894         if ((ret != -1) && (ctx_layer != NULL))
1895         {
1896             *pVisibility = ctx_layer->prop.visibility;
1897             returnValue = ILM_SUCCESS;
1898         }
1899 
1900         unlock_context(ctx);
1901     }
1902 
1903     return returnValue;
1904 }
1905 
1906 ILM_EXPORT ilmErrorTypes
ilm_layerSetOpacity(t_ilm_layer layerId,t_ilm_float opacity)1907 ilm_layerSetOpacity(t_ilm_layer layerId, t_ilm_float opacity)
1908 {
1909     ilmErrorTypes returnValue = ILM_FAILED;
1910     struct ilm_control_context *const ctx = &ilm_context;
1911     wl_fixed_t opacity_fixed = wl_fixed_from_double((double)opacity);
1912 
1913     lock_context(ctx);
1914     if (ctx->wl.controller) {
1915         ivi_wm_set_layer_opacity(ctx->wl.controller, layerId, opacity_fixed);
1916         wl_display_flush(ctx->wl.display);
1917         returnValue = ILM_SUCCESS;
1918     }
1919     unlock_context(ctx);
1920 
1921     return returnValue;
1922 }
1923 
1924 ILM_EXPORT ilmErrorTypes
ilm_layerGetOpacity(t_ilm_layer layerId,t_ilm_float * pOpacity)1925 ilm_layerGetOpacity(t_ilm_layer layerId, t_ilm_float *pOpacity)
1926 {
1927     ilmErrorTypes returnValue = ILM_FAILED;
1928     struct ilm_control_context *const ctx = &ilm_context;
1929     struct layer_context *ctx_layer = NULL;
1930 
1931     if (pOpacity != NULL) {
1932         lock_context(ctx);
1933 
1934         ivi_wm_layer_get(ctx->wl.controller, layerId, IVI_WM_PARAM_OPACITY);
1935         int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
1936 
1937         ctx_layer = (struct layer_context*)
1938                     wayland_controller_get_layer_context(
1939                         &ctx->wl, (uint32_t)layerId);
1940 
1941         if ((ret != -1) && (ctx_layer != NULL))
1942         {
1943             *pOpacity = ctx_layer->prop.opacity;
1944             returnValue = ILM_SUCCESS;
1945         }
1946 
1947         unlock_context(ctx);
1948     }
1949 
1950     return returnValue;
1951 }
1952 
1953 ILM_EXPORT ilmErrorTypes
ilm_layerSetSourceRectangle(t_ilm_layer layerId,t_ilm_uint x,t_ilm_uint y,t_ilm_uint width,t_ilm_uint height)1954 ilm_layerSetSourceRectangle(t_ilm_layer layerId,
1955                                 t_ilm_uint x, t_ilm_uint y,
1956                                 t_ilm_uint width, t_ilm_uint height)
1957 {
1958     ilmErrorTypes returnValue = ILM_FAILED;
1959     struct ilm_control_context *const ctx = &ilm_context;
1960 
1961     lock_context(ctx);
1962     if (ctx->wl.controller) {
1963         ivi_wm_set_layer_source_rectangle(ctx->wl.controller, layerId,
1964                                           (uint32_t)x, (uint32_t)y,
1965                                           (uint32_t)width, (uint32_t)height);
1966         wl_display_flush(ctx->wl.display);
1967         returnValue = ILM_SUCCESS;
1968     }
1969     unlock_context(ctx);
1970 
1971     return returnValue;
1972 }
1973 
1974 ILM_EXPORT ilmErrorTypes
ilm_layerSetDestinationRectangle(t_ilm_layer layerId,t_ilm_int x,t_ilm_int y,t_ilm_int width,t_ilm_int height)1975 ilm_layerSetDestinationRectangle(t_ilm_layer layerId,
1976                                  t_ilm_int x, t_ilm_int y,
1977                                  t_ilm_int width, t_ilm_int height)
1978 {
1979     ilmErrorTypes returnValue = ILM_FAILED;
1980     struct ilm_control_context *const ctx = &ilm_context;
1981 
1982     lock_context(ctx);
1983     if (ctx->wl.controller) {
1984         ivi_wm_set_layer_destination_rectangle(ctx->wl.controller,
1985                                                layerId, (uint32_t)x,
1986                                                (uint32_t)y, (uint32_t)width,
1987                                                (uint32_t)height);
1988         wl_display_flush(ctx->wl.display);
1989         returnValue = ILM_SUCCESS;
1990     }
1991     unlock_context(ctx);
1992 
1993     return returnValue;
1994 }
1995 
1996 ILM_EXPORT ilmErrorTypes
ilm_layerSetRenderOrder(t_ilm_layer layerId,t_ilm_surface * pSurfaceId,t_ilm_int number)1997 ilm_layerSetRenderOrder(t_ilm_layer layerId,
1998                         t_ilm_surface *pSurfaceId,
1999                         t_ilm_int number)
2000 {
2001     ilmErrorTypes returnValue = ILM_FAILED;
2002     struct ilm_control_context *const ctx = &ilm_context;
2003     t_ilm_int i;
2004 
2005     lock_context(ctx);
2006     if (ctx->wl.controller) {
2007         ivi_wm_layer_clear(ctx->wl.controller, layerId);
2008 
2009         for (i = 0; i < number; i++) {
2010             ivi_wm_layer_add_surface(ctx->wl.controller, layerId,
2011                                      (uint32_t)pSurfaceId[i]);
2012         }
2013 
2014         wl_display_flush(ctx->wl.display);
2015         returnValue = ILM_SUCCESS;
2016     }
2017     unlock_context(ctx);
2018 
2019     return returnValue;
2020 }
2021 
2022 ILM_EXPORT ilmErrorTypes
ilm_surfaceSetVisibility(t_ilm_surface surfaceId,t_ilm_bool newVisibility)2023 ilm_surfaceSetVisibility(t_ilm_surface surfaceId, t_ilm_bool newVisibility)
2024 {
2025     ilmErrorTypes returnValue = ILM_FAILED;
2026     struct ilm_control_context *const ctx = &ilm_context;
2027     uint32_t visibility = 0;
2028 
2029     if (newVisibility == ILM_TRUE) {
2030         visibility = 1;
2031     }
2032 
2033     lock_context(ctx);
2034     if (ctx->wl.controller) {
2035         ivi_wm_set_surface_visibility(ctx->wl.controller, surfaceId, visibility);
2036         wl_display_flush(ctx->wl.display);
2037         returnValue = ILM_SUCCESS;
2038     }
2039     unlock_context(ctx);
2040 
2041     return returnValue;
2042 }
2043 
2044 ILM_EXPORT ilmErrorTypes
ilm_surfaceSetOpacity(t_ilm_surface surfaceId,t_ilm_float opacity)2045 ilm_surfaceSetOpacity(t_ilm_surface surfaceId, t_ilm_float opacity)
2046 {
2047     ilmErrorTypes returnValue = ILM_FAILED;
2048     struct ilm_control_context *const ctx = &ilm_context;
2049     wl_fixed_t opacity_fixed = wl_fixed_from_double((double)opacity);
2050 
2051     lock_context(ctx);
2052     if (ctx->wl.controller) {
2053         ivi_wm_set_surface_opacity(ctx->wl.controller, surfaceId, opacity_fixed);
2054         wl_display_flush(ctx->wl.display);
2055         returnValue = ILM_SUCCESS;
2056     }
2057     unlock_context(ctx);
2058 
2059     return returnValue;
2060 }
2061 
2062 ILM_EXPORT ilmErrorTypes
ilm_surfaceGetOpacity(t_ilm_surface surfaceId,t_ilm_float * pOpacity)2063 ilm_surfaceGetOpacity(t_ilm_surface surfaceId, t_ilm_float *pOpacity)
2064 {
2065     ilmErrorTypes returnValue = ILM_FAILED;
2066     struct ilm_control_context *const ctx = &ilm_context;
2067     struct surface_context *ctx_surf = NULL;
2068 
2069     if (pOpacity != NULL) {
2070         lock_context(ctx);
2071 
2072         ivi_wm_surface_get(ctx->wl.controller, surfaceId, IVI_WM_PARAM_OPACITY);
2073         int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
2074 
2075         ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2076 
2077         if ((ret != -1) && (ctx_surf != NULL))
2078         {
2079             *pOpacity = ctx_surf->prop.opacity;
2080             returnValue = ILM_SUCCESS;
2081         }
2082 
2083         unlock_context(ctx);
2084     }
2085 
2086     return returnValue;
2087 }
2088 
2089 ILM_EXPORT ilmErrorTypes
ilm_surfaceSetDestinationRectangle(t_ilm_surface surfaceId,t_ilm_int x,t_ilm_int y,t_ilm_int width,t_ilm_int height)2090 ilm_surfaceSetDestinationRectangle(t_ilm_surface surfaceId,
2091                                    t_ilm_int x, t_ilm_int y,
2092                                    t_ilm_int width, t_ilm_int height)
2093 {
2094     ilmErrorTypes returnValue = ILM_FAILED;
2095     struct ilm_control_context *const ctx = &ilm_context;
2096 
2097     lock_context(ctx);
2098     if (ctx->wl.controller) {
2099         ivi_wm_set_surface_destination_rectangle(ctx->wl.controller, surfaceId,
2100                                                  x, y, width, height);
2101         wl_display_flush(ctx->wl.display);
2102         returnValue = ILM_SUCCESS;
2103     }
2104     unlock_context(ctx);
2105 
2106     return returnValue;
2107 }
2108 
2109 ILM_EXPORT ilmErrorTypes
ilm_surfaceSetType(t_ilm_surface surfaceId,ilmSurfaceType type)2110 ilm_surfaceSetType(t_ilm_surface surfaceId, ilmSurfaceType type)
2111 {
2112     ilmErrorTypes returnValue = ILM_FAILED;
2113     struct ilm_control_context *const ctx = &ilm_context;
2114     int32_t ivitype = 0;
2115 
2116     switch(type) {
2117     case ILM_SURFACETYPE_RESTRICTED:
2118         ivitype = IVI_WM_SURFACE_TYPE_RESTRICTED;
2119         break;
2120     case ILM_SURFACETYPE_DESKTOP:
2121         ivitype = IVI_WM_SURFACE_TYPE_DESKTOP;
2122         break;
2123     default:
2124         ivitype = -1;
2125         returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2126         break;
2127     }
2128 
2129     lock_context(ctx);
2130     if ((ivitype >= 0) && ctx->wl.controller) {
2131         ivi_wm_set_surface_type(ctx->wl.controller, surfaceId, type);
2132         wl_display_flush(ctx->wl.display);
2133         returnValue = ILM_SUCCESS;
2134     }
2135     unlock_context(ctx);
2136 
2137     return returnValue;
2138 }
2139 
2140 ILM_EXPORT ilmErrorTypes
ilm_displaySetRenderOrder(t_ilm_display display,t_ilm_layer * pLayerId,const t_ilm_uint number)2141 ilm_displaySetRenderOrder(t_ilm_display display,
2142                           t_ilm_layer *pLayerId, const t_ilm_uint number)
2143 {
2144     ilmErrorTypes returnValue = ILM_FAILED;
2145     struct ilm_control_context *const ctx = &ilm_context;
2146     struct screen_context *ctx_scrn = NULL;
2147     t_ilm_uint i;
2148 
2149     lock_context(ctx);
2150     ctx_scrn = get_screen_context_by_id(&ctx->wl, (uint32_t)display);
2151     if (ctx_scrn != NULL) {
2152         ivi_wm_screen_clear(ctx_scrn->controller);
2153 
2154         for (i = 0; i < number; i++) {
2155             ivi_wm_screen_add_layer(ctx_scrn->controller, (uint32_t)pLayerId[i]);
2156         }
2157 
2158         wl_display_flush(ctx->wl.display);
2159         returnValue = ILM_SUCCESS;
2160     }
2161     unlock_context(ctx);
2162 
2163     return returnValue;
2164 }
2165 
screenshot_done(void * data,struct ivi_screenshot * ivi_screenshot,int32_t fd,int32_t width,int32_t height,int32_t stride,uint32_t format,uint32_t timestamp)2166 static void screenshot_done(void *data, struct ivi_screenshot *ivi_screenshot,
2167                             int32_t fd, int32_t width, int32_t height,
2168                             int32_t stride, uint32_t format, uint32_t timestamp)
2169 {
2170     struct screenshot_context *ctx_scrshot = data;
2171     char *buffer;
2172     size_t size = stride * height;
2173     const char *filename = ctx_scrshot->filename;
2174     char *filename_ext = NULL;
2175 
2176     ctx_scrshot->filename = NULL;
2177     ivi_screenshot_destroy(ivi_screenshot);
2178 
2179     if (filename == NULL) {
2180         ctx_scrshot->result = ILM_FAILED;
2181         fprintf(stderr, "screenshot file name not provided: %m\n");
2182         return;
2183     }
2184 
2185     buffer = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
2186     close(fd);
2187 
2188     if (buffer == MAP_FAILED) {
2189         ctx_scrshot->result = ILM_FAILED;
2190         fprintf(stderr, "failed to mmap screenshot file: %m\n");
2191         return;
2192     }
2193 
2194     if ((filename_ext = strstr(filename, ".png")) && (strlen(filename_ext) == 4)) {
2195         if (save_as_png(filename, (const char *)buffer,
2196                         width, height, format) == 0) {
2197             ctx_scrshot->result = ILM_SUCCESS;
2198         } else {
2199             ctx_scrshot->result = ILM_FAILED;
2200             fprintf(stderr, "failed to write screenshot as png file: %m\n");
2201         }
2202     } else {
2203         if (!((filename_ext = strstr(filename, ".bmp")) && (strlen(filename_ext) == 4))) {
2204             fprintf(stderr, "trying to write screenshot as bmp file, although file extension does not match: %m\n");
2205         }
2206 
2207         if (save_as_bitmap(filename, (const char *)buffer,
2208                            width, height, format) == 0) {
2209             ctx_scrshot->result = ILM_SUCCESS;
2210         } else {
2211             ctx_scrshot->result = ILM_FAILED;
2212             fprintf(stderr, "failed to write screenshot as bmp file: %m\n");
2213         }
2214     }
2215 
2216     munmap(buffer, size);
2217 }
2218 
screenshot_error(void * data,struct ivi_screenshot * ivi_screenshot,uint32_t error,const char * message)2219 static void screenshot_error(void *data, struct ivi_screenshot *ivi_screenshot,
2220                              uint32_t error, const char *message)
2221 {
2222     struct screenshot_context *ctx_scrshot = data;
2223     ctx_scrshot->filename = NULL;
2224     ivi_screenshot_destroy(ivi_screenshot);
2225     fprintf(stderr, "screenshot failed, error 0x%x: %s\n", error, message);
2226 }
2227 
2228 static struct ivi_screenshot_listener screenshot_listener = {
2229     screenshot_done,
2230     screenshot_error,
2231 };
2232 
screenshot_buffer_done(void * data,struct ivi_screenshot * ivi_screenshot,int32_t fd,int32_t width,int32_t height,int32_t stride,uint32_t format,uint32_t timestamp)2233 static void screenshot_buffer_done(void *data, struct ivi_screenshot *ivi_screenshot,
2234                             int32_t fd, int32_t width, int32_t height,
2235                             int32_t stride, uint32_t format, uint32_t timestamp)
2236 {
2237     struct screenshot_buffer_context *ctx_scrshot = data;
2238     char *buffer;
2239     size_t size = stride * height;
2240 
2241     ctx_scrshot->isshotdone = true;
2242     ivi_screenshot_destroy(ivi_screenshot);
2243 
2244     buffer = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
2245     close(fd);
2246 
2247     if (buffer == MAP_FAILED) {
2248         ctx_scrshot->result = ILM_FAILED;
2249         fprintf(stderr, "failed to mmap screenshot file: %m\n");
2250         return;
2251     }
2252     if (ctx_scrshot->done_cb) {
2253         ctx_scrshot->done_cb(buffer, size, width, height, format);
2254         ctx_scrshot->result = ILM_SUCCESS;
2255     } else {
2256         ctx_scrshot->result = ILM_FAILED;
2257     }
2258     munmap(buffer, size);
2259 }
2260 
screenshot_buffer_error(void * data,struct ivi_screenshot * ivi_screenshot,uint32_t error,const char * message)2261 static void screenshot_buffer_error(void *data, struct ivi_screenshot *ivi_screenshot,
2262                              uint32_t error, const char *message)
2263 {
2264     struct screenshot_buffer_context *ctx_scrshot = data;
2265     ctx_scrshot->isshotdone = true;
2266     ivi_screenshot_destroy(ivi_screenshot);
2267     fprintf(stderr, "screenshot failed, error 0x%x: %s\n", error, message);
2268 }
2269 
2270 static struct ivi_screenshot_listener screenshot_buffer_listener = {
2271     screenshot_buffer_done,
2272     screenshot_buffer_error,
2273 };
2274 
2275 ILM_EXPORT ilmErrorTypes
ilm_takeScreenshot_buffer(t_ilm_uint screen,shotdoneNotificationFunc doneCb)2276 ilm_takeScreenshot_buffer(t_ilm_uint screen, shotdoneNotificationFunc doneCb)
2277 {
2278     ilmErrorTypes returnValue = ILM_FAILED;
2279     struct ilm_control_context *const ctx = &ilm_context;
2280     struct screen_context *ctx_scrn = NULL;
2281 
2282     lock_context(ctx);
2283     ctx_scrn = get_screen_context_by_id(&ctx->wl, (uint32_t)screen);
2284     if (ctx_scrn != NULL) {
2285         struct screenshot_buffer_context ctx_scrshot = {
2286             .isshotdone = false,
2287             .result = ILM_FAILED,
2288             .done_cb = doneCb,
2289         };
2290 
2291         struct ivi_screenshot *scrshot =
2292             ivi_wm_screen_screenshot(ctx_scrn->controller);
2293         if (scrshot) {
2294             ivi_screenshot_add_listener(scrshot, &screenshot_buffer_listener,
2295                                         &ctx_scrshot);
2296             // dispatch until filename has been reset in done or error callback
2297             int ret;
2298             do {
2299                 ret =
2300                     wl_display_dispatch_queue(ctx->wl.display, ctx->wl.queue);
2301             } while ((ret != -1) && !ctx_scrshot.isshotdone);
2302 
2303             returnValue = ctx_scrshot.result;
2304         }
2305     }
2306     unlock_context(ctx);
2307 
2308     return returnValue;
2309 }
2310 
2311 ILM_EXPORT ilmErrorTypes
ilm_takeSurfaceScreenshot_buffer(t_ilm_surface surfaceid,shotdoneNotificationFunc doneCb)2312 ilm_takeSurfaceScreenshot_buffer(t_ilm_surface surfaceid,
2313                               shotdoneNotificationFunc doneCb)
2314 {
2315     ilmErrorTypes returnValue = ILM_FAILED;
2316     struct ilm_control_context *const ctx = &ilm_context;
2317 
2318     lock_context(ctx);
2319     if (ctx->wl.controller) {
2320           struct screenshot_buffer_context ctx_scrshot = {
2321             .isshotdone = false,
2322             .result = ILM_FAILED,
2323             .done_cb = doneCb,
2324         };
2325 
2326         struct ivi_screenshot *scrshot =
2327             ivi_wm_surface_screenshot(ctx->wl.controller, surfaceid);
2328         if (scrshot) {
2329             ivi_screenshot_add_listener(scrshot, &screenshot_buffer_listener,
2330                                         &ctx_scrshot);
2331             // dispatch until filename has been reset in done or error callback
2332             int ret;
2333             do {
2334                 ret =
2335                     wl_display_dispatch_queue(ctx->wl.display, ctx->wl.queue);
2336             } while ((ret != -1) && !ctx_scrshot.isshotdone);
2337 
2338             returnValue = ctx_scrshot.result;
2339         }
2340     }
2341     unlock_context(ctx);
2342 
2343     return returnValue;
2344 }
2345 
2346 ILM_EXPORT ilmErrorTypes
ilm_takeScreenshot(t_ilm_uint screen,t_ilm_const_string filename)2347 ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
2348 {
2349     ilmErrorTypes returnValue = ILM_FAILED;
2350     struct ilm_control_context *const ctx = &ilm_context;
2351     struct screen_context *ctx_scrn = NULL;
2352 
2353     lock_context(ctx);
2354     ctx_scrn = get_screen_context_by_id(&ctx->wl, (uint32_t)screen);
2355     if (ctx_scrn != NULL) {
2356         struct screenshot_context ctx_scrshot = {
2357             .filename = filename,
2358             .result = ILM_FAILED,
2359         };
2360 
2361         struct ivi_screenshot *scrshot =
2362             ivi_wm_screen_screenshot(ctx_scrn->controller);
2363         if (scrshot) {
2364             ivi_screenshot_add_listener(scrshot, &screenshot_listener,
2365                                         &ctx_scrshot);
2366             // dispatch until filename has been reset in done or error callback
2367             int ret;
2368             do {
2369                 ret =
2370                     wl_display_dispatch_queue(ctx->wl.display, ctx->wl.queue);
2371             } while ((ret != -1) && ctx_scrshot.filename);
2372 
2373             returnValue = ctx_scrshot.result;
2374         }
2375     }
2376     unlock_context(ctx);
2377 
2378     return returnValue;
2379 }
2380 
2381 ILM_EXPORT ilmErrorTypes
ilm_takeSurfaceScreenshot(t_ilm_const_string filename,t_ilm_surface surfaceid)2382 ilm_takeSurfaceScreenshot(t_ilm_const_string filename,
2383                               t_ilm_surface surfaceid)
2384 {
2385     ilmErrorTypes returnValue = ILM_FAILED;
2386     struct ilm_control_context *const ctx = &ilm_context;
2387 
2388     lock_context(ctx);
2389     if (ctx->wl.controller) {
2390           struct screenshot_context ctx_scrshot = {
2391             .filename = filename,
2392             .result = ILM_FAILED,
2393         };
2394 
2395         struct ivi_screenshot *scrshot =
2396             ivi_wm_surface_screenshot(ctx->wl.controller, surfaceid);
2397         if (scrshot) {
2398             ivi_screenshot_add_listener(scrshot, &screenshot_listener,
2399                                         &ctx_scrshot);
2400             // dispatch until filename has been reset in done or error callback
2401             int ret;
2402             do {
2403                 ret =
2404                     wl_display_dispatch_queue(ctx->wl.display, ctx->wl.queue);
2405             } while ((ret != -1) && ctx_scrshot.filename);
2406 
2407             returnValue = ctx_scrshot.result;
2408         }
2409     }
2410     unlock_context(ctx);
2411 
2412     return returnValue;
2413 }
2414 
2415 ILM_EXPORT ilmErrorTypes
ilm_layerAddNotification(t_ilm_layer layer,layerNotificationFunc callback)2416 ilm_layerAddNotification(t_ilm_layer layer,
2417                              layerNotificationFunc callback)
2418 {
2419     ilmErrorTypes returnValue = ILM_FAILED;
2420     struct ilm_control_context *ctx = sync_and_acquire_instance();
2421     struct layer_context *ctx_layer = NULL;
2422 
2423     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2424                     &ctx->wl, (uint32_t)layer);
2425     if (ctx_layer == NULL) {
2426         returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2427     } else {
2428         ctx_layer->notification = callback;
2429         ivi_wm_layer_sync(ctx->wl.controller, layer, IVI_WM_SYNC_ADD);
2430         if (wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) == -1)
2431             fprintf(stderr, "wl_display_roundtrip queue failed\n");
2432 
2433         returnValue = ILM_SUCCESS;
2434     }
2435 
2436     release_instance();
2437     return returnValue;
2438 }
2439 
2440 ILM_EXPORT ilmErrorTypes
ilm_layerRemoveNotification(t_ilm_layer layer)2441 ilm_layerRemoveNotification(t_ilm_layer layer)
2442 {
2443     ilmErrorTypes returnValue = ILM_FAILED;
2444     struct ilm_control_context *ctx = sync_and_acquire_instance();
2445     struct layer_context *ctx_layer = NULL;
2446 
2447     ctx_layer = (struct layer_context*)wayland_controller_get_layer_context(
2448                     &ctx->wl, (uint32_t)layer);
2449     if (ctx_layer != NULL) {
2450         if (ctx_layer->notification != NULL) {
2451             ivi_wm_layer_sync(ctx->wl.controller, layer, IVI_WM_SYNC_REMOVE);
2452             wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
2453 
2454             ctx_layer->notification = NULL;
2455             returnValue = ILM_SUCCESS;
2456         } else {
2457             returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2458         }
2459     }
2460 
2461     release_instance();
2462     return returnValue;
2463 }
2464 
2465 static struct surface_context *
create_surface_context(struct wayland_context * ctx,uint32_t id_surface)2466 create_surface_context(struct wayland_context *ctx, uint32_t id_surface)
2467 {
2468     struct surface_context *ctx_surf = NULL;
2469 
2470     ctx_surf = calloc(1, sizeof *ctx_surf);
2471     if (ctx_surf == NULL) {
2472         fprintf(stderr, "Failed to allocate memory for surface_context\n");
2473         return NULL;
2474     }
2475 
2476     ctx_surf->id_surface = id_surface;
2477     ctx_surf->ctx = ctx;
2478 
2479     wl_list_insert(&ctx->list_surface, &ctx_surf->link);
2480     wl_list_init(&ctx_surf->list_accepted_seats);
2481 
2482     return ctx_surf;
2483 }
2484 
2485 ILM_EXPORT ilmErrorTypes
ilm_registerNotification(notificationFunc callback,void * user_data)2486 ilm_registerNotification(notificationFunc callback, void *user_data)
2487 {
2488     struct ilm_control_context *ctx = sync_and_acquire_instance();
2489     struct layer_context *ctx_layer = NULL;
2490     struct surface_context *ctx_surf = NULL;
2491 
2492     ctx->wl.notification = callback;
2493     ctx->wl.notification_user_data = user_data;
2494     if (callback != NULL) {
2495         wl_list_for_each(ctx_layer, &ctx->wl.list_layer, link) {
2496             callback(ILM_LAYER, ctx_layer->id_layer, ILM_TRUE, user_data);
2497         }
2498 
2499         wl_list_for_each(ctx_surf, &ctx->wl.list_surface, link) {
2500             callback(ILM_SURFACE, ctx_surf->id_surface, ILM_TRUE, user_data);
2501         }
2502     }
2503     release_instance();
2504     return ILM_SUCCESS;
2505 }
2506 
2507 ILM_EXPORT ilmErrorTypes
ilm_unregisterNotification(void)2508 ilm_unregisterNotification(void)
2509 {
2510    return ilm_registerNotification(NULL, NULL);
2511 }
2512 
2513 ILM_EXPORT ilmErrorTypes
ilm_surfaceAddNotification(t_ilm_surface surface,surfaceNotificationFunc callback)2514 ilm_surfaceAddNotification(t_ilm_surface surface,
2515                              surfaceNotificationFunc callback)
2516 {
2517     ilmErrorTypes returnValue = ILM_FAILED;
2518     struct ilm_control_context *ctx = sync_and_acquire_instance();
2519     struct surface_context *ctx_surf = NULL;
2520 
2521     ctx_surf = (struct surface_context*)get_surface_context(
2522                     &ctx->wl, (uint32_t)surface);
2523 
2524     if (ctx_surf == NULL) {
2525         if (callback != NULL) {
2526             callback((uint32_t)surface, NULL, ILM_NOTIFICATION_CONTENT_REMOVED);
2527             ctx_surf = create_surface_context(&ctx->wl, (uint32_t)surface);
2528         }
2529     }
2530     else {
2531         if (callback != NULL) {
2532             ctx_surf->notification = callback;
2533             ivi_wm_surface_sync(ctx->wl.controller, surface, IVI_WM_SYNC_ADD);
2534             if (wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) == -1)
2535                 fprintf(stderr, "wl_display_roundtrip queue failed\n");
2536 
2537             callback(ctx_surf->id_surface,
2538                      &ctx_surf->prop, ILM_NOTIFICATION_CONTENT_AVAILABLE);
2539         }
2540     }
2541 
2542     if (ctx_surf == NULL) {
2543         returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2544     }
2545     else {
2546         ctx_surf->notification = callback;
2547         returnValue = ILM_SUCCESS;
2548     }
2549 
2550     release_instance();
2551     return returnValue;
2552 }
2553 
2554 ILM_EXPORT ilmErrorTypes
ilm_surfaceRemoveNotification(t_ilm_surface surface)2555 ilm_surfaceRemoveNotification(t_ilm_surface surface)
2556 {
2557     ilmErrorTypes returnValue = ILM_FAILED;
2558     struct ilm_control_context *ctx = sync_and_acquire_instance();
2559     struct surface_context *ctx_surf = NULL;
2560 
2561     ctx_surf = (struct surface_context*)get_surface_context(
2562                     &ctx->wl, (uint32_t)surface);
2563     if (ctx_surf != NULL) {
2564         if (ctx_surf->notification != NULL) {
2565             ivi_wm_surface_sync(ctx->wl.controller, surface, IVI_WM_SYNC_REMOVE);
2566             wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
2567 
2568             ctx_surf->notification = NULL;
2569             returnValue = ILM_SUCCESS;
2570         } else {
2571             returnValue = ILM_ERROR_INVALID_ARGUMENTS;
2572         }
2573     }
2574 
2575     release_instance();
2576     return returnValue;
2577 }
2578 
2579 ILM_EXPORT ilmErrorTypes
ilm_getPropertiesOfSurface(t_ilm_uint surfaceID,struct ilmSurfaceProperties * pSurfaceProperties)2580 ilm_getPropertiesOfSurface(t_ilm_uint surfaceID,
2581                         struct ilmSurfaceProperties* pSurfaceProperties)
2582 {
2583     ilmErrorTypes returnValue = ILM_FAILED;
2584     struct ilm_control_context *const ctx = &ilm_context;
2585     struct surface_context *ctx_surface = NULL;
2586     int32_t mask = 0;
2587 
2588     mask |= IVI_WM_PARAM_OPACITY;
2589     mask |= IVI_WM_PARAM_VISIBILITY;
2590     mask |= IVI_WM_PARAM_SIZE;
2591 
2592     if (pSurfaceProperties != NULL) {
2593         lock_context(ctx);
2594 
2595         ivi_wm_surface_get(ctx->wl.controller, surfaceID, mask);
2596         int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
2597 
2598         ctx_surface = get_surface_context(&ctx->wl, (uint32_t)surfaceID);
2599 
2600         if ((ret != -1) && (ctx_surface != NULL))
2601         {
2602             *pSurfaceProperties = ctx_surface->prop;
2603             returnValue = ILM_SUCCESS;
2604         }
2605 
2606         unlock_context(ctx);
2607     }
2608 
2609     return returnValue;
2610 }
2611 
2612 ILM_EXPORT ilmErrorTypes
ilm_layerAddSurface(t_ilm_layer layerId,t_ilm_surface surfaceId)2613 ilm_layerAddSurface(t_ilm_layer layerId,
2614                         t_ilm_surface surfaceId)
2615 {
2616     ilmErrorTypes returnValue = ILM_FAILED;
2617     struct ilm_control_context *const ctx = &ilm_context;
2618 
2619     lock_context(ctx);
2620     if (ctx->wl.controller) {
2621         ivi_wm_layer_add_surface(ctx->wl.controller, layerId, surfaceId);
2622         wl_display_flush(ctx->wl.display);
2623         returnValue = ILM_SUCCESS;
2624     }
2625     unlock_context(ctx);
2626 
2627     return returnValue;
2628 }
2629 
2630 ILM_EXPORT ilmErrorTypes
ilm_layerRemoveSurface(t_ilm_layer layerId,t_ilm_surface surfaceId)2631 ilm_layerRemoveSurface(t_ilm_layer layerId,
2632                            t_ilm_surface surfaceId)
2633 {
2634     ilmErrorTypes returnValue = ILM_FAILED;
2635     struct ilm_control_context *const ctx = &ilm_context;
2636 
2637     lock_context(ctx);
2638     if (ctx->wl.controller) {
2639         ivi_wm_layer_remove_surface(ctx->wl.controller, layerId, surfaceId);
2640         wl_display_flush(ctx->wl.display);
2641         returnValue = ILM_SUCCESS;
2642     }
2643     unlock_context(ctx);
2644 
2645     return returnValue;
2646 }
2647 
2648 ILM_EXPORT ilmErrorTypes
ilm_surfaceGetVisibility(t_ilm_surface surfaceId,t_ilm_bool * pVisibility)2649 ilm_surfaceGetVisibility(t_ilm_surface surfaceId,
2650                              t_ilm_bool *pVisibility)
2651 {
2652     ilmErrorTypes returnValue = ILM_FAILED;
2653     struct ilm_control_context *const ctx = &ilm_context;
2654     struct surface_context *ctx_surf = NULL;
2655 
2656     if (pVisibility != NULL) {
2657         lock_context(ctx);
2658 
2659         ivi_wm_surface_get(ctx->wl.controller, surfaceId, IVI_WM_PARAM_VISIBILITY);
2660         int ret = wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue);
2661 
2662         ctx_surf = get_surface_context(&ctx->wl, (uint32_t)surfaceId);
2663 
2664         if ((ret != -1) && (ctx_surf != NULL))
2665         {
2666             *pVisibility = (t_ilm_bool)ctx_surf->prop.visibility;
2667             returnValue = ILM_SUCCESS;
2668         }
2669 
2670         unlock_context(ctx);
2671     }
2672 
2673     return returnValue;
2674 }
2675 
2676 ILM_EXPORT ilmErrorTypes
ilm_surfaceSetSourceRectangle(t_ilm_surface surfaceId,t_ilm_int x,t_ilm_int y,t_ilm_int width,t_ilm_int height)2677 ilm_surfaceSetSourceRectangle(t_ilm_surface surfaceId,
2678                                   t_ilm_int x, t_ilm_int y,
2679                                   t_ilm_int width, t_ilm_int height)
2680 {
2681     ilmErrorTypes returnValue = ILM_FAILED;
2682     struct ilm_control_context *const ctx = &ilm_context;
2683 
2684 
2685     lock_context(ctx);
2686     if (ctx->wl.controller) {
2687         ivi_wm_set_surface_source_rectangle(ctx->wl.controller, surfaceId, x, y,
2688                                             width, height);
2689         wl_display_flush(ctx->wl.display);
2690         returnValue = ILM_SUCCESS;
2691     }
2692     unlock_context(ctx);
2693 
2694     return returnValue;
2695 }
2696 
2697 ILM_EXPORT ilmErrorTypes
ilm_commitChanges(void)2698 ilm_commitChanges(void)
2699 {
2700     ilmErrorTypes returnValue = ILM_FAILED;
2701     struct ilm_control_context *const ctx = &ilm_context;
2702 
2703     lock_context(ctx);
2704     if (ctx->wl.controller) {
2705         ivi_wm_commit_changes(ctx->wl.controller);
2706         wl_display_flush(ctx->wl.display);
2707         if (wl_display_flush (ctx->wl.display) != -1)
2708         {
2709             returnValue = ILM_SUCCESS;
2710         }
2711     }
2712     unlock_context(ctx);
2713 
2714     return returnValue;
2715 }
2716 
2717 ILM_EXPORT ilmErrorTypes
ilm_getError(void)2718 ilm_getError(void)
2719 {
2720     ilmErrorTypes returnValue = ILM_FAILED;
2721     struct ilm_control_context *const ctx = &ilm_context;
2722 
2723     lock_context(ctx);
2724     if (ctx->wl.controller) {
2725         if (wl_display_roundtrip_queue(ctx->wl.display, ctx->wl.queue) != -1)
2726         {
2727             returnValue = ctx->wl.error_flag;
2728             ctx->wl.error_flag = ILM_SUCCESS;
2729         }
2730     }
2731     unlock_context(ctx);
2732 
2733     return returnValue;
2734 }
2735