Logo Search packages:      
Sourcecode: netbook-launcher-efl version File versions  Download package

gadget_item.c

#include <gtk/gtk.h>
#include <Elementary.h>
#include <cairo/cairo.h>
#include <libgadget/libgadget.h>
#include "netbook-launcher.h"

#define SMART_DATA_GET(o, ptr)  \
    struct _data *ptr = evas_object_smart_data_get(o)

#define SMART_DATA_GET_OR_RETURN(o, ptr) \
    SMART_DATA_GET(o, ptr);              \
    if (!ptr) {                          \
        ERR("no private data for object %p (%s)\n", \
            o, evas_object_type_get(o));            \
        return;                          \
    }

#define SMART_DATA_GET_OR_RETURN_NULL(o, ptr)   \
    SMART_DATA_GET(o, ptr);                     \
    if (!ptr) {                                 \
        ERR("no private data for object %p (%s)\n", \
            o, evas_object_type_get(o));            \
    return NULL;                                \
    }

struct _data {
    Evas_Object_Smart_Clipped_Data base;
    Evas_Object *cairo;
    GadgetProxy *proxy;
    GadgetManager *manager;
    const char *uid;
    const char *path;
};

/* Keep just one instance of them */
static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL;
static unsigned int gtk_init_count = 0;
static unsigned int g_type_init_count = 0;

static void *
_setup_private_data(Evas_Object *o, unsigned int size)
{
    struct _data *priv;

    priv = evas_object_smart_data_get(o);
    if (!priv) {
        priv = malloc(size);
        if (!priv) {
            ERR("could not malloc private data.\n");
            return NULL;
        }
        evas_object_smart_data_set(o, priv);
    }

    return priv;
}

static void
_smart_add(Evas_Object *o)
{
    struct _data *priv;

    priv = _setup_private_data(o, sizeof(struct _data));
    if (!priv) {
        ERR("Could not add new smart object\n");
        return;
    }

    priv->cairo = NULL;
    priv->proxy = NULL;
    priv->manager = NULL;
    priv->path = NULL;
    priv->uid = NULL;

    _parent_sc.add(o);
}

static void
_smart_del(Evas_Object *o)
{
    SMART_DATA_GET(o, priv);

    if (priv->cairo)
        evas_object_del(priv->cairo);
    if (priv->manager)
        g_object_unref(priv->manager);
    if (priv->proxy)
        g_object_unref(priv->proxy);
    if (priv->path)
        eina_stringshare_del(priv->path);
    if (priv->uid)
        eina_stringshare_del(priv->uid);

    priv->cairo = NULL;
    priv->manager = NULL;
    priv->proxy = NULL;

    _parent_sc.del(o);
}

static void
_smart_calculate(Evas_Object *o)
{
    Evas_Coord x, y, w, h;
    SMART_DATA_GET_OR_RETURN(o, priv);
    evas_object_geometry_get(o, &x, &y, &w, &h);
    evas_object_image_data_update_add(priv->cairo, 0, 0, w, h);
}

static void
_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
{
    SMART_DATA_GET_OR_RETURN(o, priv);

    /* Resize smart object */
    evas_object_image_size_set(priv->cairo, w, h);
    cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
    evas_image_cairo_surface_set(priv->cairo, s);

    evas_object_smart_changed(o);

    return;
}

static Evas_Smart_Class *
_smart_class_new(void)
{
    static Evas_Smart_Class sc =
        EVAS_SMART_CLASS_INIT_NAME_VERSION("EFLGADGET");

    if (!_parent_sc.name) {
        evas_object_smart_clipped_smart_set(&sc);
        _parent_sc = sc;
        sc.add = _smart_add;
        sc.del = _smart_del;
        sc.resize = _smart_resize;
        sc.calculate = _smart_calculate;
    }

    return &sc;
}

static void
_key_down(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Event_Key_Down *kd = (Evas_Event_Key_Down *)ev;
    GdkEventKey e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    e.type = GDK_KEY_PRESS;
    e.time = kd->timestamp;
    e.keyval = 0;
    e.hardware_keycode = 0;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}

static void
_key_up(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Event_Key_Up *ku = (Evas_Event_Key_Up *)ev;
    GdkEventKey e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    e.window = NULL;
    e.type = GDK_KEY_RELEASE;
    e.time = ku->timestamp;
    e.keyval = 0;
    e.hardware_keycode = 0;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}

static void
_mouse_down(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Coord x, y;
    Evas_Event_Mouse_Down *md = (Evas_Event_Mouse_Down *)ev;
    GdkEventButton e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(data, priv);

    x = md->canvas.x;
    y = md->canvas.y;

    // the x coordinate of the pointer relative to the window.
    e.x = x;
    e.y = y;
    e.time = md->timestamp;
    // FIXME: Treat here double and triple-click too
    e.type = GDK_BUTTON_PRESS;
    e.device = NULL;
    e.button = md->button;
    // Ask evas for modifiers and translate them to gdk bit-mask
    // e.state = key_modifiers;
    // the x coordinate of the pointer relative to the root of the screen.
    //e.x_root = last_x;
    //e.y_root = last_y;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}


static void
_mouse_up(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Coord x, y;
    Evas_Event_Mouse_Up *mu = (Evas_Event_Mouse_Up *)ev;
    GdkEventButton e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    x = mu->canvas.x;
    y = mu->canvas.y;

    e.x = x;
    e.y = y;
    e.time = mu->timestamp;
    e.type = GDK_BUTTON_RELEASE;
    e.device = NULL;
    e.button = mu->button;
    //e.x_root = last_x;
    //e.y_root = last_y;

    //last_x = x;
    //last_y = y;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}

static void
_mouse_move(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Coord x, y;
    Evas_Event_Mouse_Move *mm = (Evas_Event_Mouse_Move *)ev;
    GdkEventMotion e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    x = mm->cur.canvas.x;
    y = mm->cur.canvas.y;

    e.type = GDK_MOTION_NOTIFY;
    e.time = mm->timestamp;
    e.x = x;
    e.y = y;
    //e.x_root = last_x;
    //e.x_root = last_y;

    //last_x = x;
    //last_y = y;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}

static void
_mouse_in(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Coord x, y;
    Evas_Event_Mouse_In *mi = (Evas_Event_Mouse_In *)ev;
    GdkEventCrossing e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    e.type = GDK_ENTER_NOTIFY;
    e.time = mi->timestamp;
    e.x = x;
    e.y = y;
    e.state = 0;
    //e.x_root = last_x;
    //e.y_root = last_y;
    e.mode = GDK_CROSSING_NORMAL;

    //last_x = x;
    //last_y = y;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}

static void
_mouse_out(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Event_Mouse_Out *mo = (Evas_Event_Mouse_Out *)ev;
    GdkEventCrossing e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    e.type = GDK_LEAVE_NOTIFY;
    e.time = mo->timestamp;
    e.x = mo->canvas.x;
    e.y = mo->canvas.y;
    e.state = 0;
    //e.x_root = last_x;
    //e.y_root = last_y;
    e.mode = GDK_CROSSING_NORMAL;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);
}

static void
_mouse_wheel(void *data, Evas *evas, Evas_Object *o, void *ev)
{
    Evas_Event_Mouse_Wheel *mw = (Evas_Event_Mouse_Wheel *)ev;
    GdkEventScroll e;
    Evas_Object *gadget = data;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    e.type = GDK_SCROLL;
    e.time = mw->timestamp;
    e.x = mw->canvas.x;
    e.y = mw->canvas.y;
    /*
       e.state = modifier_state;
       e.x_root = root;
       e.y_root = root; */
    e.direction =
        mw->direction == 0 && mw->z < 0 ? GDK_SCROLL_UP :
        mw->direction == 0 && mw->z > 0 ? GDK_SCROLL_DOWN :
        mw->direction != 0 && mw->z < 0 ? GDK_SCROLL_LEFT :
        GDK_SCROLL_RIGHT;

    gadget_proxy_event(priv->proxy, (GdkEvent *)&e);

}

static void
_on_queue_redraw(GadgetProxy *proxy, Evas_Object *gadget)
{
    cairo_t *cr;
    cairo_surface_t *cs;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    if (!priv->cairo || !priv->proxy)
        return;

    cs = evas_image_cairo_surface_get(priv->cairo);
    if (!cs) {
        ERR("Could not get cairo surface\n");
        return;
    }
    cr = cairo_create(cs);
    if (!cr) {
        ERR("Could not get cairo from surface\n");
        return;
    }

    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
    cairo_paint(cr);
    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
    gadget_cairo_draw(GADGET_CAIRO(priv->proxy), cr);
    cairo_destroy(cr);

    evas_object_smart_changed(gadget);
}

static void
_on_queue_resize(GadgetProxy *proxy, Evas_Object *gadget)
{
    int w, h;
    SMART_DATA_GET_OR_RETURN(gadget, priv);

    w = gadget_proxy_get_width(proxy);
    h = gadget_proxy_get_height(proxy);

    evas_object_resize(gadget, w, h);
}

static void
_on_remove_me(GadgetProxy *proxy, Evas_Object *gadget)
{
    SMART_DATA_GET(gadget, priv);

    if (priv->proxy)
        gadget_proxy_removed(priv->proxy);

    evas_object_smart_callback_call(gadget, "remove-me", NULL);
}

static void
_on_begin_resize(GadgetProxy *proxy, GadgetResizePoint point, Evas_Object *gadget)
{
    //printf("Resize: %d\n", point);
}

static void
_on_begin_drag_move(Evas_Object *gadget)
{
    INF("on drag move\n");
    /* Store last position here? */
    //g_signal_emit_by_name(gadget, "begin-drag-move", NULL);
}

static void
_on_open_url(GadgetProxy *proxy, const gchar *url, Evas_Object *gadget)
{
    INF("open url %s", url);
}

static void
_signals_connect(GadgetProxy *proxy, Evas_Object *gadget)
{
    if (!proxy || !gadget)
        return;

    g_signal_connect(proxy, "queue-redraw",
            G_CALLBACK(_on_queue_redraw), gadget);
    g_signal_connect(proxy, "queue-resize",
            G_CALLBACK(_on_queue_resize), gadget);
    g_signal_connect(proxy, "open-url",
            G_CALLBACK(_on_open_url), gadget);
    g_signal_connect(proxy, "begin-resize",
            G_CALLBACK(_on_begin_resize), gadget);
    g_signal_connect(proxy, "begin-drag-move",
            G_CALLBACK(_on_begin_drag_move), gadget);
    g_signal_connect(proxy, "remove-me",
            G_CALLBACK(_on_remove_me), gadget);
}

static void
_callbacks_add(Evas_Object *cairo, Evas_Object *gadget)
{
    if (!cairo || !gadget)
        return;

    evas_object_event_callback_add(cairo, EVAS_CALLBACK_MOUSE_DOWN,
            _mouse_down, gadget);
    evas_object_event_callback_add(cairo, EVAS_CALLBACK_MOUSE_UP,
            _mouse_up, gadget);
    evas_object_event_callback_add(cairo, EVAS_CALLBACK_MOUSE_MOVE,
            _mouse_move, gadget);
    evas_object_event_callback_add(cairo, EVAS_CALLBACK_MOUSE_IN,
            _mouse_in, gadget);
    evas_object_event_callback_add(cairo, EVAS_CALLBACK_MOUSE_OUT,
            _mouse_out, gadget);
    evas_object_event_callback_add(cairo, EVAS_CALLBACK_MOUSE_WHEEL,
            _mouse_wheel, gadget);
}

static Evas_Object *
_create_gadget(Evas *evas, Evas_Smart *smart, const char *path, const char *uid)
{
    Evas_Object *gadget = evas_object_smart_add(evas, smart);
    if (!gadget) {
        ERR("Could not add smart gadget\n");
        return NULL;
    }

    SMART_DATA_GET(gadget, priv);
    if (!priv)
        goto on_error;

    priv->manager = gadget_manager_get_default();
    if (!priv->manager) {
        ERR("Could not get a gadget manager\n");
        goto on_error;
    }
    gadget_manager_load_sources(priv->manager);

    if (!gadget_manager_can_handle_path(priv->manager, path)) {
        ERR("Cannot handle path: %s\n", path);
        goto on_error;
    }

    priv->proxy = gadget_manager_load_gadget(priv->manager, path, uid);
    if (!priv->proxy) {
        ERR("Unable to load gadget %s path %s\n", uid, path);
        goto on_error;
    }

    priv->cairo = evas_image_cairo_new(evas, 1, 1, 1);
    if (!priv->cairo)
        goto on_error;

    evas_object_smart_member_add(priv->cairo, gadget);
    evas_object_show(priv->cairo);

    priv->uid = eina_stringshare_add(uid);
    priv->path = eina_stringshare_add(path);

    _signals_connect(priv->proxy, gadget);
    _callbacks_add(priv->cairo, gadget);

    evas_object_image_filled_set(priv->cairo, 1);
    evas_image_cairo_fill_auto_set(priv->cairo, 1);
    _on_queue_resize(priv->proxy, gadget);

    return gadget;

on_error:
    evas_object_del(gadget);
    return NULL;
}

Evas_Object *
efl_gadget_new(Evas *evas, const char *path, const char *uid)
{
    Evas_Smart *smart;
    Evas_Object *gadget;

    if (!evas) {
        ERR("No canvas to add the gadget to\n");
        return NULL;
    }

    smart = evas_smart_class_new(_smart_class_new());
    if (!smart) {
        ERR("Could not create new smart class\n");
        return NULL;
    }

    gadget = _create_gadget(evas, smart, path, uid);
    if (!gadget) {
        ERR("Could not create new gadget\n");
        return NULL;
    }

    return gadget;
}

const char *
efl_gadget_path_get(Evas_Object *gadget)
{
    SMART_DATA_GET_OR_RETURN_NULL(gadget, priv);
    return priv->path;
}

const char *
efl_gadget_uid_get(Evas_Object *gadget)
{
    SMART_DATA_GET_OR_RETURN_NULL(gadget, priv);
    return priv->uid;
}

void
efl_gadget_init(int argc, char *argv[])
{
    if (!g_type_init_count)
        g_type_init();
    g_type_init_count++;

    if (!gtk_init_count)
        gtk_init(&argc, &argv);
    gtk_init_count++;
}

void
efl_gadget_shutdown(void)
{
    if (g_type_init_count - 1 >= 0)
        g_type_init_count--;

    if (gtk_init_count - 1 >= 0)
        gtk_init_count--;
}

Generated by  Doxygen 1.6.0   Back to index