From 6ea2e696ffd3a5c4bade206562ccb0c1b21a0951 Mon Sep 17 00:00:00 2001 From: Christopher Michael Date: Wed, 29 Aug 2012 06:52:48 +0000 Subject: [PATCH] Elementary: Copy-Paste support for Wayland Engines. NB: Based on patch from Alex , but cleaned up for compiler warnings. SVN revision: 75810 --- legacy/elementary/src/lib/elm_cnp.c | 172 ++++++++++++++++++++++---- legacy/elementary/src/lib/elm_entry.c | 12 ++ 2 files changed, 162 insertions(+), 22 deletions(-) diff --git a/legacy/elementary/src/lib/elm_cnp.c b/legacy/elementary/src/lib/elm_cnp.c index 44977f9c48..54a194b09f 100644 --- a/legacy/elementary/src/lib/elm_cnp.c +++ b/legacy/elementary/src/lib/elm_cnp.c @@ -98,19 +98,6 @@ static Tmp_Info *_tempfile_new (int size); static int _tmpinfo_free (Tmp_Info *tmp); static Eina_Bool _pasteimage_append (char *file, Evas_Object *entry); - - - - - - - - - -// x11 specific stuff -//////////////////////////////////////////////////////////////////////////// -#ifdef HAVE_ELEMENTARY_X -#define ARRAYINIT(foo) [foo] = //#define DEBUGON 1 #ifdef DEBUGON # define cnp_debug(x...) fprintf(stderr, __FILE__": " x) @@ -118,6 +105,11 @@ static Eina_Bool _pasteimage_append (char *file, Evas_Object *entry); # define cnp_debug(x...) do { } while (0) #endif +// x11 specific stuff +//////////////////////////////////////////////////////////////////////////// +#ifdef HAVE_ELEMENTARY_X +#define ARRAYINIT(foo) [foo] = + typedef struct _X11_Cnp_Selection X11_Cnp_Selection; typedef struct _X11_Cnp_Atom X11_Cnp_Atom; @@ -1534,6 +1526,124 @@ _x11_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__) #endif +#ifdef HAVE_ELEMENTARY_WAYLAND +typedef struct _Wl_Cnp_Selection Wl_Cnp_Selection; + +struct _Wl_Cnp_Selection +{ + char *selbuf; + int buflen; + + Evas_Object *widget; + Evas_Object *requestwidget; +}; + +static Wl_Cnp_Selection wl_cnp_selection = {0, 0, NULL, NULL}; + +static void +_wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + Wl_Cnp_Selection *sel = data; + if (sel->requestwidget == obj) sel->requestwidget = NULL; +} + +static Eina_Bool +_wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen) +{ + const char *types[10] = {0, }; + + /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */ + if (ELM_SEL_TYPE_CLIPBOARD == selection) + { + types[0] = "text/plain;charset=utf-8"; + ecore_wl_dnd_set_selection(ecore_wl_dnd_get(), types); + + if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf); + wl_cnp_selection.selbuf = strdup((char*)selbuf); + wl_cnp_selection.buflen = buflen; + return EINA_TRUE; + } + + return EINA_FALSE; +} + +static Eina_Bool +_wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__) +{ + /* For now, just avoid overlapped request */ + if (wl_cnp_selection.requestwidget) return EINA_FALSE; + + /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */ + if (ELM_SEL_TYPE_CLIPBOARD == selection) + { + wl_cnp_selection.requestwidget = obj; + evas_object_event_callback_add(wl_cnp_selection.requestwidget, EVAS_CALLBACK_DEL, + _wl_sel_obj_del2, &wl_cnp_selection); + ecore_wl_dnd_get_selection(ecore_wl_dnd_get(), "text/plain;charset=utf-8"); + } + return EINA_TRUE; +} + +static Eina_Bool +_wl_selection_send(void *udata, int type __UNUSED__, void *event) +{ + char *buf; + int ret, len_remained; + int len_written = 0; + Wl_Cnp_Selection *sel = udata; + Ecore_Wl_Event_Data_Source_Send *ev = event; + + len_remained = sel->buflen; + buf = sel->selbuf; + + while (len_written < sel->buflen) + { + ret = write(ev->fd, buf, len_remained); + if (ret == -1) break; + buf += ret; + len_written += ret; + len_remained -= ret; + } + + close(ev->fd); + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_wl_selection_receive(void *udata, int type __UNUSED__, void *event) +{ + Wl_Cnp_Selection *sel = udata; + Ecore_Wl_Event_Selection_Data_Ready *ev = event; + + if (sel->requestwidget) + { + if (!ev->done) + { + /* TODO BUG: should never NEVER assume it's an elm_entry! */ + _elm_entry_entry_paste(sel->requestwidget, ev->data); + } + else + { + evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, + _wl_sel_obj_del2, sel); + sel->requestwidget = NULL; + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool _wl_elm_cnp_init(void) +{ + ecore_event_handler_add(ECORE_WL_EVENT_DATA_SOURCE_SEND, + _wl_selection_send, &wl_cnp_selection); + ecore_event_handler_add(ECORE_WL_EVENT_SELECTION_DATA_READY, + _wl_selection_receive, &wl_cnp_selection); + + return EINA_TRUE; +} +#endif + @@ -1711,10 +1821,17 @@ _local_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__) // common internal funcs //////////////////////////////////////////////////////////////////////////// static Eina_Bool -_elm_cnp_init(void) +_elm_cnp_init(Evas_Object *obj) { if (_elm_cnp_init_count > 0) return EINA_TRUE; _elm_cnp_init_count++; +#ifdef HAVE_ELEMENTARY_X + if (_x11_elm_widget_xwin_get(obj)) _x11_elm_cnp_init(); +#endif +#ifdef HAVE_ELEMENTARY_WAYLAND + if (elm_win_wl_window_get(obj)) _wl_elm_cnp_init(); +#endif + _local_elm_cnp_init(); text_uri = eina_stringshare_add("text/uri-list"); return EINA_TRUE; } @@ -1838,10 +1955,14 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen) { if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE; - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); +#endif +#ifdef HAVE_ELEMENTARY_WAYLAND + if (elm_win_wl_window_get(obj)) + return _wl_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); #endif return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen); } @@ -1852,7 +1973,7 @@ elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection, const void *data) { if (selection > ELM_SEL_TYPE_CLIPBOARD) return; - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data); @@ -1864,7 +1985,7 @@ EAPI Eina_Bool elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection) { if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE; - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_object_cnp_selection_clear(obj, selection); @@ -1877,10 +1998,14 @@ elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata) { if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE; - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_cnp_selection_get(obj, selection, format, datacb, udata); +#endif +#ifdef HAVE_ELEMENTARY_WAYLAND + if (elm_win_wl_window_get(obj)) + return _wl_elm_cnp_selection_get(obj, selection, format, datacb, udata); #endif return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata); } @@ -1894,7 +2019,7 @@ EAPI Eina_Bool elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, void *cbdata) { - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_drop_target_add(obj, format, dropcb, cbdata); @@ -1905,7 +2030,7 @@ elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, EAPI Eina_Bool elm_drop_target_del(Evas_Object *obj) { - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_drop_target_del(obj); @@ -1917,7 +2042,7 @@ EAPI Eina_Bool elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (*dragdone) (void *data, Evas_Object *), void *donecbdata) { - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_drag_start(obj, format, data, dragdone, donecbdata); @@ -1928,10 +2053,13 @@ elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, EAPI Eina_Bool elm_selection_selection_has_owner(Evas_Object *obj) { - if (!_elm_cnp_init_count) _elm_cnp_init(); + if (!_elm_cnp_init_count) _elm_cnp_init(obj); #ifdef HAVE_ELEMENTARY_X if (_x11_elm_widget_xwin_get(obj)) return _x11_elm_selection_selection_has_owner(obj); +#endif +#ifdef HAVE_ELEMENTARY_WAYLAND + return ecore_wl_dnd_selection_has_owner(ecore_wl_dnd_get()); #endif return _local_elm_selection_selection_has_owner(obj); } diff --git a/legacy/elementary/src/lib/elm_entry.c b/legacy/elementary/src/lib/elm_entry.c index 703575cd4b..a6d1fa9a44 100644 --- a/legacy/elementary/src/lib/elm_entry.c +++ b/legacy/elementary/src/lib/elm_entry.c @@ -1272,6 +1272,18 @@ _paste(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) else if (wd->cnp_mode != ELM_CNP_MODE_NO_IMAGE) formats |= ELM_SEL_FORMAT_IMAGE; elm_cnp_selection_get(data, ELM_SEL_TYPE_CLIPBOARD, formats, NULL, NULL); +#endif + } + else + { +#ifdef HAVE_ELEMENTARY_WAYLAND + Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP; + wd->selection_asked = EINA_TRUE; + if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT) + formats = ELM_SEL_FORMAT_TEXT; + else if (wd->cnp_mode != ELM_CNP_MODE_NO_IMAGE) + formats |= ELM_SEL_FORMAT_IMAGE; + elm_cnp_selection_get(data, ELM_SEL_TYPE_CLIPBOARD, formats, NULL, NULL); #endif } }