cnp_dnd: add selection manager

Selection manager implements functions for selection (cnp)
and drag and drop.
All objects can uses it APIs. It also supports multi-seat.
This commit is contained in:
Thiep Ha 2018-01-08 19:13:10 +09:00
parent 1b4f330c9c
commit 763daa870e
8 changed files with 5903 additions and 1 deletions

View File

@ -127,6 +127,7 @@ elm_private_eolian_files = \
lib/elementary/efl_ui_focus_parent_provider_gen.eo \
tests/elementary/focus_test.eo \
tests/elementary/focus_test_sub_main.eo \
lib/elementary/efl_selection_manager.eo \
$(NULL)
# Legacy classes - not part of public EO API
@ -226,7 +227,9 @@ elm_legacy_eolian_files = \
elm_eolian_type_files = \
lib/elementary/elm_general.eot \
lib/elementary/efl_ui.eot \
lib/elementary/efl_ui_list_types.eot
lib/elementary/efl_ui_list_types.eot \
lib/elementary/efl_selection_types.eot \
lib/elementary/efl_ui_dnd_types.eot
elm_public_eolian_c = $(elm_public_eolian_files:%.eo=%.eo.c)
elm_public_eolian_h = $(elm_public_eolian_files:%.eo=%.eo.h) \
@ -757,6 +760,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_scroller.c \
lib/elementary/efl_ui_scroll_manager.c \
lib/elementary/efl_ui_pan.c \
lib/elementary/efl_selection_manager.c \
$(NULL)

View File

@ -321,6 +321,8 @@ EAPI extern Elm_Version *elm_version;
# include <efl_ui_list_pan.eo.h>
# include <efl_ui_scroll_manager.eo.h>
# include <efl_ui_scroller.eo.h>
# include "efl_selection_types.eot.h"
# include "efl_ui_dnd_types.eot.h"
# include <efl_ui_pan.eo.h>
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
import efl_ui_dnd_types;
class Efl.Selection.Manager (Efl.Object) {
methods {
selection_set @beta {
[[Set selection]]
params {
@in owner: Efl.Object; [[Seleciton owner]]
@in type: Efl.Selection.Type; [[Selection type]]
@in format: Efl.Selection.Format; [[Selection format]]
@in data: Eina.Slice; [[Selection data]]
@in seat: uint @optional;[[Specified seat for multiple seats case.]]
}
return: ptr(Eina.Future); [[Future for tracking when the selection is lost]]
}
selection_get @beta {
[[Get selection]]
params {
@in request: const(Efl.Object); [[Seleciton owner]]
@in type: Efl.Selection.Type; [[Selection type]]
@in format: Efl.Selection.Format; [[Selection Format]]
@in data_func: Efl.Selection.Data_Ready; [[Data ready function pointer]]
@in seat: uint @optional;[[Specified seat for multiple seats case.]]
}
}
selection_clear @beta {
params {
@in owner: Efl.Object; [[Seleciton owner]]
@in type: Efl.Selection.Type; [[Selection type]]
@in seat: uint @optional; [[Specified seat for multiple seats case.]]
}
}
selection_has_owner @beta {
[[Check if the request object has selection or not]]
params {
@in request: Efl.Object; [[Request object]]
@in type: Efl.Selection.Type; [[Selection type]]
@in seat: uint @optional; [[Specified seat for multiple seats case.]]
}
return: bool; [[EINA_TRUE if the request object has selection, otherwise, EINA_FALSE]]
}
drag_start @beta {
[[This starts a drag and drop process at the drag side.
During dragging, there are three events emitted as belows:
- EFL_UI_DND_EVENT_DRAG_POS
- EFL_UI_DND_EVENT_DRAG_ACCEPT
- EFL_UI_DND_EVENT_DRAG_DONE
]]
params {
@in drag_obj: Efl.Object; [[Drag object]]
@in format: Efl.Selection.Format; [[Data format]]
@in data: Eina.Slice; [[Data to transfer]]
@in action: Efl.Selection.Action; [[Action when data is transferred]]
@in icon_func: Efl.Dnd.Drag_Icon_Create; [[Function pointer to create icon]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
drag_action_set @beta {
[[This sets the action for the drag]]
params {
@in drag_obj: Efl.Object; [[Drag object]]
@in action: Efl.Selection.Action; [[Drag action]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
drag_cancel @beta {
[[This cancels the on-going drag]]
params {
@in drag_obj: Efl.Object; [[Drag object]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
container_drag_item_add @beta {
[[This registers a drag for items in a container. Many items can be
dragged at a time. During dragging, there are three events emitted:
- EFL_UI_DND_EVENT_DRAG_POS
- EFL_UI_DND_EVENT_DRAG_ACCEPT
- EFL_UI_DND_EVENT_DRAG_DONE.]]
params {
@in cont: Efl.Object; [[Container object]]
@in time_to_drag: double; [[Time since mouse down happens to drag starts]]
@in anim_duration: double; [[animation duration]]
@in data_func: Efl.Dnd.Drag_Data_Get; [[Data and its format]]
@in item_func: Efl.Dnd.Item_Get; [[Item to determine drag start]]
@in icon_func: Efl.Dnd.Drag_Icon_Create; [[Icon used during drag]]
@in icon_list_func: Efl.Dnd.Drag_Icon_List_Create; [[Icons used for animations]]
@in seat: uint; [[Specified seat for multiple seats case]]
}
}
container_drag_item_del @beta {
[[Remove drag function of items in the container object.]]
params {
@in cont: Efl.Object; [[Container object]]
@in seat: uint; [[Specified seat for multiple seats case]]
}
}
drop_target_add @beta {
[[Add a dropable target. There are four events emitted:
- EFL_UI_DND_DROP_DRAG_ENTER
- EFL_UI_DND_DROP_DRAG_LEAVE
- EFL_UI_DND_DROP_DRAG_POS
- EFL_UI_DND_DROP_DRAG_DROP.]]
params {
@in target_obj: Efl.Object; [[Drop target]]
@in format: Efl.Selection.Format; [[Accepted data format]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
return: bool; [[$true on success, $false otherwise]]
}
drop_target_del @beta {
[[Remove a dropable target]]
params {
@in target_obj: Efl.Object; [[Drop target]]
@in format: Efl.Selection.Format; [[Accepted data format]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
container_drop_item_add @beta {
[[Add dropable target for a container in which items can drop to it]]
params {
@in cont: Efl.Object; [[Container object]]
@in format: Efl.Selection.Format; [[Accepted data formats]]
@in item_func: Efl.Dnd.Item_Get; [[Get item at specific position]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
container_drop_item_del @beta {
[[Remove dropable target for the container]]
params {
@in cont: Efl.Object; [[Container object]]
@in seat: uint; [[Specified seat for multiple seats case.]]
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
}

View File

@ -0,0 +1,319 @@
#ifndef EFL_SELECTION_MANAGER_PRIVATE_H
#define EFL_SELECTION_MANAGER_PRIVATE_H
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
enum
{
SELECTION_ATOM_TARGETS = 0,
SELECTION_ATOM_ATOM,
SELECTION_ATOM_LISTING_ATOMS = SELECTION_ATOM_ATOM,
SELECTION_ATOM_TEXT_URILIST,
SELECTION_ATOM_TEXT_X_VCARD,
SELECTION_ATOM_IMAGE_PNG,
SELECTION_ATOM_IMAGE_JPEG,
SELECTION_ATOM_IMAGE_BMP,
SELECTION_ATOM_IMAGE_GIF,
SELECTION_ATOM_IMAGE_TIFF,
SELECTION_ATOM_IMAGE_SVG,
SELECTION_ATOM_IMAGE_XPM,
SELECTION_ATOM_IMAGE_TGA,
SELECTION_ATOM_IMAGE_PPM,
SELECTION_ATOM_ELM,
SELECTION_ATOM_UTF8STRING,
SELECTION_ATOM_STRING,
SELECTION_ATOM_COMPOUND_TEXT,
SELECTION_ATOM_TEXT,
SELECTION_ATOM_TEXT_PLAIN_UTF8,
SELECTION_ATOM_TEXT_PLAIN,
SELECTION_N_ATOMS,
};
typedef struct _Efl_Selection_Manager_Data Efl_Selection_Manager_Data;
typedef struct _Sel_Manager_Seat_Selection Sel_Manager_Seat_Selection;
typedef struct _Sel_Manager_Atom Sel_Manager_Atom;
typedef struct _Sel_Manager_Dropable Sel_Manager_Dropable;
typedef struct _Anim_Icon Anim_Icon;
typedef struct _Sel_Manager_Drag_Container Sel_Manager_Drag_Container;
typedef struct _Drop_Format Drop_Format;
typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info;
typedef struct _Sel_Manager_Selection Sel_Manager_Selection;
typedef struct _Tmp_Info Tmp_Info;
typedef struct _Saved_Type Saved_Type;
#ifdef HAVE_ELEMENTARY_X
typedef Eina_Bool (*X11_Converter_Fn_Cb) (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
typedef int (*X11_Response_Handler_Cb) (Sel_Manager_Selection *sel, Ecore_X_Event_Selection_Notify *);
typedef Eina_Bool (*X11_Data_Preparer_Cb) (Sel_Manager_Seat_Selection *seat_sel, Ecore_X_Event_Selection_Notify *, Efl_Selection_Data *, Tmp_Info **);
#endif
#ifdef HAVE_ELEMENTARY_WL2
typedef Eina_Bool (*Wl_Converter_Fn_Cb) (char *target, Sel_Manager_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
static Eina_Bool _wl_targets_converter(char *target, Sel_Manager_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
static Eina_Bool _wl_general_converter(char *target, Sel_Manager_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
static Eina_Bool _wl_text_converter(char *target, Sel_Manager_Selection *sel, void *data, int size, void **data_ret, int *size_ret);
typedef Eina_Bool (*Wl_Data_Preparer_Cb) (Sel_Manager_Selection *sel, Efl_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
static Eina_Bool _wl_data_preparer_markup(Sel_Manager_Selection *sel, Efl_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
static Eina_Bool _wl_data_preparer_uri(Sel_Manager_Selection *sel, Efl_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
static Eina_Bool _wl_data_preparer_vcard(Sel_Manager_Selection *sel, Efl_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
static Eina_Bool _wl_data_preparer_image(Sel_Manager_Selection *sel, Efl_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
static Eina_Bool _wl_data_preparer_text(Sel_Manager_Selection *sel, Efl_Selection_Data *ddata, Ecore_Wl2_Event_Offer_Data_Ready *ev, Tmp_Info **tmp_info);
#endif
struct _Tmp_Info
{
char *filename;
void *map;
int fd;
int len;
};
struct _Saved_Type
{
const char **types;
char *imgfile;
int ntypes;
Eina_Position2D pos;
Eina_Bool textreq: 1;
};
struct _Sel_Manager_Selection
{
const char *debug;
Eina_Rw_Slice data;
Efl_Selection_Format request_format;
#ifdef HAVE_ELEMENTARY_X
Eina_Bool (*set) (Ecore_X_Window, const void *data, int size);
Eina_Bool (*clear) (void);
void (*request) (Ecore_X_Window, const char *target);
Ecore_X_Selection ecore_sel;
Ecore_X_Window xwin;
#endif
#ifdef HAVE_ELEMENTARY_WL2
uint32_t selection_serial;
uint32_t drag_serial;
Ecore_Wl2_Offer *sel_offer;
Ecore_Wl2_Offer *dnd_offer;
Ecore_Event_Handler *offer_handler;
Ecore_Wl2_Window *win;
#endif
#ifdef HAVE_ELEMENTARY_COCOA
Ecore_Cocoa_Window *win;
int pb_count;
#endif
#ifdef HAVE_ELEMENTARY_WIN32
Eina_Bool (*set)(const Ecore_Win32_Window *window, const void *data, int size);
Eina_Bool (*clear)(const Ecore_Win32_Window *window);
Eina_Bool (*get)(const Ecore_Win32_Window *window , void **data, int *size);
Ecore_Win32_Selection ecore_sel;
Ecore_Win32_Window *win;
#endif
Efl_Selection_Format format;
Efl_Selection_Action action;
Eina_Bool active : 1;
Efl_Object *owner;
Efl_Object *request_obj;
void *data_func_data;
Efl_Selection_Data_Ready data_func;
Eina_Free_Cb data_func_free_cb;
Sel_Manager_Seat_Selection *seat_sel;
};
typedef struct _Sel_Manager_Selection_Lost Sel_Manager_Selection_Lost;
struct _Sel_Manager_Selection_Lost
{
Efl_Object *request;
Eina_Promise *promise;
Efl_Selection_Type type;
};
struct _Sel_Manager_Seat_Selection
{
unsigned int seat;
#ifdef HAVE_ELEMENTARY_X
Sel_Manager_Selection *sel_list;
#endif
#ifdef HAVE_ELEMENTARY_WL2
Sel_Manager_Selection *sel;
#endif
#ifdef HAVE_ELEMENTARY_COCOA
Sel_Manager_Selection *sel;
#endif
#ifdef HAVE_ELEMENTARY_WIN32
Sel_Manager_Selection *sel_list;
#endif
Eina_List *sel_lost_list;
//drag
Eo *drag_obj;
Efl_Selection_Action drag_action;
Eo *drag_win;
Ecore_Event_Handler *mouse_up_handler, *dnd_status_handler;
Eina_Bool accept;
Ecore_X_Window xwin;
Eina_Position2D drag_pos;
Eina_Position2D drag_win_start;
Eina_Position2D drag_win_end;
Efl_Selection_Type active_type;
Saved_Type *saved_types;
Ecore_Event_Handler *enter_handler;
Ecore_Event_Handler *leave_handler;
Ecore_Event_Handler *pos_handler;
Ecore_Event_Handler *drop_handler;
Efl_Selection_Manager_Data *pd;
};
struct _Anim_Icon
{
Eina_Rectangle start;
Evas_Object *obj;
};
struct _Sel_Manager_Drag_Container
{
Evas *e;
Efl_Object *cont;
Efl_Selection_Format format;
Eina_Rw_Slice data;
Efl_Selection_Action action;
Eina_List *icons;
Eina_Size2D final_icon;
Eina_Position2D down;
Ecore_Timer *timer;
Ecore_Animator *animator;
double time_to_drag;
double anim_duration;
void *drag_data_func_data;
Efl_Dnd_Drag_Data_Get drag_data_func;
Eina_Free_Cb drag_data_func_free_cb;
void *item_get_func_data;
Efl_Dnd_Item_Get item_get_func;
Eina_Free_Cb item_get_func_free_cb;
void *icon_func_data;
Efl_Dnd_Drag_Icon_Create icon_func;
Eina_Free_Cb icon_func_free_cb;
void *icon_list_func_data;
Efl_Dnd_Drag_Icon_List_Create icon_list_func;
Eina_Free_Cb icon_list_func_free_cb;
unsigned int seat;
Efl_Selection_Manager_Data *pd;
};
struct _Sel_Manager_Atom
{
const char *name;
Efl_Selection_Format format;
#ifdef HAVE_ELEMENTARY_X
// Called by ecore to do conversion
X11_Converter_Fn_Cb x_converter;
X11_Data_Preparer_Cb x_data_preparer;
// Atom
Ecore_X_Atom x_atom;
#endif
#ifdef HAVE_ELEMENTARY_WL2
Wl_Converter_Fn_Cb wl_converter;
Wl_Data_Preparer_Cb wl_data_preparer;
#endif
void *_term;
};
struct _Drop_Format
{
EINA_INLIST;
Efl_Selection_Format format;
};
struct _Sel_Manager_Dropable
{
Evas_Object *obj;
Eina_Inlist *format_list;
unsigned int seat;
struct {
Eina_Position2D pos;
Eina_Bool in : 1;
const char *type;
Efl_Selection_Format format;
} last;
//for container
Efl_Dnd_Item_Get item_func;
void *item_func_data;
Eina_Bool is_container : 1;
};
struct _Item_Container_Drop_Info
{
Efl_Object *obj;
void *item_func_data;
Efl_Dnd_Item_Get item_func;
};
#ifdef HAVE_ELEMENTARY_WL2
typedef struct _Wl_Format_Translation
{
Efl_Selection_Format format;
char **translates;
} Sel_Manager_Wl_Format_Translation;
char *sm_wl_markup[] = {"application/x-elementary-markup", "", NULL};
char *sm_wl_text[] = {"text/plain;charset=utf-8", "text/plain", NULL};
char *sm_wl_html[] = {"text/html;charset=utf-8", "text/html", NULL};
char *sm_wl_vcard[] = {"text/x-vcard", NULL};
char *sm_wl_image[] = {"image/", "text/uri-list", NULL};
Sel_Manager_Wl_Format_Translation sm_wl_convertion[] = {
{EFL_SELECTION_FORMAT_MARKUP, sm_wl_markup},
{EFL_SELECTION_FORMAT_TEXT, sm_wl_text},
{EFL_SELECTION_FORMAT_HTML, sm_wl_html},
{EFL_SELECTION_FORMAT_VCARD, sm_wl_vcard},
{EFL_SELECTION_FORMAT_IMAGE, sm_wl_image},
{EFL_SELECTION_FORMAT_NONE, NULL},
};
#endif
struct _Efl_Selection_Manager_Data
{
Eo *sel_man;
#ifdef HAVE_ELEMENTARY_X
Ecore_Event_Handler *notify_handler;
Ecore_Event_Handler *clear_handler;
Ecore_Event_Handler *fix_handler;
#endif
#ifdef HAVE_ELEMENTARY_WL2
Ecore_Event_Handler *send_handler;
Ecore_Event_Handler *changed_handler;
Ecore_Event_Handler *end_handler;
Ecore_Wl2_Display *wl_display;
#endif
Efl_Selection_Type loss_type;
Sel_Manager_Atom *atom_list;
Eina_List *seat_list;
Eina_List *drag_cont_list;
//drop
Eina_List *drop_list;
Eina_Hash *type_hash;
const char *text_uri;
Eina_List *drop_cont_list;
};
#endif

View File

@ -0,0 +1,59 @@
enum Efl.Selection.Type
{
[[Selection type]]
primary, [[Primary text selection (highlighted or selected text)]]
secondary, [[Used when primary selection is in use]]
dnd, [[Drag and Drop]]
clipboard [[Clipboard selection (ctrl+C)]]
}
enum Efl.Selection.Format
{
[[Selection format]]
targets = -1, [[For matching every possible atom]]
none = 0x0, [[Content is from outside of Elementary]]
text = 0x01, [[Plain unformatted text: Used for things that don't want rich markup]]
markup = 0x2, [[Edje textblock markup, including inline images]]
image = 0x4, [[Images]]
vcard = 0x08, [[Vcards]]
html = 0x10 [[Raw HTML-like data (eg. webkit)]]
}
enum Efl.Selection.Action
{
[[Defines the kind of action associated with the drop data]]
unknown, [[Action type is unknown]]
copy, [[Copy the data]]
move, [[Move the data]]
private, [[Private action type]]
ask, [[Ask the user what to do]]
list, [[List the data]]
link, [[Link the data]]
description [[Describe the data]]
}
struct Efl.Selection.Data
{
[[Structure holding the info about selected data]]
pos: Eina.Position2D; [[Coordinates of the drop (DND operations only)]]
format: Efl.Selection.Format; [[Format of the selection]]
data: Eina.Slice; [[Selection data]]
action: Efl.Selection.Action; [[Action to perform with the data]]
item: Efl.Object; [[Item under the drag position. It is only available for container]]
}
function Efl.Selection.Data_Ready {
[[Function pointer for getting selection]]
params {
@in obj: Efl.Object; [[Object which requested for the selection]]
@in seldata: ptr(Efl.Selection.Data); [[Selection data]]
}
};
struct Efl.Selection.Changed
{
type: Efl.Selection.Type; [[Selection type]]
seat: int; [[The seat on which the selection changed, or NULL for "default"]]
display: void_ptr; [[The display connection object, NULL under X11]]
exist: bool; [[EINA_TRUE if the selection has an owner]]
}

View File

@ -0,0 +1,58 @@
import efl_selection_types;
function Efl.Dnd.Drag_Icon_Create {
[[Function pointer for creating icon at the drag side.]]
params {
@in win: Efl.Canvas.Object; [[The window to create the objects relative to]]
@in drag_obj: Efl.Canvas.Object; [[The drag object]]
@out off: Eina.Position2D;
}
return: Efl.Canvas.Object; [[The drag icon object]]
};
function Efl.Dnd.Drag_Data_Get {
[[Function pointer for getting data and format at the drag side.]]
params {
@in obj: Efl.Canvas.Object; [[The container object]]
@out format: Efl.Selection.Format; [[Data format]]
@out drag_data: Eina.Rw_Slice; [[Data]]
@out action: Efl.Selection.Action; [[The drag action]]
}
};
function Efl.Dnd.Item_Get {
[[Function pointer to find out which item is under position (x, y)]]
params {
@in obj: Efl.Canvas.Object; [[The container object]]
@in pos: Eina.Position2D; [[The coordinates to get item]]
@out posret: Eina.Position2D; [[position relative to item (left (-1), middle (0), right (1)]]
}
return: ptr(Eo); [[Object under x,y coordinates or NULL if not found]]
};
function Efl.Dnd.Drag_Icon_List_Create {
[[Function pointer to create list of icons at the drag side.
These icons are used for animation on combining selection icons
to one icon.]]
params {
@in obj: Efl.Canvas.Object; [[The container object]]
}
return: ptr(Eina_List);
};
struct Efl.Dnd.Drag_Accept {
accepted: bool;
}
struct Efl.Dnd.Drag_Pos {
pos: Eina.Position2D; [[Evas Coordinate]]
action: Efl.Selection.Action; [[The drag action]]
format: Efl.Selection.Format; [[The drag format]]
item: Efl.Canvas.Object; [[The item object. It is only available for container object.]]
}
struct Efl.Dnd.Drag_Item_Container_Drop {
item: Efl.Canvas.Object; [[The item object]]
data: Efl.Selection.Data; [[The selection data]]
pos: Eina.Position2D; [[Position relative to item (left (-1), middle (0), right (1)]]
}

View File

@ -66,6 +66,7 @@
# include "efl_ui_focus_parent_provider.eo.h"
# include "efl_ui_focus_parent_provider_standard.eo.h"
# include "elm_widget_item_static_focus.eo.h"
#include "efl_selection_manager.eo.h"
# ifdef HAVE_LANGINFO_H
# include <langinfo.h>