/*
 * (C) Copyright 2014, Fuji Xerox Co.,Ltd.  All rights reserved.
 * File name : fx-surface-extension.c
 * Title : surface extension of fx.
 */

#include "config.h"

#include "shared/helpers.h"
#include "fx-shell.h"
#include "fx-surface-extension-server-protocol.h"
#include "fx-surface-extension.h"

/* Typedefs */
struct fx_surface_extension {
    struct wl_resource *
        resource;
    struct wl_listener
        destroy_listener;
    struct fx_shell *
        shell;
} ;
struct fx_extended_surface {
    struct wl_resource *
        resource;
    struct wl_listener
        destroy_listener;
    struct fx_surface_extension *
        surface_extension;
    struct wl_resource *
        surface_resource;
} ;

/* Procedures */
static void
set_window_flags(
        struct wl_client *client,
        struct wl_resource *resource,
        int32_t flags )
{
    struct fx_extended_surface *extended_surface
        = wl_resource_get_user_data( resource );
    struct weston_surface *surface
        = wl_resource_get_user_data( extended_surface->surface_resource );
    struct fx_shell_surface *shell_surface
        = fx_shell_surface_get_shell_surface( surface );

    if ( shell_surface != 0 ) {
        const int mask = FX_EXTENDED_SURFACE_WINDOWFLAG_DOESNOTACCEPTFOCUS;

        fx_shell_surafce_set_flags(
                shell_surface,
                ( fx_shell_surafce_get_flags( shell_surface ) & ~mask )
                | ( flags & mask ) );
    }
}
static void
set_shadow_focus(
        struct wl_client *client,
        struct wl_resource *resource,
        int32_t on )
{
    struct fx_extended_surface *extended_surface
        = wl_resource_get_user_data( resource );
    struct weston_surface *surface
        = wl_resource_get_user_data( extended_surface->surface_resource );
    struct fx_shell_surface *shell_surface
        = fx_shell_surface_get_shell_surface( surface );

    if ( shell_surface != 0 ) {
        fx_shell_surafce_set_shadow_focus(
                shell_surface,
                on );
    }
}

static void
set_anim_enabled(
        struct wl_client *client,
        struct wl_resource *resource,
        int32_t on )
{
    struct fx_extended_surface *extended_surface
        = wl_resource_get_user_data( resource );
    struct weston_surface *surface
        = wl_resource_get_user_data( extended_surface->surface_resource );
    struct fx_shell_surface *shell_surface
        = fx_shell_surface_get_shell_surface( surface );

    if ( shell_surface != 0 ) {
        fx_shell_surafce_set_anim_enabled(
                shell_surface,
                on );
    }
}
static void
set_layer_index(
        struct wl_client *client,
        struct wl_resource *resource,
        int32_t layer_index )
{
    struct fx_extended_surface *extended_surface
        = wl_resource_get_user_data( resource );
    struct weston_surface *surface
        = wl_resource_get_user_data( extended_surface->surface_resource );
    struct fx_shell_surface *shell_surface
        = fx_shell_surface_get_shell_surface( surface );

    if ( shell_surface != 0 ) {
        fx_shell_surafce_set_layer_index(
                shell_surface,
                layer_index );
    }
}

static void
extended_surface_destroyed(
        struct wl_listener *listener,
        void *data )
{
    struct fx_extended_surface *extended_surface
        = container_of(listener, struct fx_extended_surface, destroy_listener);

    free( extended_surface );
}
static struct fx_extended_surface_interface fx_extended_surface_implementation = {
    set_window_flags,
    set_shadow_focus,
    set_anim_enabled,
    set_layer_index,
};

static void
get_extended_surface(
        struct wl_client *client,
        struct wl_resource *resource,
        uint32_t id,
        struct wl_resource *surface_resource )
{
    struct fx_surface_extension *surface_extension
        = wl_resource_get_user_data( resource );
    struct fx_extended_surface *extended_surface;

    extended_surface = zalloc( sizeof ( *extended_surface ) );

    if ( extended_surface == NULL ) {
        return;
    }
    extended_surface->resource = wl_resource_create(
            client,
            &fx_extended_surface_interface,
            1,
            id );
    wl_resource_set_implementation(
            extended_surface->resource,
            &fx_extended_surface_implementation,
            extended_surface,
            NULL );
    extended_surface->destroy_listener.notify = extended_surface_destroyed;
    wl_client_add_destroy_listener(
            client,
            &extended_surface->destroy_listener );

    extended_surface->surface_extension = surface_extension;
    extended_surface->surface_resource = surface_resource;
}

static struct fx_surface_extension_interface fx_surface_extension_implementation = {
    get_extended_surface,
};
static void 
bind_fx_surface_extension(
        struct wl_client *client,
        void *data,
        uint32_t version,
        uint32_t id )
{
    struct fx_shell *shell = data;
    struct fx_surface_extension * surface_extension;

    surface_extension = zalloc( sizeof ( *surface_extension ) );

    if ( surface_extension == NULL ) {
        return;
    }
    surface_extension->resource = wl_resource_create(
            client,
            &fx_surface_extension_interface,
            1,
            id );
    wl_resource_set_implementation(
            surface_extension->resource,
            &fx_surface_extension_implementation,
            surface_extension,
            NULL );
    surface_extension->destroy_listener.notify = extended_surface_destroyed;
    wl_client_add_destroy_listener(
            client,
            &surface_extension->destroy_listener );

    surface_extension->shell = shell;
}

struct wl_global*
fx_surface_extension_create( struct fx_shell* shell )
{
    return wl_global_create(
            shell->compositor->wl_display,
            &fx_surface_extension_interface,
            1,
            shell,
            bind_fx_surface_extension );
}

