924e79f4f2
Without this, the earliest signal the ivi controller receives for a new surface is configure_desktop_changed signal. And this is not emitted until the surface has the first buffer attached. By emitting the signal during surface creation, the controller is able to set the initial width and height for the first configure. Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2148 lines
59 KiB
C
2148 lines
59 KiB
C
/*
|
|
* Copyright (C) 2013 DENSO CORPORATION
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the
|
|
* next paragraph) shall be included in all copies or substantial
|
|
* portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
/**
|
|
* Implementation of ivi-layout library. The actual view on ivi_screen is
|
|
* not updated until ivi_layout_commit_changes is called. An overview from
|
|
* calling API for updating properties of ivi_surface/ivi_layer to asking
|
|
* compositor to compose them by using weston_view_schedule_repaint,
|
|
* 0/ initialize this library by ivi_layout_init_with_compositor
|
|
* with (struct weston_compositor *ec) from ivi-shell.
|
|
* 1/ When an API for updating properties of ivi_surface/ivi_layer, it updates
|
|
* pending prop of ivi_surface/ivi_layer/ivi_screen which are structure to
|
|
* store properties.
|
|
* 2/ Before calling commitChanges, in case of calling an API to get a property,
|
|
* return current property, not pending property.
|
|
* 3/ At the timing of calling ivi_layout_commitChanges, pending properties
|
|
* are applied to properties.
|
|
*
|
|
* *) ivi_layout_commitChanges is also called by transition animation
|
|
* per each frame. See ivi-layout-transition.c in details. Transition
|
|
* animation interpolates frames between previous properties of ivi_surface
|
|
* and new ones.
|
|
* For example, when a property of ivi_surface is changed from invisible
|
|
* to visible, it behaves like fade-in. When ivi_layout_commitChange is
|
|
* called during transition animation, it cancels the transition and
|
|
* re-start transition to new properties from current properties of final
|
|
* frame just before the cancellation.
|
|
*
|
|
* 4/ According properties, set transformation by using weston_matrix and
|
|
* weston_view per ivi_surfaces and ivi_layers in while loop.
|
|
* 5/ Set damage and trigger transform by using weston_view_geometry_dirty.
|
|
* 6/ Schedule repaint for each view by using weston_view_schedule_repaint.
|
|
* 7/ Notify update of properties.
|
|
*
|
|
*/
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
|
|
#include "compositor/weston.h"
|
|
#include <libweston/libweston.h>
|
|
#include "ivi-shell.h"
|
|
#include "ivi-layout-export.h"
|
|
#include "ivi-layout-private.h"
|
|
#include "ivi-layout-shell.h"
|
|
|
|
#include "shared/helpers.h"
|
|
#include "shared/os-compatibility.h"
|
|
|
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
struct ivi_layout;
|
|
|
|
struct ivi_layout_screen {
|
|
struct wl_list link; /* ivi_layout::screen_list */
|
|
|
|
struct ivi_layout *layout;
|
|
struct weston_output *output;
|
|
|
|
struct {
|
|
struct wl_list layer_list; /* ivi_layout_layer::pending.link */
|
|
} pending;
|
|
|
|
struct {
|
|
int dirty;
|
|
struct wl_list layer_list; /* ivi_layout_layer::order.link */
|
|
} order;
|
|
};
|
|
|
|
struct ivi_rectangle
|
|
{
|
|
int32_t x;
|
|
int32_t y;
|
|
int32_t width;
|
|
int32_t height;
|
|
};
|
|
|
|
static struct ivi_layout ivilayout = {0};
|
|
|
|
struct ivi_layout *
|
|
get_instance(void)
|
|
{
|
|
return &ivilayout;
|
|
}
|
|
|
|
/**
|
|
* Internal API to add/remove an ivi_layer to/from ivi_screen.
|
|
*/
|
|
static struct ivi_layout_surface *
|
|
get_surface(struct wl_list *surf_list, uint32_t id_surface)
|
|
{
|
|
struct ivi_layout_surface *ivisurf;
|
|
|
|
wl_list_for_each(ivisurf, surf_list, link) {
|
|
if (ivisurf->id_surface == id_surface) {
|
|
return ivisurf;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static struct ivi_layout_layer *
|
|
get_layer(struct wl_list *layer_list, uint32_t id_layer)
|
|
{
|
|
struct ivi_layout_layer *ivilayer;
|
|
|
|
wl_list_for_each(ivilayer, layer_list, link) {
|
|
if (ivilayer->id_layer == id_layer) {
|
|
return ivilayer;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static bool
|
|
ivi_view_is_rendered(struct ivi_layout_view *view)
|
|
{
|
|
return !wl_list_empty(&view->order_link);
|
|
}
|
|
|
|
static void
|
|
ivi_view_destroy(struct ivi_layout_view *ivi_view)
|
|
{
|
|
wl_list_remove(&ivi_view->transform.link);
|
|
wl_list_remove(&ivi_view->link);
|
|
wl_list_remove(&ivi_view->surf_link);
|
|
wl_list_remove(&ivi_view->pending_link);
|
|
wl_list_remove(&ivi_view->order_link);
|
|
|
|
if (weston_surface_is_desktop_surface(ivi_view->ivisurf->surface))
|
|
weston_desktop_surface_unlink_view(ivi_view->view);
|
|
weston_view_destroy(ivi_view->view);
|
|
|
|
free(ivi_view);
|
|
}
|
|
|
|
static struct ivi_layout_view*
|
|
ivi_view_create(struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface *ivisurf)
|
|
{
|
|
struct ivi_layout_view *ivi_view;
|
|
|
|
ivi_view = calloc(1, sizeof *ivi_view);
|
|
if (ivi_view == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return NULL;
|
|
}
|
|
|
|
if (weston_surface_is_desktop_surface(ivisurf->surface)) {
|
|
ivi_view->view = weston_desktop_surface_create_view(
|
|
ivisurf->weston_desktop_surface);
|
|
} else {
|
|
ivi_view->view = weston_view_create(ivisurf->surface);
|
|
}
|
|
|
|
if (ivi_view->view == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
free(ivi_view);
|
|
return NULL;
|
|
}
|
|
|
|
weston_matrix_init(&ivi_view->transform.matrix);
|
|
wl_list_init(&ivi_view->transform.link);
|
|
|
|
ivi_view->ivisurf = ivisurf;
|
|
ivi_view->on_layer = ivilayer;
|
|
wl_list_insert(&ivilayer->layout->view_list,
|
|
&ivi_view->link);
|
|
wl_list_insert(&ivisurf->view_list,
|
|
&ivi_view->surf_link);
|
|
|
|
wl_list_init(&ivi_view->pending_link);
|
|
wl_list_init(&ivi_view->order_link);
|
|
|
|
return ivi_view;
|
|
}
|
|
|
|
static struct ivi_layout_view *
|
|
get_ivi_view(struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface *ivisurf)
|
|
{
|
|
struct ivi_layout_view *ivi_view;
|
|
|
|
assert(ivisurf->surface != NULL);
|
|
|
|
wl_list_for_each(ivi_view, &ivisurf->view_list, surf_link) {
|
|
if (ivi_view->on_layer == ivilayer)
|
|
return ivi_view;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static struct ivi_layout_screen *
|
|
get_screen_from_output(struct weston_output *output)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_screen *iviscrn = NULL;
|
|
|
|
wl_list_for_each(iviscrn, &layout->screen_list, link) {
|
|
if (iviscrn->output == output)
|
|
return iviscrn;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Called at destruction of wl_surface/ivi_surface
|
|
*/
|
|
void
|
|
ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_view *ivi_view ,*next;
|
|
|
|
if (ivisurf == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return;
|
|
}
|
|
|
|
wl_list_remove(&ivisurf->link);
|
|
|
|
wl_list_for_each_safe(ivi_view, next, &ivisurf->view_list, surf_link) {
|
|
ivi_view_destroy(ivi_view);
|
|
}
|
|
|
|
wl_signal_emit(&layout->surface_notification.removed, ivisurf);
|
|
|
|
ivi_layout_remove_all_surface_transitions(ivisurf);
|
|
|
|
free(ivisurf);
|
|
}
|
|
|
|
/**
|
|
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
|
|
* Called by ivi_layout_init_with_compositor.
|
|
*/
|
|
static void
|
|
create_screen(struct weston_compositor *ec)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_screen *iviscrn = NULL;
|
|
struct weston_output *output = NULL;
|
|
|
|
wl_list_for_each(output, &ec->output_list, link) {
|
|
iviscrn = calloc(1, sizeof *iviscrn);
|
|
if (iviscrn == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
continue;
|
|
}
|
|
|
|
iviscrn->layout = layout;
|
|
|
|
iviscrn->output = output;
|
|
|
|
wl_list_init(&iviscrn->pending.layer_list);
|
|
|
|
wl_list_init(&iviscrn->order.layer_list);
|
|
|
|
wl_list_insert(&layout->screen_list, &iviscrn->link);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Internal APIs to initialize properties of ivi_surface/ivi_layer when they are created.
|
|
*/
|
|
static void
|
|
init_layer_properties(struct ivi_layout_layer_properties *prop,
|
|
int32_t width, int32_t height)
|
|
{
|
|
memset(prop, 0, sizeof *prop);
|
|
prop->opacity = wl_fixed_from_double(1.0);
|
|
prop->source_width = width;
|
|
prop->source_height = height;
|
|
prop->dest_width = width;
|
|
prop->dest_height = height;
|
|
}
|
|
|
|
static void
|
|
init_surface_properties(struct ivi_layout_surface_properties *prop)
|
|
{
|
|
memset(prop, 0, sizeof *prop);
|
|
prop->opacity = wl_fixed_from_double(1.0);
|
|
/*
|
|
* FIXME: this shall be fixed by ivi-layout-transition.
|
|
*/
|
|
prop->dest_width = 1;
|
|
prop->dest_height = 1;
|
|
}
|
|
|
|
/**
|
|
* Internal APIs to be called from ivi_layout_commit_changes.
|
|
*/
|
|
static void
|
|
update_opacity(struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface *ivisurf,
|
|
struct weston_view *view)
|
|
{
|
|
double layer_alpha = wl_fixed_to_double(ivilayer->prop.opacity);
|
|
double surf_alpha = wl_fixed_to_double(ivisurf->prop.opacity);
|
|
|
|
view->alpha = layer_alpha * surf_alpha;
|
|
}
|
|
|
|
static void
|
|
calc_transformation_matrix(struct ivi_rectangle *source_rect,
|
|
struct ivi_rectangle *dest_rect,
|
|
struct weston_matrix *m)
|
|
{
|
|
float source_center_x;
|
|
float source_center_y;
|
|
float scale_x;
|
|
float scale_y;
|
|
float translate_x;
|
|
float translate_y;
|
|
|
|
source_center_x = source_rect->x + source_rect->width * 0.5f;
|
|
source_center_y = source_rect->y + source_rect->height * 0.5f;
|
|
weston_matrix_translate(m, -source_center_x, -source_center_y, 0.0f);
|
|
|
|
if ((dest_rect->width != source_rect->width) ||
|
|
(dest_rect->height != source_rect->height))
|
|
{
|
|
scale_x = (float) dest_rect->width / (float) source_rect->width;
|
|
scale_y = (float) dest_rect->height / (float) source_rect->height;
|
|
weston_matrix_scale(m, scale_x, scale_y, 1.0f);
|
|
}
|
|
|
|
translate_x = dest_rect->width * 0.5f + dest_rect->x;
|
|
translate_y = dest_rect->height * 0.5f + dest_rect->y;
|
|
weston_matrix_translate(m, translate_x, translate_y, 0.0f);
|
|
}
|
|
|
|
/*
|
|
* This computes intersected rect_output from two ivi_rectangles
|
|
*/
|
|
static void
|
|
ivi_rectangle_intersect(const struct ivi_rectangle *rect1,
|
|
const struct ivi_rectangle *rect2,
|
|
struct ivi_rectangle *rect_output)
|
|
{
|
|
int32_t rect1_right = rect1->x + rect1->width;
|
|
int32_t rect1_bottom = rect1->y + rect1->height;
|
|
int32_t rect2_right = rect2->x + rect2->width;
|
|
int32_t rect2_bottom = rect2->y + rect2->height;
|
|
|
|
rect_output->x = max(rect1->x, rect2->x);
|
|
rect_output->y = max(rect1->y, rect2->y);
|
|
rect_output->width = rect1_right < rect2_right ?
|
|
rect1_right - rect_output->x :
|
|
rect2_right - rect_output->x;
|
|
rect_output->height = rect1_bottom < rect2_bottom ?
|
|
rect1_bottom - rect_output->y :
|
|
rect2_bottom - rect_output->y;
|
|
|
|
if (rect_output->width < 0 || rect_output->height < 0) {
|
|
rect_output->width = 0;
|
|
rect_output->height = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Transform rect_input by the inverse of matrix, intersect with boundingbox,
|
|
* and store the result in rect_output.
|
|
* The boundingbox must be given in the same coordinate space as rect_output.
|
|
* Additionally, there are the following restrictions on the matrix:
|
|
* - no projective transformations
|
|
* - no skew
|
|
* - only multiples of 90-degree rotations supported
|
|
*
|
|
* In failure case of weston_matrix_invert, rect_output is set to boundingbox
|
|
* as a fail-safe with log.
|
|
*/
|
|
static void
|
|
calc_inverse_matrix_transform(const struct weston_matrix *matrix,
|
|
const struct ivi_rectangle *rect_input,
|
|
const struct ivi_rectangle *boundingbox,
|
|
struct ivi_rectangle *rect_output)
|
|
{
|
|
struct weston_matrix m;
|
|
struct weston_vector top_left;
|
|
struct weston_vector bottom_right;
|
|
|
|
assert(boundingbox != rect_output);
|
|
|
|
if (weston_matrix_invert(&m, matrix) < 0) {
|
|
weston_log("ivi-shell: calc_inverse_matrix_transform fails to invert a matrix.\n");
|
|
weston_log("ivi-shell: boundingbox is set to the rect_output.\n");
|
|
rect_output->x = boundingbox->x;
|
|
rect_output->y = boundingbox->y;
|
|
rect_output->width = boundingbox->width;
|
|
rect_output->height = boundingbox->height;
|
|
}
|
|
|
|
/* The vectors and matrices involved will always produce f[3] == 1.0. */
|
|
top_left.f[0] = rect_input->x;
|
|
top_left.f[1] = rect_input->y;
|
|
top_left.f[2] = 0.0f;
|
|
top_left.f[3] = 1.0f;
|
|
|
|
bottom_right.f[0] = rect_input->x + rect_input->width;
|
|
bottom_right.f[1] = rect_input->y + rect_input->height;
|
|
bottom_right.f[2] = 0.0f;
|
|
bottom_right.f[3] = 1.0f;
|
|
|
|
weston_matrix_transform(&m, &top_left);
|
|
weston_matrix_transform(&m, &bottom_right);
|
|
|
|
if (top_left.f[0] < bottom_right.f[0]) {
|
|
rect_output->x = top_left.f[0];
|
|
rect_output->width = bottom_right.f[0] - rect_output->x;
|
|
} else {
|
|
rect_output->x = bottom_right.f[0];
|
|
rect_output->width = top_left.f[0] - rect_output->x;
|
|
}
|
|
|
|
if (top_left.f[1] < bottom_right.f[1]) {
|
|
rect_output->y = top_left.f[1];
|
|
rect_output->height = bottom_right.f[1] - rect_output->y;
|
|
} else {
|
|
rect_output->y = bottom_right.f[1];
|
|
rect_output->height = top_left.f[1] - rect_output->y;
|
|
}
|
|
|
|
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
|
|
}
|
|
|
|
/**
|
|
* This computes the whole transformation matrix:m from surface-local
|
|
* coordinates to multi-screen coordinates, which are global coordinates.
|
|
* It is assumed that weston_view::geometry.{x,y} are zero.
|
|
*
|
|
* Additionally, this computes the mask on surface-local coordinates as an
|
|
* ivi_rectangle. This can be set to weston_view_set_mask.
|
|
*
|
|
* The mask is computed by following steps
|
|
* - destination rectangle of layer is transformed to multi-screen coordinates,
|
|
* global coordinates. This is done by adding weston_output.{x,y} in simple
|
|
* because there is no scaled and rotated transformation.
|
|
* - destination rectangle of layer in multi-screen coordinates needs to be
|
|
* intersected inside of a screen the layer is assigned to. This is because
|
|
* overlapped region of weston surface in another screen shall not be
|
|
* displayed according to ivi use case.
|
|
* - destination rectangle of layer
|
|
* - in multi-screen coordinates,
|
|
* - and intersected inside of an assigned screen,
|
|
* is inversed to surface-local coordinates by inversed matrix:m.
|
|
* - the area is intersected by intersected area between weston_surface and
|
|
* source rectangle of ivi_surface.
|
|
*/
|
|
static void
|
|
calc_surface_to_global_matrix_and_mask_to_weston_surface(
|
|
struct ivi_layout_screen *iviscrn,
|
|
struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface *ivisurf,
|
|
struct weston_matrix *m,
|
|
struct ivi_rectangle *result)
|
|
{
|
|
const struct ivi_layout_surface_properties *sp = &ivisurf->prop;
|
|
const struct ivi_layout_layer_properties *lp = &ivilayer->prop;
|
|
struct weston_output *output = iviscrn->output;
|
|
struct ivi_rectangle weston_surface_rect = { 0,
|
|
0,
|
|
ivisurf->surface->width,
|
|
ivisurf->surface->height };
|
|
struct ivi_rectangle surface_source_rect = { sp->source_x,
|
|
sp->source_y,
|
|
sp->source_width,
|
|
sp->source_height };
|
|
struct ivi_rectangle surface_dest_rect = { sp->dest_x,
|
|
sp->dest_y,
|
|
sp->dest_width,
|
|
sp->dest_height };
|
|
struct ivi_rectangle layer_source_rect = { lp->source_x,
|
|
lp->source_y,
|
|
lp->source_width,
|
|
lp->source_height };
|
|
struct ivi_rectangle layer_dest_rect = { lp->dest_x,
|
|
lp->dest_y,
|
|
lp->dest_width,
|
|
lp->dest_height };
|
|
struct ivi_rectangle screen_dest_rect = { output->x,
|
|
output->y,
|
|
output->width,
|
|
output->height };
|
|
struct ivi_rectangle layer_dest_rect_in_global =
|
|
{ lp->dest_x + output->x,
|
|
lp->dest_y + output->y,
|
|
lp->dest_width,
|
|
lp->dest_height };
|
|
struct ivi_rectangle surface_result;
|
|
struct ivi_rectangle layer_dest_rect_in_global_intersected;
|
|
|
|
/*
|
|
* the whole transformation matrix:m from surface-local
|
|
* coordinates to global coordinates, which is computed by
|
|
* two steps,
|
|
* - surface-local coordinates to layer-local coordinates
|
|
* - layer-local coordinates to single screen-local coordinates
|
|
* - single screen-local coordinates to multi-screen coordinates,
|
|
* which are global coordinates.
|
|
*/
|
|
calc_transformation_matrix(&surface_source_rect, &surface_dest_rect, m);
|
|
calc_transformation_matrix(&layer_source_rect, &layer_dest_rect, m);
|
|
|
|
weston_matrix_translate(m, output->x, output->y, 0.0f);
|
|
|
|
/* this intersected ivi_rectangle would be used for masking
|
|
* weston_surface
|
|
*/
|
|
ivi_rectangle_intersect(&surface_source_rect, &weston_surface_rect,
|
|
&surface_result);
|
|
|
|
/*
|
|
* destination rectangle of layer in multi screens coordinate
|
|
* is intersected to avoid displaying outside of an assigned screen.
|
|
*/
|
|
ivi_rectangle_intersect(&layer_dest_rect_in_global, &screen_dest_rect,
|
|
&layer_dest_rect_in_global_intersected);
|
|
|
|
/* calc masking area of weston_surface from m */
|
|
calc_inverse_matrix_transform(m,
|
|
&layer_dest_rect_in_global_intersected,
|
|
&surface_result,
|
|
result);
|
|
}
|
|
|
|
static void
|
|
update_prop(struct ivi_layout_view *ivi_view)
|
|
{
|
|
struct ivi_layout_surface *ivisurf = ivi_view->ivisurf;
|
|
struct ivi_layout_layer *ivilayer = ivi_view->on_layer;
|
|
struct ivi_layout_screen *iviscrn = ivilayer->on_screen;
|
|
struct ivi_rectangle r;
|
|
bool can_calc = true;
|
|
|
|
/*In case of no prop change, this just returns*/
|
|
if (!ivilayer->prop.event_mask && !ivisurf->prop.event_mask)
|
|
return;
|
|
|
|
update_opacity(ivilayer, ivisurf, ivi_view->view);
|
|
|
|
if (ivisurf->prop.source_width == 0 || ivisurf->prop.source_height == 0) {
|
|
weston_log("ivi-shell: source rectangle is not yet set by ivi_layout_surface_set_source_rectangle\n");
|
|
can_calc = false;
|
|
}
|
|
|
|
if (ivisurf->prop.dest_width == 0 || ivisurf->prop.dest_height == 0) {
|
|
weston_log("ivi-shell: destination rectangle is not yet set by ivi_layout_surface_set_destination_rectangle\n");
|
|
can_calc = false;
|
|
}
|
|
|
|
if (can_calc) {
|
|
wl_list_remove(&ivi_view->transform.link);
|
|
weston_matrix_init(&ivi_view->transform.matrix);
|
|
|
|
calc_surface_to_global_matrix_and_mask_to_weston_surface(
|
|
iviscrn, ivilayer, ivisurf, &ivi_view->transform.matrix, &r);
|
|
|
|
weston_view_set_mask(ivi_view->view, r.x, r.y, r.width, r.height);
|
|
wl_list_insert(&ivi_view->view->geometry.transformation_list,
|
|
&ivi_view->transform.link);
|
|
|
|
weston_view_set_transform_parent(ivi_view->view, NULL);
|
|
weston_view_geometry_dirty(ivi_view->view);
|
|
weston_view_update_transform(ivi_view->view);
|
|
}
|
|
|
|
ivisurf->update_count++;
|
|
|
|
weston_view_schedule_repaint(ivi_view->view);
|
|
}
|
|
|
|
static bool
|
|
ivi_view_is_mapped(struct ivi_layout_view *ivi_view)
|
|
{
|
|
return (!wl_list_empty(&ivi_view->order_link) &&
|
|
ivi_view->on_layer->on_screen &&
|
|
ivi_view->on_layer->prop.visibility &&
|
|
ivi_view->ivisurf->prop.visibility);
|
|
}
|
|
|
|
static void
|
|
commit_changes(struct ivi_layout *layout)
|
|
{
|
|
struct ivi_layout_view *ivi_view = NULL;
|
|
|
|
wl_list_for_each(ivi_view, &layout->view_list, link) {
|
|
/*
|
|
* If the view is not on the currently rendered scenegraph,
|
|
* we do not need to update its properties.
|
|
*/
|
|
if (!ivi_view_is_mapped(ivi_view))
|
|
continue;
|
|
|
|
update_prop(ivi_view);
|
|
}
|
|
}
|
|
|
|
static void
|
|
commit_surface_list(struct ivi_layout *layout)
|
|
{
|
|
struct ivi_layout_surface *ivisurf = NULL;
|
|
int32_t dest_x = 0;
|
|
int32_t dest_y = 0;
|
|
int32_t dest_width = 0;
|
|
int32_t dest_height = 0;
|
|
int32_t configured = 0;
|
|
|
|
wl_list_for_each(ivisurf, &layout->surface_list, link) {
|
|
if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEFAULT) {
|
|
dest_x = ivisurf->prop.dest_x;
|
|
dest_y = ivisurf->prop.dest_y;
|
|
dest_width = ivisurf->prop.dest_width;
|
|
dest_height = ivisurf->prop.dest_height;
|
|
|
|
ivi_layout_transition_move_resize_view(ivisurf,
|
|
ivisurf->pending.prop.dest_x,
|
|
ivisurf->pending.prop.dest_y,
|
|
ivisurf->pending.prop.dest_width,
|
|
ivisurf->pending.prop.dest_height,
|
|
ivisurf->pending.prop.transition_duration);
|
|
|
|
if (ivisurf->pending.prop.visibility) {
|
|
ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration);
|
|
} else {
|
|
ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration);
|
|
}
|
|
|
|
ivisurf->prop = ivisurf->pending.prop;
|
|
ivisurf->prop.dest_x = dest_x;
|
|
ivisurf->prop.dest_y = dest_y;
|
|
ivisurf->prop.dest_width = dest_width;
|
|
ivisurf->prop.dest_height = dest_height;
|
|
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
|
|
} else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_DEST_RECT_ONLY) {
|
|
dest_x = ivisurf->prop.dest_x;
|
|
dest_y = ivisurf->prop.dest_y;
|
|
dest_width = ivisurf->prop.dest_width;
|
|
dest_height = ivisurf->prop.dest_height;
|
|
|
|
ivi_layout_transition_move_resize_view(ivisurf,
|
|
ivisurf->pending.prop.dest_x,
|
|
ivisurf->pending.prop.dest_y,
|
|
ivisurf->pending.prop.dest_width,
|
|
ivisurf->pending.prop.dest_height,
|
|
ivisurf->pending.prop.transition_duration);
|
|
|
|
ivisurf->prop = ivisurf->pending.prop;
|
|
ivisurf->prop.dest_x = dest_x;
|
|
ivisurf->prop.dest_y = dest_y;
|
|
ivisurf->prop.dest_width = dest_width;
|
|
ivisurf->prop.dest_height = dest_height;
|
|
|
|
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
|
|
} else if (ivisurf->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_VIEW_FADE_ONLY) {
|
|
configured = 0;
|
|
if (ivisurf->pending.prop.visibility) {
|
|
ivi_layout_transition_visibility_on(ivisurf, ivisurf->pending.prop.transition_duration);
|
|
} else {
|
|
ivi_layout_transition_visibility_off(ivisurf, ivisurf->pending.prop.transition_duration);
|
|
}
|
|
|
|
if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width ||
|
|
ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) {
|
|
configured = 1;
|
|
}
|
|
|
|
ivisurf->prop = ivisurf->pending.prop;
|
|
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
|
|
if (configured && !is_surface_transition(ivisurf)) {
|
|
ivi_layout_surface_set_size(ivisurf,
|
|
ivisurf->prop.dest_width,
|
|
ivisurf->prop.dest_height);
|
|
}
|
|
} else {
|
|
configured = 0;
|
|
if (ivisurf->prop.dest_width != ivisurf->pending.prop.dest_width ||
|
|
ivisurf->prop.dest_height != ivisurf->pending.prop.dest_height) {
|
|
configured = 1;
|
|
}
|
|
|
|
ivisurf->prop = ivisurf->pending.prop;
|
|
ivisurf->prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
|
|
if (configured && !is_surface_transition(ivisurf)) {
|
|
ivi_layout_surface_set_size(ivisurf,
|
|
ivisurf->prop.dest_width,
|
|
ivisurf->prop.dest_height);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
commit_layer_list(struct ivi_layout *layout)
|
|
{
|
|
struct ivi_layout_view *ivi_view = NULL;
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
struct ivi_layout_view *next = NULL;
|
|
|
|
wl_list_for_each(ivilayer, &layout->layer_list, link) {
|
|
if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_MOVE) {
|
|
ivi_layout_transition_move_layer(ivilayer, ivilayer->pending.prop.dest_x, ivilayer->pending.prop.dest_y, ivilayer->pending.prop.transition_duration);
|
|
} else if (ivilayer->pending.prop.transition_type == IVI_LAYOUT_TRANSITION_LAYER_FADE) {
|
|
ivi_layout_transition_fade_layer(ivilayer,ivilayer->pending.prop.is_fade_in,
|
|
ivilayer->pending.prop.start_alpha,ivilayer->pending.prop.end_alpha,
|
|
NULL, NULL,
|
|
ivilayer->pending.prop.transition_duration);
|
|
}
|
|
ivilayer->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE;
|
|
|
|
ivilayer->prop = ivilayer->pending.prop;
|
|
|
|
if (!ivilayer->order.dirty) {
|
|
continue;
|
|
}
|
|
|
|
wl_list_for_each_safe(ivi_view, next, &ivilayer->order.view_list,
|
|
order_link) {
|
|
wl_list_remove(&ivi_view->order_link);
|
|
wl_list_init(&ivi_view->order_link);
|
|
ivi_view->ivisurf->prop.event_mask |= IVI_NOTIFICATION_REMOVE;
|
|
}
|
|
|
|
assert(wl_list_empty(&ivilayer->order.view_list));
|
|
|
|
wl_list_for_each(ivi_view, &ivilayer->pending.view_list,
|
|
pending_link) {
|
|
wl_list_remove(&ivi_view->order_link);
|
|
wl_list_insert(&ivilayer->order.view_list, &ivi_view->order_link);
|
|
ivi_view->ivisurf->prop.event_mask |= IVI_NOTIFICATION_ADD;
|
|
}
|
|
|
|
ivilayer->order.dirty = 0;
|
|
}
|
|
}
|
|
|
|
static void
|
|
commit_screen_list(struct ivi_layout *layout)
|
|
{
|
|
struct ivi_layout_screen *iviscrn = NULL;
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
struct ivi_layout_layer *next = NULL;
|
|
|
|
wl_list_for_each(iviscrn, &layout->screen_list, link) {
|
|
if (iviscrn->order.dirty) {
|
|
wl_list_for_each_safe(ivilayer, next,
|
|
&iviscrn->order.layer_list, order.link) {
|
|
ivilayer->on_screen = NULL;
|
|
wl_list_remove(&ivilayer->order.link);
|
|
wl_list_init(&ivilayer->order.link);
|
|
ivilayer->prop.event_mask |= IVI_NOTIFICATION_REMOVE;
|
|
}
|
|
|
|
assert(wl_list_empty(&iviscrn->order.layer_list));
|
|
|
|
wl_list_for_each(ivilayer, &iviscrn->pending.layer_list,
|
|
pending.link) {
|
|
/* FIXME: avoid to insert order.link to multiple screens */
|
|
wl_list_remove(&ivilayer->order.link);
|
|
|
|
wl_list_insert(&iviscrn->order.layer_list,
|
|
&ivilayer->order.link);
|
|
ivilayer->on_screen = iviscrn;
|
|
ivilayer->prop.event_mask |= IVI_NOTIFICATION_ADD;
|
|
}
|
|
|
|
iviscrn->order.dirty = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
build_view_list(struct ivi_layout *layout)
|
|
{
|
|
struct ivi_layout_screen *iviscrn;
|
|
struct ivi_layout_layer *ivilayer;
|
|
struct ivi_layout_view *ivi_view;
|
|
|
|
/* If ivi_view is not part of the scenegrapgh, we have to unmap
|
|
* weston_views
|
|
*/
|
|
wl_list_for_each(ivi_view, &layout->view_list, link) {
|
|
if (!ivi_view_is_mapped(ivi_view))
|
|
weston_view_unmap(ivi_view->view);
|
|
}
|
|
|
|
/* Clear view list of layout ivi_layer */
|
|
wl_list_init(&layout->layout_layer.view_list.link);
|
|
|
|
wl_list_for_each(iviscrn, &layout->screen_list, link) {
|
|
wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
|
|
if (ivilayer->prop.visibility == false)
|
|
continue;
|
|
|
|
wl_list_for_each(ivi_view, &ivilayer->order.view_list, order_link) {
|
|
if (ivi_view->ivisurf->prop.visibility == false)
|
|
continue;
|
|
|
|
weston_layer_entry_insert(&layout->layout_layer.view_list,
|
|
&ivi_view->view->layer_link);
|
|
|
|
ivi_view->ivisurf->surface->is_mapped = true;
|
|
ivi_view->view->is_mapped = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
commit_transition(struct ivi_layout* layout)
|
|
{
|
|
if (wl_list_empty(&layout->pending_transition_list)) {
|
|
return;
|
|
}
|
|
|
|
wl_list_insert_list(&layout->transitions->transition_list,
|
|
&layout->pending_transition_list);
|
|
|
|
wl_list_init(&layout->pending_transition_list);
|
|
|
|
wl_event_source_timer_update(layout->transitions->event_source, 1);
|
|
}
|
|
|
|
static void
|
|
send_surface_prop(struct ivi_layout_surface *ivisurf)
|
|
{
|
|
wl_signal_emit(&ivisurf->property_changed, ivisurf);
|
|
ivisurf->pending.prop.event_mask = 0;
|
|
}
|
|
|
|
static void
|
|
send_layer_prop(struct ivi_layout_layer *ivilayer)
|
|
{
|
|
wl_signal_emit(&ivilayer->property_changed, ivilayer);
|
|
ivilayer->pending.prop.event_mask = 0;
|
|
}
|
|
|
|
static void
|
|
send_prop(struct ivi_layout *layout)
|
|
{
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
struct ivi_layout_surface *ivisurf = NULL;
|
|
|
|
wl_list_for_each_reverse(ivilayer, &layout->layer_list, link) {
|
|
if (ivilayer->prop.event_mask)
|
|
send_layer_prop(ivilayer);
|
|
}
|
|
|
|
wl_list_for_each_reverse(ivisurf, &layout->surface_list, link) {
|
|
if (ivisurf->prop.event_mask)
|
|
send_surface_prop(ivisurf);
|
|
}
|
|
}
|
|
|
|
static void
|
|
clear_view_pending_list(struct ivi_layout_layer *ivilayer)
|
|
{
|
|
struct ivi_layout_view *view_link = NULL;
|
|
struct ivi_layout_view *view_next = NULL;
|
|
|
|
wl_list_for_each_safe(view_link, view_next,
|
|
&ivilayer->pending.view_list, pending_link) {
|
|
wl_list_remove(&view_link->pending_link);
|
|
wl_list_init(&view_link->pending_link);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Exported APIs of ivi-layout library are implemented from here.
|
|
* Brief of APIs is described in ivi-layout-export.h.
|
|
*/
|
|
static int32_t
|
|
ivi_layout_add_listener_create_layer(struct wl_listener *listener)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
if (listener == NULL) {
|
|
weston_log("ivi_layout_add_listener_create_layer: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&layout->layer_notification.created, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_add_listener_remove_layer(struct wl_listener *listener)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
if (listener == NULL) {
|
|
weston_log("ivi_layout_add_listener_remove_layer: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&layout->layer_notification.removed, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_add_listener_create_surface(struct wl_listener *listener)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
if (listener == NULL) {
|
|
weston_log("ivi_layout_add_listener_create_surface: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&layout->surface_notification.created, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_add_listener_remove_surface(struct wl_listener *listener)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
if (listener == NULL) {
|
|
weston_log("ivi_layout_add_listener_remove_surface: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&layout->surface_notification.removed, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_add_listener_configure_surface(struct wl_listener *listener)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
if (listener == NULL) {
|
|
weston_log("ivi_layout_add_listener_configure_surface: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&layout->surface_notification.configure_changed, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
if (!listener) {
|
|
weston_log("ivi_layout_add_listener_configure_desktop_surface: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
uint32_t
|
|
ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf)
|
|
{
|
|
return ivisurf->id_surface;
|
|
}
|
|
|
|
static uint32_t
|
|
ivi_layout_get_id_of_layer(struct ivi_layout_layer *ivilayer)
|
|
{
|
|
return ivilayer->id_layer;
|
|
}
|
|
|
|
static struct ivi_layout_layer *
|
|
ivi_layout_get_layer_from_id(uint32_t id_layer)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
|
|
wl_list_for_each(ivilayer, &layout->layer_list, link) {
|
|
if (ivilayer->id_layer == id_layer) {
|
|
return ivilayer;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct ivi_layout_surface *
|
|
ivi_layout_get_surface_from_id(uint32_t id_surface)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_surface *ivisurf = NULL;
|
|
|
|
wl_list_for_each(ivisurf, &layout->surface_list, link) {
|
|
if (ivisurf->id_surface == id_surface) {
|
|
return ivisurf;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_surface_add_listener(struct ivi_layout_surface *ivisurf,
|
|
struct wl_listener *listener)
|
|
{
|
|
if (ivisurf == NULL || listener == NULL) {
|
|
weston_log("ivi_layout_surface_add_listener: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&ivisurf->property_changed, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static const struct ivi_layout_layer_properties *
|
|
ivi_layout_get_properties_of_layer(struct ivi_layout_layer *ivilayer)
|
|
{
|
|
if (ivilayer == NULL) {
|
|
weston_log("ivi_layout_get_properties_of_layer: invalid argument\n");
|
|
return NULL;
|
|
}
|
|
|
|
return &ivilayer->prop;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_get_screens_under_layer(struct ivi_layout_layer *ivilayer,
|
|
int32_t *pLength,
|
|
struct weston_output ***ppArray)
|
|
{
|
|
int32_t length = 0;
|
|
int32_t n = 0;
|
|
|
|
if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
|
|
weston_log("ivi_layout_get_screens_under_layer: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
if (ivilayer->on_screen != NULL)
|
|
length = 1;
|
|
|
|
if (length != 0) {
|
|
/* the Array must be free by module which called this function */
|
|
*ppArray = calloc(length, sizeof(struct weston_output *));
|
|
if (*ppArray == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
(*ppArray)[n++] = ivilayer->on_screen->output;
|
|
}
|
|
|
|
*pLength = length;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_get_layers(int32_t *pLength, struct ivi_layout_layer ***ppArray)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
int32_t length = 0;
|
|
int32_t n = 0;
|
|
|
|
if (pLength == NULL || ppArray == NULL) {
|
|
weston_log("ivi_layout_get_layers: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
length = wl_list_length(&layout->layer_list);
|
|
|
|
if (length != 0) {
|
|
/* the Array must be freed by module which called this function */
|
|
*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
|
|
if (*ppArray == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_list_for_each(ivilayer, &layout->layer_list, link) {
|
|
(*ppArray)[n++] = ivilayer;
|
|
}
|
|
}
|
|
|
|
*pLength = length;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_get_layers_on_screen(struct weston_output *output,
|
|
int32_t *pLength,
|
|
struct ivi_layout_layer ***ppArray)
|
|
{
|
|
struct ivi_layout_screen *iviscrn = NULL;
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
int32_t length = 0;
|
|
int32_t n = 0;
|
|
|
|
if (output == NULL || pLength == NULL || ppArray == NULL) {
|
|
weston_log("ivi_layout_get_layers_on_screen: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
iviscrn = get_screen_from_output(output);
|
|
length = wl_list_length(&iviscrn->order.layer_list);
|
|
|
|
if (length != 0) {
|
|
/* the Array must be freed by module which called this function */
|
|
*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
|
|
if (*ppArray == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
|
|
(*ppArray)[n++] = ivilayer;
|
|
}
|
|
}
|
|
|
|
*pLength = length;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_get_layers_under_surface(struct ivi_layout_surface *ivisurf,
|
|
int32_t *pLength,
|
|
struct ivi_layout_layer ***ppArray)
|
|
{
|
|
struct ivi_layout_view *ivi_view;
|
|
int32_t length = 0;
|
|
int32_t n = 0;
|
|
|
|
if (ivisurf == NULL || pLength == NULL || ppArray == NULL) {
|
|
weston_log("ivi_layout_getLayers: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
if (!wl_list_empty(&ivisurf->view_list)) {
|
|
/* the Array must be free by module which called this function */
|
|
length = wl_list_length(&ivisurf->view_list);
|
|
*ppArray = calloc(length, sizeof(struct ivi_layout_layer *));
|
|
if (*ppArray == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_list_for_each_reverse(ivi_view, &ivisurf->view_list, surf_link) {
|
|
if (ivi_view_is_rendered(ivi_view))
|
|
(*ppArray)[n++] = ivi_view->on_layer;
|
|
else
|
|
length--;
|
|
}
|
|
}
|
|
|
|
*pLength = length;
|
|
|
|
if (!length) {
|
|
free(*ppArray);
|
|
*ppArray = NULL;
|
|
}
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static
|
|
int32_t
|
|
ivi_layout_get_surfaces(int32_t *pLength, struct ivi_layout_surface ***ppArray)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_surface *ivisurf = NULL;
|
|
int32_t length = 0;
|
|
int32_t n = 0;
|
|
|
|
if (pLength == NULL || ppArray == NULL) {
|
|
weston_log("ivi_layout_get_surfaces: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
length = wl_list_length(&layout->surface_list);
|
|
|
|
if (length != 0) {
|
|
/* the Array must be freed by module which called this function */
|
|
*ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
|
|
if (*ppArray == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_list_for_each(ivisurf, &layout->surface_list, link) {
|
|
(*ppArray)[n++] = ivisurf;
|
|
}
|
|
}
|
|
|
|
*pLength = length;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_get_surfaces_on_layer(struct ivi_layout_layer *ivilayer,
|
|
int32_t *pLength,
|
|
struct ivi_layout_surface ***ppArray)
|
|
{
|
|
struct ivi_layout_view *ivi_view = NULL;
|
|
int32_t length = 0;
|
|
int32_t n = 0;
|
|
|
|
if (ivilayer == NULL || pLength == NULL || ppArray == NULL) {
|
|
weston_log("ivi_layout_getSurfaceIDsOnLayer: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
length = wl_list_length(&ivilayer->order.view_list);
|
|
|
|
if (length != 0) {
|
|
/* the Array must be freed by module which called this function */
|
|
*ppArray = calloc(length, sizeof(struct ivi_layout_surface *));
|
|
if (*ppArray == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_list_for_each(ivi_view, &ivilayer->order.view_list, order_link) {
|
|
(*ppArray)[n++] = ivi_view->ivisurf;
|
|
}
|
|
}
|
|
|
|
*pLength = length;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static struct ivi_layout_layer *
|
|
ivi_layout_layer_create_with_dimension(uint32_t id_layer,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
|
|
ivilayer = get_layer(&layout->layer_list, id_layer);
|
|
if (ivilayer != NULL) {
|
|
weston_log("id_layer is already created\n");
|
|
++ivilayer->ref_count;
|
|
return ivilayer;
|
|
}
|
|
|
|
ivilayer = calloc(1, sizeof *ivilayer);
|
|
if (ivilayer == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return NULL;
|
|
}
|
|
|
|
ivilayer->ref_count = 1;
|
|
wl_signal_init(&ivilayer->property_changed);
|
|
ivilayer->layout = layout;
|
|
ivilayer->id_layer = id_layer;
|
|
|
|
init_layer_properties(&ivilayer->prop, width, height);
|
|
|
|
wl_list_init(&ivilayer->pending.view_list);
|
|
wl_list_init(&ivilayer->pending.link);
|
|
ivilayer->pending.prop = ivilayer->prop;
|
|
|
|
wl_list_init(&ivilayer->order.view_list);
|
|
wl_list_init(&ivilayer->order.link);
|
|
|
|
wl_list_insert(&layout->layer_list, &ivilayer->link);
|
|
|
|
wl_signal_emit(&layout->layer_notification.created, ivilayer);
|
|
|
|
return ivilayer;
|
|
}
|
|
|
|
static void
|
|
ivi_layout_layer_destroy(struct ivi_layout_layer *ivilayer)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_view *ivi_view, *next;
|
|
|
|
if (ivilayer == NULL) {
|
|
weston_log("ivi_layout_layer_destroy: invalid argument\n");
|
|
return;
|
|
}
|
|
|
|
if (--ivilayer->ref_count > 0)
|
|
return;
|
|
|
|
/*Destroy all ivi_views*/
|
|
wl_list_for_each_safe(ivi_view, next, &layout->view_list, link) {
|
|
if (ivi_view->on_layer == ivilayer)
|
|
ivi_view_destroy(ivi_view);
|
|
}
|
|
|
|
wl_signal_emit(&layout->layer_notification.removed, ivilayer);
|
|
|
|
wl_list_remove(&ivilayer->pending.link);
|
|
wl_list_remove(&ivilayer->order.link);
|
|
wl_list_remove(&ivilayer->link);
|
|
|
|
free(ivilayer);
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_layer_set_visibility(struct ivi_layout_layer *ivilayer,
|
|
bool newVisibility)
|
|
{
|
|
struct ivi_layout_layer_properties *prop = NULL;
|
|
|
|
if (ivilayer == NULL) {
|
|
weston_log("ivi_layout_layer_set_visibility: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivilayer->pending.prop;
|
|
prop->visibility = newVisibility;
|
|
|
|
if (ivilayer->prop.visibility != newVisibility)
|
|
prop->event_mask |= IVI_NOTIFICATION_VISIBILITY;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_layer_set_opacity(struct ivi_layout_layer *ivilayer,
|
|
wl_fixed_t opacity)
|
|
{
|
|
struct ivi_layout_layer_properties *prop = NULL;
|
|
|
|
if (ivilayer == NULL ||
|
|
opacity < wl_fixed_from_double(0.0) ||
|
|
wl_fixed_from_double(1.0) < opacity) {
|
|
weston_log("ivi_layout_layer_set_opacity: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivilayer->pending.prop;
|
|
prop->opacity = opacity;
|
|
|
|
if (ivilayer->prop.opacity != opacity)
|
|
prop->event_mask |= IVI_NOTIFICATION_OPACITY;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_OPACITY;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_layer_set_source_rectangle(struct ivi_layout_layer *ivilayer,
|
|
int32_t x, int32_t y,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout_layer_properties *prop = NULL;
|
|
|
|
if (ivilayer == NULL) {
|
|
weston_log("ivi_layout_layer_set_source_rectangle: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivilayer->pending.prop;
|
|
prop->source_x = x;
|
|
prop->source_y = y;
|
|
prop->source_width = width;
|
|
prop->source_height = height;
|
|
|
|
if (ivilayer->prop.source_x != x || ivilayer->prop.source_y != y ||
|
|
ivilayer->prop.source_width != width ||
|
|
ivilayer->prop.source_height != height)
|
|
prop->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_SOURCE_RECT;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_layer_set_destination_rectangle(struct ivi_layout_layer *ivilayer,
|
|
int32_t x, int32_t y,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout_layer_properties *prop = NULL;
|
|
|
|
if (ivilayer == NULL) {
|
|
weston_log("ivi_layout_layer_set_destination_rectangle: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivilayer->pending.prop;
|
|
prop->dest_x = x;
|
|
prop->dest_y = y;
|
|
prop->dest_width = width;
|
|
prop->dest_height = height;
|
|
|
|
if (ivilayer->prop.dest_x != x || ivilayer->prop.dest_y != y ||
|
|
ivilayer->prop.dest_width != width ||
|
|
ivilayer->prop.dest_height != height)
|
|
prop->event_mask |= IVI_NOTIFICATION_DEST_RECT;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_DEST_RECT;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_layer_set_render_order(struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface **pSurface,
|
|
int32_t number)
|
|
{
|
|
int32_t i = 0;
|
|
struct ivi_layout_view * ivi_view;
|
|
|
|
if (ivilayer == NULL) {
|
|
weston_log("ivi_layout_layer_set_render_order: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
clear_view_pending_list(ivilayer);
|
|
|
|
for (i = 0; i < number; i++) {
|
|
ivi_view = get_ivi_view(ivilayer, pSurface[i]);
|
|
if (!ivi_view)
|
|
ivi_view = ivi_view_create(ivilayer, pSurface[i]);
|
|
|
|
assert(ivi_view != NULL);
|
|
|
|
wl_list_remove(&ivi_view->pending_link);
|
|
wl_list_insert(&ivilayer->pending.view_list, &ivi_view->pending_link);
|
|
}
|
|
|
|
ivilayer->order.dirty = 1;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_surface_set_visibility(struct ivi_layout_surface *ivisurf,
|
|
bool newVisibility)
|
|
{
|
|
struct ivi_layout_surface_properties *prop = NULL;
|
|
|
|
if (ivisurf == NULL) {
|
|
weston_log("ivi_layout_surface_set_visibility: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivisurf->pending.prop;
|
|
prop->visibility = newVisibility;
|
|
|
|
if (ivisurf->prop.visibility != newVisibility)
|
|
prop->event_mask |= IVI_NOTIFICATION_VISIBILITY;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_VISIBILITY;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_surface_set_opacity(struct ivi_layout_surface *ivisurf,
|
|
wl_fixed_t opacity)
|
|
{
|
|
struct ivi_layout_surface_properties *prop = NULL;
|
|
|
|
if (ivisurf == NULL ||
|
|
opacity < wl_fixed_from_double(0.0) ||
|
|
wl_fixed_from_double(1.0) < opacity) {
|
|
weston_log("ivi_layout_surface_set_opacity: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivisurf->pending.prop;
|
|
prop->opacity = opacity;
|
|
|
|
if (ivisurf->prop.opacity != opacity)
|
|
prop->event_mask |= IVI_NOTIFICATION_OPACITY;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_OPACITY;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_surface_set_destination_rectangle(struct ivi_layout_surface *ivisurf,
|
|
int32_t x, int32_t y,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout_surface_properties *prop = NULL;
|
|
|
|
if (ivisurf == NULL) {
|
|
weston_log("ivi_layout_surface_set_destination_rectangle: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivisurf->pending.prop;
|
|
prop->start_x = prop->dest_x;
|
|
prop->start_y = prop->dest_y;
|
|
prop->dest_x = x;
|
|
prop->dest_y = y;
|
|
prop->start_width = prop->dest_width;
|
|
prop->start_height = prop->dest_height;
|
|
prop->dest_width = width;
|
|
prop->dest_height = height;
|
|
|
|
if (ivisurf->prop.dest_x != x || ivisurf->prop.dest_y != y ||
|
|
ivisurf->prop.dest_width != width ||
|
|
ivisurf->prop.dest_height != height)
|
|
prop->event_mask |= IVI_NOTIFICATION_DEST_RECT;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_DEST_RECT;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
void
|
|
ivi_layout_surface_set_size(struct ivi_layout_surface *ivisurf,
|
|
int32_t width, int32_t height)
|
|
{
|
|
if (weston_surface_is_desktop_surface(ivisurf->surface)) {
|
|
weston_desktop_surface_set_size(ivisurf->weston_desktop_surface,
|
|
width, height);
|
|
} else {
|
|
shell_surface_send_configure(ivisurf->surface,
|
|
width, height);
|
|
}
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_screen_add_layer(struct weston_output *output,
|
|
struct ivi_layout_layer *addlayer)
|
|
{
|
|
struct ivi_layout_screen *iviscrn;
|
|
|
|
if (output == NULL || addlayer == NULL) {
|
|
weston_log("ivi_layout_screen_add_layer: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
iviscrn = get_screen_from_output(output);
|
|
|
|
/*if layer is already assigned to screen make order of it dirty
|
|
* we are going to remove it (in commit_screen_list)*/
|
|
if (addlayer->on_screen)
|
|
addlayer->on_screen->order.dirty = 1;
|
|
|
|
wl_list_remove(&addlayer->pending.link);
|
|
wl_list_insert(&iviscrn->pending.layer_list, &addlayer->pending.link);
|
|
|
|
iviscrn->order.dirty = 1;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_screen_remove_layer(struct weston_output *output,
|
|
struct ivi_layout_layer *removelayer)
|
|
{
|
|
struct ivi_layout_screen *iviscrn;
|
|
|
|
if (output == NULL || removelayer == NULL) {
|
|
weston_log("ivi_layout_screen_remove_layer: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
iviscrn = get_screen_from_output(output);
|
|
|
|
wl_list_remove(&removelayer->pending.link);
|
|
wl_list_init(&removelayer->pending.link);
|
|
|
|
iviscrn->order.dirty = 1;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_screen_set_render_order(struct weston_output *output,
|
|
struct ivi_layout_layer **pLayer,
|
|
const int32_t number)
|
|
{
|
|
struct ivi_layout_screen *iviscrn;
|
|
struct ivi_layout_layer *ivilayer = NULL;
|
|
struct ivi_layout_layer *next = NULL;
|
|
int32_t i = 0;
|
|
|
|
if (output == NULL) {
|
|
weston_log("ivi_layout_screen_set_render_order: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
iviscrn = get_screen_from_output(output);
|
|
|
|
wl_list_for_each_safe(ivilayer, next,
|
|
&iviscrn->pending.layer_list, pending.link) {
|
|
wl_list_remove(&ivilayer->pending.link);
|
|
wl_list_init(&ivilayer->pending.link);
|
|
}
|
|
|
|
assert(wl_list_empty(&iviscrn->pending.layer_list));
|
|
|
|
for (i = 0; i < number; i++) {
|
|
wl_list_remove(&pLayer[i]->pending.link);
|
|
wl_list_insert(&iviscrn->pending.layer_list,
|
|
&pLayer[i]->pending.link);
|
|
}
|
|
|
|
iviscrn->order.dirty = 1;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
/**
|
|
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
|
|
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
|
|
* This function is used to get the result of drawing by clients.
|
|
*/
|
|
static struct weston_surface *
|
|
ivi_layout_surface_get_weston_surface(struct ivi_layout_surface *ivisurf)
|
|
{
|
|
return ivisurf != NULL ? ivisurf->surface : NULL;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_surface_get_size(struct ivi_layout_surface *ivisurf,
|
|
int32_t *width, int32_t *height,
|
|
int32_t *stride)
|
|
{
|
|
int32_t w;
|
|
int32_t h;
|
|
const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
|
|
|
|
if (ivisurf == NULL || ivisurf->surface == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
weston_surface_get_content_size(ivisurf->surface, &w, &h);
|
|
|
|
if (width != NULL)
|
|
*width = w;
|
|
|
|
if (height != NULL)
|
|
*height = h;
|
|
|
|
if (stride != NULL)
|
|
*stride = w * bytespp;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_layer_add_listener(struct ivi_layout_layer *ivilayer,
|
|
struct wl_listener *listener)
|
|
{
|
|
if (ivilayer == NULL || listener == NULL) {
|
|
weston_log("ivi_layout_layer_add_listener: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
wl_signal_add(&ivilayer->property_changed, listener);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static const struct ivi_layout_surface_properties *
|
|
ivi_layout_get_properties_of_surface(struct ivi_layout_surface *ivisurf)
|
|
{
|
|
if (ivisurf == NULL) {
|
|
weston_log("ivi_layout_get_properties_of_surface: invalid argument\n");
|
|
return NULL;
|
|
}
|
|
|
|
return &ivisurf->prop;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_layer_add_surface(struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface *addsurf)
|
|
{
|
|
struct ivi_layout_view *ivi_view;
|
|
|
|
if (ivilayer == NULL || addsurf == NULL) {
|
|
weston_log("ivi_layout_layer_add_surface: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
ivi_view = get_ivi_view(ivilayer, addsurf);
|
|
if (!ivi_view)
|
|
ivi_view = ivi_view_create(ivilayer, addsurf);
|
|
|
|
wl_list_remove(&ivi_view->pending_link);
|
|
wl_list_insert(&ivilayer->pending.view_list, &ivi_view->pending_link);
|
|
|
|
ivilayer->order.dirty = 1;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static void
|
|
ivi_layout_layer_remove_surface(struct ivi_layout_layer *ivilayer,
|
|
struct ivi_layout_surface *remsurf)
|
|
{
|
|
struct ivi_layout_view *ivi_view;
|
|
|
|
if (ivilayer == NULL || remsurf == NULL) {
|
|
weston_log("ivi_layout_layer_remove_surface: invalid argument\n");
|
|
return;
|
|
}
|
|
|
|
ivi_view = get_ivi_view(ivilayer, remsurf);
|
|
if (ivi_view) {
|
|
wl_list_remove(&ivi_view->pending_link);
|
|
wl_list_init(&ivi_view->pending_link);
|
|
|
|
ivilayer->order.dirty = 1;
|
|
}
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_surface_set_source_rectangle(struct ivi_layout_surface *ivisurf,
|
|
int32_t x, int32_t y,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout_surface_properties *prop = NULL;
|
|
|
|
if (ivisurf == NULL) {
|
|
weston_log("ivi_layout_surface_set_source_rectangle: invalid argument\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
prop = &ivisurf->pending.prop;
|
|
prop->source_x = x;
|
|
prop->source_y = y;
|
|
prop->source_width = width;
|
|
prop->source_height = height;
|
|
|
|
if (ivisurf->prop.source_x != x || ivisurf->prop.source_y != y ||
|
|
ivisurf->prop.source_width != width ||
|
|
ivisurf->prop.source_height != height)
|
|
prop->event_mask |= IVI_NOTIFICATION_SOURCE_RECT;
|
|
else
|
|
prop->event_mask &= ~IVI_NOTIFICATION_SOURCE_RECT;
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
int32_t
|
|
ivi_layout_commit_changes(void)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
commit_surface_list(layout);
|
|
commit_layer_list(layout);
|
|
commit_screen_list(layout);
|
|
build_view_list(layout);
|
|
|
|
commit_transition(layout);
|
|
|
|
commit_changes(layout);
|
|
send_prop(layout);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer,
|
|
enum ivi_layout_transition_type type,
|
|
uint32_t duration)
|
|
{
|
|
if (ivilayer == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
ivilayer->pending.prop.transition_type = type;
|
|
ivilayer->pending.prop.transition_duration = duration;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_layer_set_fade_info(struct ivi_layout_layer* ivilayer,
|
|
uint32_t is_fade_in,
|
|
double start_alpha, double end_alpha)
|
|
{
|
|
if (ivilayer == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
ivilayer->pending.prop.is_fade_in = is_fade_in;
|
|
ivilayer->pending.prop.start_alpha = start_alpha;
|
|
ivilayer->pending.prop.end_alpha = end_alpha;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf,
|
|
uint32_t duration)
|
|
{
|
|
struct ivi_layout_surface_properties *prop;
|
|
|
|
if (ivisurf == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
prop = &ivisurf->pending.prop;
|
|
prop->transition_duration = duration*10;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* This interface enables e.g. an id agent to set the id of an ivi-layout
|
|
* surface, that has been created by a desktop application. This can only be
|
|
* done once as long as the initial surface id equals IVI_INVALID_ID. Afterwards
|
|
* two events are emitted, namely surface_created and surface_configured.
|
|
*/
|
|
static int32_t
|
|
ivi_layout_surface_set_id(struct ivi_layout_surface *ivisurf,
|
|
uint32_t id_surface)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_surface *search_ivisurf = NULL;
|
|
|
|
if (!ivisurf) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
if (ivisurf->id_surface != IVI_INVALID_ID) {
|
|
weston_log("surface id can only be set once\n");
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
search_ivisurf = get_surface(&layout->surface_list, id_surface);
|
|
if (search_ivisurf) {
|
|
weston_log("id_surface(%d) is already created\n", id_surface);
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
ivisurf->id_surface = id_surface;
|
|
|
|
wl_signal_emit(&layout->surface_notification.configure_changed,
|
|
ivisurf);
|
|
|
|
return IVI_SUCCEEDED;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf,
|
|
enum ivi_layout_transition_type type,
|
|
uint32_t duration)
|
|
{
|
|
struct ivi_layout_surface_properties *prop;
|
|
|
|
if (ivisurf == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
prop = &ivisurf->pending.prop;
|
|
prop->transition_type = type;
|
|
prop->transition_duration = duration;
|
|
return 0;
|
|
}
|
|
|
|
static int32_t
|
|
ivi_layout_surface_dump(struct weston_surface *surface,
|
|
void *target, size_t size,int32_t x, int32_t y,
|
|
int32_t width, int32_t height)
|
|
{
|
|
int result = 0;
|
|
|
|
if (surface == NULL) {
|
|
weston_log("%s: invalid argument\n", __func__);
|
|
return IVI_FAILED;
|
|
}
|
|
|
|
result = weston_surface_copy_content(
|
|
surface, target, size,
|
|
x, y, width, height);
|
|
|
|
return result == 0 ? IVI_SUCCEEDED : IVI_FAILED;
|
|
}
|
|
|
|
/**
|
|
* methods of interaction between ivi-shell with ivi-layout
|
|
*/
|
|
|
|
static struct ivi_layout_surface*
|
|
surface_create(struct weston_surface *wl_surface, uint32_t id_surface)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_surface *ivisurf = NULL;
|
|
|
|
if (wl_surface == NULL) {
|
|
weston_log("ivi_layout_surface_create: invalid argument\n");
|
|
return NULL;
|
|
}
|
|
|
|
ivisurf = calloc(1, sizeof *ivisurf);
|
|
if (ivisurf == NULL) {
|
|
weston_log("fails to allocate memory\n");
|
|
return NULL;
|
|
}
|
|
|
|
wl_signal_init(&ivisurf->property_changed);
|
|
ivisurf->id_surface = id_surface;
|
|
ivisurf->layout = layout;
|
|
|
|
ivisurf->surface = wl_surface;
|
|
|
|
ivisurf->surface->width_from_buffer = 0;
|
|
ivisurf->surface->height_from_buffer = 0;
|
|
|
|
init_surface_properties(&ivisurf->prop);
|
|
|
|
ivisurf->pending.prop = ivisurf->prop;
|
|
|
|
wl_list_init(&ivisurf->view_list);
|
|
|
|
wl_list_insert(&layout->surface_list, &ivisurf->link);
|
|
|
|
return ivisurf;
|
|
}
|
|
|
|
void
|
|
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
/* emit callback which is set by ivi-layout api user */
|
|
wl_signal_emit(&layout->surface_notification.configure_desktop_changed,
|
|
ivisurf);
|
|
}
|
|
|
|
struct ivi_layout_surface*
|
|
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
|
struct weston_desktop_surface *surface)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_surface *ivisurf;
|
|
|
|
ivisurf = surface_create(wl_surface, IVI_INVALID_ID);
|
|
|
|
if (ivisurf) {
|
|
ivisurf->weston_desktop_surface = surface;
|
|
wl_signal_emit(&layout->surface_notification.created, ivisurf);
|
|
}
|
|
|
|
return ivisurf;
|
|
}
|
|
|
|
void
|
|
ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf,
|
|
int32_t width, int32_t height)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
/* emit callback which is set by ivi-layout api user */
|
|
wl_signal_emit(&layout->surface_notification.configure_changed,
|
|
ivisurf);
|
|
}
|
|
|
|
struct ivi_layout_surface*
|
|
ivi_layout_surface_create(struct weston_surface *wl_surface,
|
|
uint32_t id_surface)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
struct ivi_layout_surface *ivisurf = NULL;
|
|
|
|
ivisurf = get_surface(&layout->surface_list, id_surface);
|
|
if (ivisurf) {
|
|
weston_log("id_surface(%d) is already created\n", id_surface);
|
|
return NULL;
|
|
}
|
|
|
|
ivisurf = surface_create(wl_surface, id_surface);
|
|
|
|
if (ivisurf)
|
|
wl_signal_emit(&layout->surface_notification.created, ivisurf);
|
|
|
|
return ivisurf;
|
|
}
|
|
|
|
static struct ivi_layout_interface ivi_layout_interface;
|
|
|
|
void
|
|
ivi_layout_init_with_compositor(struct weston_compositor *ec)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
layout->compositor = ec;
|
|
|
|
wl_list_init(&layout->surface_list);
|
|
wl_list_init(&layout->layer_list);
|
|
wl_list_init(&layout->screen_list);
|
|
wl_list_init(&layout->view_list);
|
|
|
|
wl_signal_init(&layout->layer_notification.created);
|
|
wl_signal_init(&layout->layer_notification.removed);
|
|
|
|
wl_signal_init(&layout->surface_notification.created);
|
|
wl_signal_init(&layout->surface_notification.removed);
|
|
wl_signal_init(&layout->surface_notification.configure_changed);
|
|
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
|
|
|
|
/* Add layout_layer at the last of weston_compositor.layer_list */
|
|
weston_layer_init(&layout->layout_layer, ec);
|
|
weston_layer_set_position(&layout->layout_layer,
|
|
WESTON_LAYER_POSITION_NORMAL);
|
|
|
|
create_screen(ec);
|
|
|
|
layout->transitions = ivi_layout_transition_set_create(ec);
|
|
wl_list_init(&layout->pending_transition_list);
|
|
|
|
weston_plugin_api_register(ec, IVI_LAYOUT_API_NAME,
|
|
&ivi_layout_interface,
|
|
sizeof(struct ivi_layout_interface));
|
|
}
|
|
|
|
void
|
|
ivi_layout_fini(void)
|
|
{
|
|
struct ivi_layout *layout = get_instance();
|
|
|
|
weston_layer_fini(&layout->layout_layer);
|
|
|
|
/* XXX: tear down everything else */
|
|
}
|
|
|
|
static struct ivi_layout_interface ivi_layout_interface = {
|
|
/**
|
|
* commit all changes
|
|
*/
|
|
.commit_changes = ivi_layout_commit_changes,
|
|
|
|
/**
|
|
* surface controller interfaces
|
|
*/
|
|
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
|
|
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
|
|
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
|
|
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
|
|
.get_surface = shell_get_ivi_layout_surface,
|
|
.get_surfaces = ivi_layout_get_surfaces,
|
|
.get_id_of_surface = ivi_layout_get_id_of_surface,
|
|
.get_surface_from_id = ivi_layout_get_surface_from_id,
|
|
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
|
|
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
|
|
.surface_set_visibility = ivi_layout_surface_set_visibility,
|
|
.surface_set_opacity = ivi_layout_surface_set_opacity,
|
|
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
|
|
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
|
|
.surface_add_listener = ivi_layout_surface_add_listener,
|
|
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
|
|
.surface_set_transition = ivi_layout_surface_set_transition,
|
|
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
|
|
.surface_set_id = ivi_layout_surface_set_id,
|
|
|
|
/**
|
|
* layer controller interfaces
|
|
*/
|
|
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
|
|
.add_listener_remove_layer = ivi_layout_add_listener_remove_layer,
|
|
.layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
|
|
.layer_destroy = ivi_layout_layer_destroy,
|
|
.get_layers = ivi_layout_get_layers,
|
|
.get_id_of_layer = ivi_layout_get_id_of_layer,
|
|
.get_layer_from_id = ivi_layout_get_layer_from_id,
|
|
.get_properties_of_layer = ivi_layout_get_properties_of_layer,
|
|
.get_layers_under_surface = ivi_layout_get_layers_under_surface,
|
|
.get_layers_on_screen = ivi_layout_get_layers_on_screen,
|
|
.layer_set_visibility = ivi_layout_layer_set_visibility,
|
|
.layer_set_opacity = ivi_layout_layer_set_opacity,
|
|
.layer_set_source_rectangle = ivi_layout_layer_set_source_rectangle,
|
|
.layer_set_destination_rectangle = ivi_layout_layer_set_destination_rectangle,
|
|
.layer_add_surface = ivi_layout_layer_add_surface,
|
|
.layer_remove_surface = ivi_layout_layer_remove_surface,
|
|
.layer_set_render_order = ivi_layout_layer_set_render_order,
|
|
.layer_add_listener = ivi_layout_layer_add_listener,
|
|
.layer_set_transition = ivi_layout_layer_set_transition,
|
|
|
|
/**
|
|
* screen controller interfaces
|
|
*/
|
|
.get_screens_under_layer = ivi_layout_get_screens_under_layer,
|
|
.screen_add_layer = ivi_layout_screen_add_layer,
|
|
.screen_remove_layer = ivi_layout_screen_remove_layer,
|
|
.screen_set_render_order = ivi_layout_screen_set_render_order,
|
|
|
|
/**
|
|
* animation
|
|
*/
|
|
.transition_move_layer_cancel = ivi_layout_transition_move_layer_cancel,
|
|
.layer_set_fade_info = ivi_layout_layer_set_fade_info,
|
|
|
|
/**
|
|
* surface content dumping for debugging
|
|
*/
|
|
.surface_get_size = ivi_layout_surface_get_size,
|
|
.surface_dump = ivi_layout_surface_dump,
|
|
};
|