efl/src/lib/elementary/efl_ui_selection.c

287 lines
8.5 KiB
C

#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#define MY_CLASS EFL_UI_SELECTION_MIXIN
#define MY_CLASS_NAME "Efl.Ui.Selection"
#ifdef HAVE_ELEMENTARY_WL2
Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
#endif
EOLIAN static void
_efl_ui_selection_selection_get(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format,
void *data_func_data, Efl_Ui_Selection_Data_Ready data_func, Eina_Free_Cb data_func_free_cb, unsigned int seat)
{
Eo *sel_man = _efl_ui_selection_manager_get(obj);
efl_ui_selection_manager_selection_get(sel_man, obj, type, format,
data_func_data, data_func,
data_func_free_cb, seat);
}
EOLIAN static Eina_Future *
_efl_ui_selection_selection_set(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format, Eina_Slice data, unsigned int seat)
{
Eo *sel_man = _efl_ui_selection_manager_get(obj);
return efl_ui_selection_manager_selection_set(sel_man, obj, type, format, data, seat);
}
EOLIAN static void
_efl_ui_selection_selection_clear(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, unsigned int seat)
{
Eo *sel_man = _efl_ui_selection_manager_get(obj);
efl_ui_selection_manager_selection_clear(sel_man, obj, type, seat);
}
EOLIAN static Eina_Bool
_efl_ui_selection_has_owner(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, unsigned int seat)
{
Eo *sel_man = _efl_ui_selection_manager_get(obj);
return efl_ui_selection_manager_selection_has_owner(sel_man, obj, type, seat);
}
////////// Support legacy APIs
//TODO: Clear this list (when sel_man is deleted)
Eina_List *lost_cb_list = NULL;
#ifdef HAVE_ELEMENTARY_WL2
static Ecore_Evas *
_wl_is_wl(const Evas_Object *obj)
{
Ecore_Evas *ee;
Evas *evas;
const char *engine_name;
if (!(evas = evas_object_evas_get(obj)))
return NULL;
if (!(ee = ecore_evas_ecore_evas_get(evas)))
return NULL;
engine_name = ecore_evas_engine_name_get(ee);
if (!strcmp(engine_name, ELM_BUFFER))
{
ee = ecore_evas_buffer_ecore_evas_parent_get(ee);
if (!ee) return NULL;
engine_name = ecore_evas_engine_name_get(ee);
}
if (!strncmp(engine_name, "wayland", sizeof("wayland") - 1))
return ee;
return NULL;
}
int
_wl_default_seat_id_get(Evas_Object *obj)
{
Ecore_Wl2_Window *win = _wl_window_get(obj);
Eo *seat, *parent2, *ewin;
Eina_Bool is_wl = EINA_FALSE;
if (obj)
{
if (_wl_is_wl(obj)) is_wl = EINA_TRUE;
if (efl_isa(obj, EFL_UI_WIDGET_CLASS))
{
Eo *top = elm_widget_top_get(obj);
if (efl_isa(top, EFL_UI_WIN_INLINED_CLASS))
{
parent2 = efl_ui_win_inlined_parent_get(top);
if (parent2) obj = elm_widget_top_get(parent2) ?: parent2;
}
/* fake win means canvas seat id will not match protocol seat id */
ewin = elm_win_get(obj);
if (elm_win_type_get(ewin) == ELM_WIN_FAKE) obj = NULL;
}
}
if (!obj)
{
if (is_wl)
{
Ecore_Wl2_Input *input;
Eina_Iterator *it;
it = ecore_wl2_display_inputs_get(ecore_wl2_window_display_get(win));
EINA_ITERATOR_FOREACH(it, input) break;
eina_iterator_free(it);
if (input)
return ecore_wl2_input_seat_id_get(input);
}
}
seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT);
EINA_SAFETY_ON_NULL_RETURN_VAL(seat, 1);
return evas_device_seat_id_get(seat);
}
#endif
typedef struct _Cnp_Data_Cb_Wrapper Cnp_Data_Cb_Wrapper;
struct _Cnp_Data_Cb_Wrapper
{
void *udata;
Elm_Drop_Cb datacb;
};
static void
_selection_data_ready_cb(void *data, Efl_Object *obj, Efl_Ui_Selection_Data *seldata)
{
Cnp_Data_Cb_Wrapper *wdata = data;
if (!wdata) return;
Elm_Selection_Data ddata;
ddata.data = calloc(1, seldata->content.len + 1);
if (!ddata.data) return;
ddata.data = memcpy(ddata.data, seldata->content.mem, seldata->content.len);
ddata.len = seldata->content.len;
ddata.x = seldata->pos.x;
ddata.y = seldata->pos.y;
ddata.format = (Elm_Sel_Format)seldata->format;
ddata.action = (Elm_Xdnd_Action)seldata->action;
wdata->datacb(wdata->udata, obj, &ddata);
free(ddata.data);
}
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 Eina_Value
_selection_lost_cb(void *data, const Eina_Value value)
{
Eina_List *l, *l2;
Sel_Lost_Data *ldata, *ldata2;
ldata = data;
EINA_LIST_FOREACH_SAFE(lost_cb_list, l, l2, ldata2)
{
if ((ldata->obj == ldata2->obj) &&
(ldata->type == ldata2->type))
{
ldata2->loss_cb(ldata2->udata, ldata2->type);
lost_cb_list = eina_list_remove(lost_cb_list, ldata2);
}
}
free(ldata);
return value;
}
EAPI Eina_Bool
elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type type,
Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
{
int seatid = 1;
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
Cnp_Data_Cb_Wrapper *wdata = calloc(1, sizeof(Cnp_Data_Cb_Wrapper));
if (!wdata) return EINA_FALSE;
#ifdef HAVE_ELEMENTARY_WL2
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get((Evas_Object *)obj);
#endif
wdata->udata = udata;
wdata->datacb = datacb;
efl_ui_selection_manager_selection_get(sel_man, (Evas_Object *)obj, (Efl_Ui_Selection_Type)type,
(Efl_Ui_Selection_Format)format,
wdata, _selection_data_ready_cb, NULL, seatid);
return EINA_TRUE;
}
EAPI Eina_Bool
elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type type,
Elm_Sel_Format format, const void *selbuf, size_t buflen)
{
int seatid = 1;
Eina_Future *f;
Sel_Lost_Data *ldata;
Eo *sel_man = _efl_ui_selection_manager_get(obj);
Eina_Slice data;
ldata = calloc(1, sizeof(Sel_Lost_Data));
if (!ldata) return EINA_FALSE;
data.mem = selbuf;
data.len = buflen;
#ifdef HAVE_ELEMENTARY_WL2
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
#endif
f = efl_ui_selection_manager_selection_set(sel_man, obj, (Efl_Ui_Selection_Type)type,
(Efl_Ui_Selection_Format)format, data, seatid);
ldata->obj = obj;
ldata->type = type;
eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
return EINA_TRUE;
}
EAPI Eina_Bool
elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type type)
{
int seatid = 1;
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
#ifdef HAVE_ELEMENTARY_WL2
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
#endif
efl_ui_selection_manager_selection_clear(sel_man, obj, (Efl_Ui_Selection_Type)type, seatid);
return EINA_TRUE;
}
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 HAVE_ELEMENTARY_COCOA
// Currently, we have no way to track changes in Cocoa pasteboard.
// Therefore, don't track this...
return;
#endif
if (!ldata) return;
ldata->obj = obj;
ldata->type = type;
ldata->udata = (void *)data;
ldata->loss_cb = func;
lost_cb_list = eina_list_append(lost_cb_list, ldata);
}
EAPI Eina_Bool
elm_selection_selection_has_owner(Evas_Object *obj)
{
int seatid = 1;
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
#ifdef HAVE_ELEMENTARY_WL2
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
#endif
return efl_ui_selection_manager_selection_has_owner(sel_man, obj,
EFL_UI_SELECTION_TYPE_CLIPBOARD, seatid);
}
EAPI Eina_Bool
elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
{
int seatid = 1;
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
#ifdef HAVE_ELEMENTARY_WL2
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
#endif
return efl_ui_selection_manager_selection_has_owner(sel_man, obj,
EFL_UI_SELECTION_TYPE_CLIPBOARD, seatid);
}
#include "efl_ui_selection.eo.c"