efl/src/lib/elementary/elm_cnp.c

253 lines
7.4 KiB
C

#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include <Ecore_Evas.h>
#include "elm_priv.h"
#include "elm_entry_eo.h"
static inline Ecore_Evas_Selection_Buffer
_elm_sel_type_to_ee_type(Elm_Sel_Type type)
{
if (type == ELM_SEL_TYPE_PRIMARY)
return ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER;
if (type == ELM_SEL_TYPE_XDND)
return ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER;
if (type == ELM_SEL_TYPE_CLIPBOARD)
return ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER;
return ECORE_EVAS_SELECTION_BUFFER_LAST;
}
static inline Eina_Array*
_elm_sel_format_to_mime_type(Elm_Sel_Format format)
{
Eina_Array *ret = eina_array_new(10);
if (format & ELM_SEL_FORMAT_TEXT)
eina_array_push(ret, "text/plain;charset=utf-8");
if (format & ELM_SEL_FORMAT_MARKUP)
eina_array_push(ret, "application/x-elementary-markup");
if (format & ELM_SEL_FORMAT_IMAGE)
{
eina_array_push(ret, "image/png");
eina_array_push(ret, "image/jpeg");
eina_array_push(ret, "image/x-ms-bmp");
eina_array_push(ret, "image/gif");
eina_array_push(ret, "image/tiff");
eina_array_push(ret, "image/svg+xml");
eina_array_push(ret, "image/x-xpixmap");
eina_array_push(ret, "image/x-tga");
eina_array_push(ret, "image/x-portable-pixmap");
}
if (format & ELM_SEL_FORMAT_VCARD)
eina_array_push(ret, "text/vcard");
if (format & ELM_SEL_FORMAT_HTML)
eina_array_push(ret, "application/xhtml+xml");
if (eina_array_count(ret) == 0)
ERR("Specified mime type is not available");
return ret;
}
static inline Elm_Sel_Format
_mime_type_to_elm_sel_format(const char *mime_type)
{
if (eina_streq(mime_type, "text/vcard"))
return ELM_SEL_FORMAT_VCARD;
else if (eina_streq(mime_type, "application/x-elementary-markup"))
return ELM_SEL_FORMAT_MARKUP;
else if (eina_streq(mime_type, "application/xhtml+xml"))
return ELM_SEL_FORMAT_HTML;
else if (!strncmp(mime_type, "text/", strlen("text/")))
return ELM_SEL_FORMAT_TEXT;
else if (!strncmp(mime_type, "image/", strlen("image/")))
return ELM_SEL_FORMAT_IMAGE;
return ELM_SEL_FORMAT_NONE;
}
static int
_default_seat(const Eo *obj)
{
return evas_device_seat_id_get(evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT));
}
EAPI Eina_Bool
elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
Elm_Sel_Format format,
const void *buf, size_t buflen)
{
Eina_Content *content;
Ecore_Evas *ee;
const char *mime_type;
Eina_Slice data;
Eina_Array *tmp;
unsigned char *mem_buf = NULL;
if (format == ELM_SEL_FORMAT_TEXT && ((char*)buf)[buflen - 1] != '\0')
{
mem_buf = eina_memdup((unsigned char *)buf, buflen, EINA_TRUE);
data.mem = mem_buf;
data.len = buflen + 1;
}
else
{
data.mem = buf;
data.len = buflen;
}
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
tmp = _elm_sel_format_to_mime_type(format);
if (eina_array_count(tmp) != 1)
{
ERR("You cannot specify more than one format when setting selection");
}
mime_type = eina_array_data_get(tmp, 0);
eina_array_free(tmp);
content = eina_content_new(data, mime_type);
_register_selection_changed(obj);
if (mem_buf != NULL)
free(mem_buf);
return ecore_evas_selection_set(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), content);
}
EAPI Eina_Bool
elm_object_cnp_selection_clear(Evas_Object *obj,
Elm_Sel_Type selection)
{
Ecore_Evas *ee;
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
return ecore_evas_selection_set(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), NULL);
}
EAPI Eina_Bool
elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
{
Ecore_Evas *ee;
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
return ecore_evas_selection_exists(ee, _default_seat(obj), ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER);
}
typedef struct _Sel_Lost_Data Sel_Lost_Data;
struct _Sel_Lost_Data
{
const Evas_Object *obj;
Elm_Sel_Type type;
void *udata;
Elm_Selection_Loss_Cb loss_cb;
};
static void
_selection_changed_cb(void *data, const Efl_Event *ev)
{
Sel_Lost_Data *ldata = data;
Efl_Ui_Wm_Selection_Changed *changed = ev->info;
if (changed->buffer == EFL_UI_CNP_BUFFER_SELECTION && ldata->type != ELM_SEL_TYPE_PRIMARY)
return;
if (changed->buffer == EFL_UI_CNP_BUFFER_COPY_AND_PASTE && ldata->type != ELM_SEL_TYPE_CLIPBOARD)
return;
if (ldata->obj == changed->caused_by)
return;
ldata->loss_cb(ldata->udata, ldata->type);
efl_event_callback_del(ev->object, ev->desc, _selection_changed_cb, data);
free(data);
}
EAPI void
elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type, Elm_Selection_Loss_Cb func, const void *data)
{
Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data));
if (!ldata) return;
ldata->obj = obj;
ldata->type = type;
ldata->udata = (void *)data;
ldata->loss_cb = func;
efl_event_callback_add(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, _selection_changed_cb, ldata);
}
typedef struct {
Elm_Drop_Cb data_cb;
void *data;
Elm_Sel_Format format;
} Callback_Storage;
static Eina_Value
_callback_storage_deliver(Eo *obj, void *data, const Eina_Value value)
{
Callback_Storage *cb_storage = data;
Eina_Content *content = eina_value_to_content(&value);
Elm_Sel_Format format = _mime_type_to_elm_sel_format(eina_content_type_get(content));
Eina_Slice cdata;
cdata = eina_content_data_get(content);
Elm_Selection_Data d = { 0 };
d.data = eina_memdup((unsigned char*)cdata.bytes, cdata.len, EINA_FALSE);
d.len = cdata.len;
d.format = _mime_type_to_elm_sel_format(eina_content_type_get(content));
if (cb_storage->data_cb)
{
cb_storage->data_cb(cb_storage->data, obj, &d);
}
else
{
EINA_SAFETY_ON_FALSE_GOTO(format == ELM_SEL_FORMAT_TEXT || format == ELM_SEL_FORMAT_MARKUP || format == ELM_SEL_FORMAT_HTML, end);
_elm_entry_entry_paste(obj, (const char *) d.data);
}
end:
free(d.data);
return EINA_VALUE_EMPTY;
}
static Eina_Value
_callback_storage_error(Eo *obj EINA_UNUSED, void *data EINA_UNUSED, Eina_Error error)
{
ERR("Content cound not be received because of %s.", eina_error_msg_get(error));
return EINA_VALUE_EMPTY;
}
static void
_callback_storage_free(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
{
free(data);
}
EAPI Eina_Bool
elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection,
Elm_Sel_Format format,
Elm_Drop_Cb data_cb, void *udata)
{
Ecore_Evas *ee;
Eina_Array *mime_types;
Eina_Future *future;
Callback_Storage *storage;
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
mime_types = _elm_sel_format_to_mime_type(format);
future = ecore_evas_selection_get(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), eina_array_iterator_new(mime_types));
storage = calloc(1,sizeof(Callback_Storage));
storage->data_cb = data_cb;
storage->data = udata;
storage->format = format;
efl_future_then(obj, future, _callback_storage_deliver, _callback_storage_error, _callback_storage_free, EINA_VALUE_TYPE_CONTENT, storage);
return EINA_TRUE;
}