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 ®istry_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