cnp: add Copy & Paste support for Windows

It needs the clipboard management in Ecore_Win32

@feature

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Vincent Torri 2015-10-15 23:13:42 +02:00 committed by Cedric BAIL
parent aa93516e5f
commit 8042bc82d3
6 changed files with 457 additions and 1 deletions

View File

@ -3969,6 +3969,320 @@ _local_elm_selection_selection_has_owner(Evas_Object *obj EINA_UNUSED)
}
#endif
// win32 specific stuff
////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_ELEMENTARY_WIN32
typedef struct _Win32_Cnp_Selection Win32_Cnp_Selection;
struct _Win32_Cnp_Selection
{
const char *debug;
Evas_Object *widget;
char *selbuf;
Evas_Object *requestwidget;
void *udata;
Elm_Sel_Format requestformat;
Elm_Drop_Cb datacb;
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);
Elm_Selection_Loss_Cb loss_cb;
void *loss_data;
Elm_Sel_Format format;
Ecore_Win32_Selection ecore_sel;
Ecore_Win32_Window *win;
Elm_Xdnd_Action action;
Eina_Bool active : 1;
};
#define ARRAYINIT(foo) [foo] =
static Win32_Cnp_Selection _win32_selections[ELM_SEL_TYPE_CLIPBOARD + 1] =
{
ARRAYINIT(ELM_SEL_TYPE_PRIMARY)
{
.debug = "Primary",
.ecore_sel = ECORE_WIN32_SELECTION_PRIMARY,
.set = ecore_win32_clipboard_set,
.clear = ecore_win32_clipboard_clear,
.get = ecore_win32_clipboard_get,
},
ARRAYINIT(ELM_SEL_TYPE_SECONDARY)
{
.debug = "Secondary",
.ecore_sel = ECORE_WIN32_SELECTION_OTHER,
},
ARRAYINIT(ELM_SEL_TYPE_XDND)
{
.debug = "XDnD",
.ecore_sel = ECORE_WIN32_SELECTION_OTHER,
},
ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD)
{
.debug = "Clipboard",
.ecore_sel = ECORE_WIN32_SELECTION_CLIPBOARD,
.set = ecore_win32_clipboard_set,
.clear = ecore_win32_clipboard_clear,
.get = ecore_win32_clipboard_get,
}
};
static void
_win32_sel_obj_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Win32_Cnp_Selection *sel = data;
if (sel->widget == obj) sel->widget = NULL;
if (dragwidget == obj) dragwidget = NULL;
}
static void
_win32_sel_obj_del2(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Win32_Cnp_Selection *sel = data;
if (sel->requestwidget == obj) sel->requestwidget = NULL;
}
static Eina_Bool
_win32_elm_cnp_init(void)
{
static int _init_count = 0;
if (_init_count > 0) return EINA_TRUE;
_init_count++;
return EINA_TRUE;
}
static Ecore_Win32_Window *
_win32_elm_widget_window_get(const Evas_Object *obj)
{
Evas_Object *top;
Ecore_Win32_Window *win = NULL;
if (elm_widget_is(obj))
{
top = elm_widget_top_get(obj);
if (!top)
{
Evas_Object *par;
par = elm_widget_parent_widget_get(obj);
if (par) top = elm_widget_top_get(par);
}
if (top && (eo_isa(top, ELM_WIN_CLASS)))
win = elm_win_win32_window_get(top);
}
if (!win)
{
Ecore_Evas *ee;
Evas *evas;
const char *engine_name;
evas = evas_object_evas_get(obj);
if (!evas) return NULL;
ee = ecore_evas_ecore_evas_get(evas);
if (!ee) 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;
win = ecore_evas_win32_window_get(ee);
}
else
{
if ((strcmp(engine_name, ELM_SOFTWARE_WIN32) == 0) ||
(strcmp(engine_name, ELM_SOFTWARE_DDRAW) == 0))
return ecore_evas_win32_window_get(ee);
}
}
return win;
}
static Eina_Bool
_win32_elm_cnp_selection_set(Ecore_Win32_Window *win, Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen)
{
Win32_Cnp_Selection *sel;
if (selection != ELM_SEL_TYPE_CLIPBOARD)
return EINA_FALSE;
_win32_elm_cnp_init();
if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
return elm_object_cnp_selection_clear(obj, selection);
sel = _win32_selections + selection;
if (sel->widget != obj && sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
if (sel->widget)
evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
_win32_sel_obj_del, sel);
sel->active = EINA_TRUE;
sel->widget = obj;
sel->win = win;
if (sel->set) sel->set(win, selbuf, buflen);
sel->format = format;
sel->loss_cb = NULL;
sel->loss_data = NULL;
evas_object_event_callback_add
(sel->widget, EVAS_CALLBACK_DEL, _win32_sel_obj_del, sel);
ELM_SAFE_FREE(sel->selbuf, free);
if (selbuf)
{
if (format == ELM_SEL_FORMAT_IMAGE)
{
// selbuf is actual image data, not text/string
sel->selbuf = malloc(buflen + 1);
if (!sel->selbuf)
{
elm_object_cnp_selection_clear(obj, selection);
return EINA_FALSE;
}
memcpy(sel->selbuf, selbuf, buflen);
sel->selbuf[buflen] = 0;
}
else
sel->selbuf = strdup((char*)selbuf);
}
return EINA_TRUE;
}
static void
_win32_elm_cnp_selection_loss_callback_set(Evas_Object *obj EINA_UNUSED, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data)
{
Win32_Cnp_Selection *sel;
if (selection != ELM_SEL_TYPE_CLIPBOARD)
return;
_win32_elm_cnp_init();
sel = _win32_selections + selection;
sel->loss_cb = func;
sel->loss_data = (void *)data;
}
static Eina_Bool
_win32_elm_object_cnp_selection_clear(Ecore_Win32_Window *win, Evas_Object *obj, Elm_Sel_Type selection)
{
Win32_Cnp_Selection *sel;
if (selection != ELM_SEL_TYPE_CLIPBOARD)
return EINA_FALSE;
_win32_elm_cnp_init();
sel = _win32_selections + selection;
/* No longer this selection: Consider it gone! */
if ((!sel->active) || (sel->widget != obj))
return EINA_TRUE;
if (sel->widget)
evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
_win32_sel_obj_del, sel);
if (sel->requestwidget)
evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
_win32_sel_obj_del2, sel);
sel->widget = NULL;
sel->requestwidget = NULL;
sel->loss_cb = NULL;
sel->loss_data = NULL;
sel->active = EINA_FALSE;
ELM_SAFE_FREE(sel->selbuf, free);
/* sel->clear(win); */
return EINA_TRUE;
}
static Eina_Bool
_win32_elm_cnp_selection_get(Ecore_Win32_Window *win,
const Evas_Object *obj,
Elm_Sel_Type selection,
Elm_Sel_Format format,
Elm_Drop_Cb datacb,
void *udata)
{
Win32_Cnp_Selection *sel;
void *data;
int size;
if (selection != ELM_SEL_TYPE_CLIPBOARD)
return EINA_FALSE;
_win32_elm_cnp_init();
sel = _win32_selections + selection;
if (sel->requestwidget)
evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
_win32_sel_obj_del2, sel);
sel->requestformat = format;
sel->requestwidget = (Evas_Object *)obj;
sel->win = win;
sel->get(win, &data, &size);
sel->datacb = datacb;
sel->udata = udata;
if (!data || (size <= 0))
goto cb_add;
if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
(sel->format & ELM_SEL_FORMAT_HTML))
{
char *str;
str = (char *)malloc(size + 1);
if (str)
{
memcpy(str, data, size);
str[size] = '\0';
data = _elm_util_mkup_to_text(str);
free(str);
if (data)
size = strlen(data);
else
size = 0;
}
else
{
free(data);
data = NULL;
}
}
if (sel->datacb && data && (size > 0))
{
Elm_Selection_Data sdata;
sdata.x = sdata.y = 0;
sdata.format = ELM_SEL_FORMAT_TEXT;
sdata.data = data;
sdata.len = size;
sdata.action = sel->action;
sel->datacb(sel->udata, sel->requestwidget, &sdata);
}
if (data)
free(data);
cb_add:
evas_object_event_callback_add
(sel->requestwidget, EVAS_CALLBACK_DEL, _win32_sel_obj_del2, sel);
return EINA_TRUE;
}
#endif /* HAVE_ELEMENTARY_WIN32 */
// common internal funcs
////////////////////////////////////////////////////////////////////////////
static Eina_Bool
@ -4113,6 +4427,13 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
Ecore_Cocoa_Window *win = _cocoa_elm_widget_cocoa_window_get(obj);
if (win)
return _cocoa_elm_cnp_selection_set(win, obj, selection, format, selbuf, buflen);
#endif
#ifdef HAVE_ELEMENTARY_WIN32
Ecore_Win32_Window *win;
win = _win32_elm_widget_window_get(obj);
if (win)
return _win32_elm_cnp_selection_set(win, obj, selection, format, selbuf, buflen);
#endif
return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
}
@ -4135,6 +4456,10 @@ elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection,
#ifdef HAVE_ELEMENTARY_COCOA
if (_cocoa_elm_widget_cocoa_window_get(obj))
_cocoa_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
#endif
#ifdef HAVE_ELEMENTARY_WIN32
if (_win32_elm_widget_window_get(obj))
_win32_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
#endif
_local_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
}
@ -4155,6 +4480,13 @@ elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
#ifdef HAVE_ELEMENTARY_COCOA
if (_cocoa_elm_widget_cocoa_window_get(obj))
return _cocoa_elm_cnp_selection_clear(obj, selection);
#endif
#ifdef HAVE_ELEMENTARY_WIN32
Ecore_Win32_Window *win;
win = _win32_elm_widget_window_get(obj);
if (win)
return _win32_elm_object_cnp_selection_clear(win, obj, selection);
#endif
return _local_elm_object_cnp_selection_clear(obj, selection);
}
@ -4178,6 +4510,13 @@ elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection,
Ecore_Cocoa_Window *win = _cocoa_elm_widget_cocoa_window_get(obj);
if (win)
return _cocoa_elm_cnp_selection_get(obj, win, selection, format, datacb, udata);
#endif
#ifdef HAVE_ELEMENTARY_WIN32
Ecore_Win32_Window *win;
win = _win32_elm_widget_window_get(obj);
if (win)
return _win32_elm_cnp_selection_get(win, obj, selection, format, datacb, udata);
#endif
return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata);
}

View File

@ -3364,7 +3364,7 @@ _elm_config_file_monitor_cb(void *data EINA_UNUSED,
void
_elm_config_sub_init(void)
{
#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WL2)
#if defined(HAVE_ELEMENTARY_X) || defined(HAVE_ELEMENTARY_WL2) || defined(HAVE_ELEMENTARY_WIN32)
const char *ev = getenv("ELM_DISPLAY");
#endif
@ -3442,6 +3442,9 @@ _elm_config_sub_init(void)
#endif
#ifdef HAVE_ELEMENTARY_COCOA
ecore_cocoa_init();
#endif
#ifdef HAVE_ELEMENTARY_WIN32
ecore_win32_init();
#endif
char buf[PATH_MAX];
size_t len;

View File

@ -20,6 +20,9 @@
#endif
# include <Ecore_Cocoa.h>
#endif
#ifdef HAVE_ELEMENTARY_WIN32
#include <Ecore_Win32.h>
#endif
#include <Eio.h>

View File

@ -123,6 +123,12 @@ struct _Elm_Win_Data
Ecore_Cocoa_Window *win;
} cocoa;
#endif
#ifdef HAVE_ELEMENTARY_WIN32
struct
{
Ecore_Win32_Window *win;
} win32;
#endif
Ecore_Job *deferred_resize_job;
Ecore_Job *deferred_child_eval_job;
@ -2193,6 +2199,28 @@ _elm_ee_cocoa_win_get(const Ecore_Evas *ee)
engine_name = ecore_evas_engine_name_get(ee);
if (EINA_UNLIKELY(!engine_name)) return NULL;
if ((!strcmp(engine_name, ELM_SOFTWARE_WIN32)) ||
(!strcmp(engine_name, ELM_SOFTWARE_DDRAW)))
{
return ecore_evas_win32_window_get(ee);
}
#else
(void)ee;
#endif
return NULL;
}
Ecore_Win32_Window *
_elm_ee_win32win_get(const Ecore_Evas *ee)
{
#ifdef HAVE_ELEMENTARY_WIN32
const char *engine_name;
if (!ee) return NULL;
engine_name = ecore_evas_engine_name_get(ee);
if (EINA_UNLIKELY(!engine_name)) return NULL;
if (!strcmp(engine_name, "opengl_cocoa") ||
!strcmp(engine_name, "gl_cocoa"))
return ecore_evas_cocoa_window_get(ee);
@ -2210,6 +2238,14 @@ _elm_win_cocoawindow_get(Elm_Win_Data *sd)
}
#endif
#ifdef HAVE_ELEMENTARY_WIN32
static void
_internal_elm_win_win32window_get(Elm_Win_Data *sd)
{
sd->win32.win = _elm_ee_win32win_get(sd->ee);
}
#endif
#ifdef HAVE_ELEMENTARY_X
static void
_elm_win_xwin_update(Elm_Win_Data *sd)
@ -3756,6 +3792,9 @@ _elm_win_finalize_internal(Eo *obj, Elm_Win_Data *sd, const char *name, Elm_Win_
#ifdef HAVE_ELEMENTARY_COCOA
_elm_win_cocoawindow_get(sd);
#endif
#ifdef HAVE_ELEMENTARY_WIN32
_internal_elm_win_win32window_get(sd);
#endif
if ((_elm_config->bgpixmap)
#ifdef HAVE_ELEMENTARY_X
@ -5472,6 +5511,41 @@ _elm_win_wl_window_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
return NULL;
}
EAPI Ecore_Win32_Window *
elm_win_win32_window_get(const Evas_Object *obj)
{
ELM_WIN_CHECK(obj) NULL;
ELM_WIN_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
const char *engine_name = ecore_evas_engine_name_get(sd->ee);
if (!(engine_name &&
((!strcmp(engine_name, ELM_SOFTWARE_WIN32)) ||
(!strcmp(engine_name, ELM_SOFTWARE_DDRAW)))))
return NULL;
if (!evas_object_smart_type_check_ptr(obj, MY_CLASS_NAME_LEGACY))
{
Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
return _elm_ee_win32win_get(ee);
}
Ecore_Win32_Window *ret = NULL;
eo_do((Eo *) obj, ret = elm_obj_win_win32_window_get());
return ret;
}
EOLIAN static Ecore_Win32_Window *
_elm_win_win32_window_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
{
#if HAVE_ELEMENTARY_WIN32
if (sd->win32.win) return sd->win32.win;
if (sd->parent) return elm_win_win32_window_get(sd->parent);
#else
(void)sd;
#endif
return NULL;
}
EAPI Eina_Bool
elm_win_trap_set(const Elm_Win_Trap *t)
{
@ -5565,6 +5639,16 @@ _elm_win_window_id_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
eo_do(sd->parent, pwin = elm_obj_win_cocoa_window_get());
return (Ecore_Window)pwin;
}
#endif
}
else if ((engine_name &&
((!strcmp(engine_name, ELM_SOFTWARE_WIN32)) ||
(!strcmp(engine_name, ELM_SOFTWARE_DDRAW)))))
{
#ifdef HAVE_ELEMENTARY_WIN32
_internal_elm_win_win32window_get(sd);
if (sd->win32.win) return (Ecore_Window)sd->win32.win;
if (sd->parent) return (Ecore_Window)elm_win_win32_window_get(sd->parent);
#endif
}

View File

@ -965,6 +965,16 @@ class Elm.Win (Elm.Widget, Elm_Interface_Atspi_Window,
get {
[[Get the Ecore_Cocoa_Window of an Evas.Object.]]
return: Ecore_Cocoa_Window *; [[The Ecore_Cocoa_Window of $obj.]]
}
}
@property win32_window {
get {
[[Get the Ecore_Win32_Window of an Evas_Object
@since 1.16
]]
return: Ecore_Win32_Window *; [[The Ecore_Win32_Window of $obj.]]
legacy: null;
}
}
@property window_id {

View File

@ -197,6 +197,23 @@ EAPI void elm_win_render(Evas_Object *obj);
*/
EAPI Ecore_Wl2_Window *elm_win_wl_window_get(const Evas_Object *obj);
/* Windows specific call - returns NULL on non-Windows engines */
/**
* Get the Ecore_Win32_Window of an Evas_Object
*
* Do not use this function if you'd like your application/library be portable.
* You have been warned.
*
* @param obj the object
*
* @return The Ecore_Win32_Window of @p obj
*
* @ingroup Win
*
* @since 1.16
*/
EAPI Ecore_Win32_Window *elm_win_win32_window_get(const Evas_Object *obj);
/**
* Set the preferred rotation value.
*