diff --git a/legacy/elementary/ChangeLog b/legacy/elementary/ChangeLog index 2c643b95aa..8a86790ed8 100644 --- a/legacy/elementary/ChangeLog +++ b/legacy/elementary/ChangeLog @@ -215,3 +215,10 @@ * Genlist: Fixed tree expand bug. Check item type when an item is requested to be expanded/contracted. + +2012-06-25 Carsten Haitzler (The Rasterman) + + * add elm_cnp_selection_loss_callback_set() so you know when you + lose a selection as a client + * improve robustness of cnp to track target object deletions. + diff --git a/legacy/elementary/src/lib/elm_cnp.c b/legacy/elementary/src/lib/elm_cnp.c index 240846f6c0..cf79031b02 100644 --- a/legacy/elementary/src/lib/elm_cnp.c +++ b/legacy/elementary/src/lib/elm_cnp.c @@ -42,7 +42,7 @@ #define ARRAYINIT(foo) [foo] = -#define DEBUGON 1 +//#define DEBUGON 1 #ifdef DEBUGON # define cnp_debug(x...) fprintf(stderr, __FILE__": " x) @@ -102,6 +102,8 @@ struct _Cnp_Selection Eina_Bool (*set) (Ecore_X_Window, const void *data, int size); Eina_Bool (*clear) (void); void (*request) (Ecore_X_Window, const char *target); + Elm_Selection_Loss_Cb loss_cb; + void *loss_data; Elm_Sel_Format format; Ecore_X_Selection ecore_sel; @@ -179,209 +181,209 @@ static int vcard_receive(Cnp_Selection *sed, Ecore_X_Event_Selection_Notify *not static Eina_Bool pasteimage_append(char *file, Evas_Object *entry); static Cnp_Atom atoms[CNP_N_ATOMS] = { - [CNP_ATOM_TARGETS] = { - "TARGETS", - ELM_SEL_FORMAT_TARGETS, - targets_converter, - response_handler_targets, - notify_handler_targets, - 0 - }, - [CNP_ATOM_ATOM] = { - "ATOM", // for opera browser - ELM_SEL_FORMAT_TARGETS, - targets_converter, - response_handler_targets, - notify_handler_targets, - 0 - }, - [CNP_ATOM_XELM] = { - "application/x-elementary-markup", - ELM_SEL_FORMAT_MARKUP, - general_converter, - NULL, - NULL, - 0 - }, - [CNP_ATOM_text_uri] = { - "text/uri", - ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE, /* Either images or entries */ - general_converter, - NULL, - notify_handler_uri, - 0 - }, - [CNP_ATOM_text_urilist] = { - "text/uri-list", - ELM_SEL_FORMAT_IMAGE, - general_converter, - NULL, - notify_handler_uri, - 0 - }, - [CNP_ATOM_text_x_vcard] = { - "text/x-vcard", - ELM_SEL_FORMAT_VCARD, - vcard_send, NULL, - vcard_receive, 0 - }, - [CNP_ATOM_image_png] = { - "image/png", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image, - 0 - }, - [CNP_ATOM_image_jpeg] = { - "image/jpeg", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_bmp] = { - "image/x-ms-bmp", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_gif] = { - "image/gif", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_tiff] = { - "image/tiff", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_svg] = { - "image/svg+xml", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_xpm] = { - "image/x-xpixmap", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_tga] = { - "image/x-tga", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_image_ppm] = { - "image/x-portable-pixmap", - ELM_SEL_FORMAT_IMAGE, - image_converter, - NULL, - notify_handler_image,/* Raw image data is the same */ - 0 - }, - [CNP_ATOM_text_html_utf8] = { - "text/html;charset=utf-8", - ELM_SEL_FORMAT_HTML, - general_converter, - NULL, - notify_handler_html, - 0 - }, - [CNP_ATOM_text_html] = { - "text/html", - ELM_SEL_FORMAT_HTML, - general_converter, - NULL, - notify_handler_html, /* No encoding: Webkit only */ - 0 - }, - [CNP_ATOM_UTF8STRING] = { - "UTF8_STRING", - ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, - text_converter, - NULL, - notify_handler_text, - 0 - }, - [CNP_ATOM_STRING] = { - "STRING", - ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, - text_converter, - NULL, - notify_handler_text, - 0 - }, - [CNP_ATOM_TEXT] = { - "TEXT", - ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, - text_converter, - NULL, - NULL, - 0 - }, - [CNP_ATOM_text_plain_utf8] = { - "text/plain;charset=utf-8", - ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, - text_converter, - NULL, - NULL, - 0 - }, - [CNP_ATOM_text_plain] = { - "text/plain", - ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, - text_converter, - NULL, - NULL, - 0 - }, + [CNP_ATOM_TARGETS] = { + "TARGETS", + ELM_SEL_FORMAT_TARGETS, + targets_converter, + response_handler_targets, + notify_handler_targets, + 0 + }, + [CNP_ATOM_ATOM] = { + "ATOM", // for opera browser + ELM_SEL_FORMAT_TARGETS, + targets_converter, + response_handler_targets, + notify_handler_targets, + 0 + }, + [CNP_ATOM_XELM] = { + "application/x-elementary-markup", + ELM_SEL_FORMAT_MARKUP, + general_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_uri] = { + "text/uri", + ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE, /* Either images or entries */ + general_converter, + NULL, + notify_handler_uri, + 0 + }, + [CNP_ATOM_text_urilist] = { + "text/uri-list", + ELM_SEL_FORMAT_IMAGE, + general_converter, + NULL, + notify_handler_uri, + 0 + }, + [CNP_ATOM_text_x_vcard] = { + "text/x-vcard", + ELM_SEL_FORMAT_VCARD, + vcard_send, NULL, + vcard_receive, 0 + }, + [CNP_ATOM_image_png] = { + "image/png", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image, + 0 + }, + [CNP_ATOM_image_jpeg] = { + "image/jpeg", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_bmp] = { + "image/x-ms-bmp", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_gif] = { + "image/gif", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_tiff] = { + "image/tiff", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_svg] = { + "image/svg+xml", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_xpm] = { + "image/x-xpixmap", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_tga] = { + "image/x-tga", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_image_ppm] = { + "image/x-portable-pixmap", + ELM_SEL_FORMAT_IMAGE, + image_converter, + NULL, + notify_handler_image,/* Raw image data is the same */ + 0 + }, + [CNP_ATOM_text_html_utf8] = { + "text/html;charset=utf-8", + ELM_SEL_FORMAT_HTML, + general_converter, + NULL, + notify_handler_html, + 0 + }, + [CNP_ATOM_text_html] = { + "text/html", + ELM_SEL_FORMAT_HTML, + general_converter, + NULL, + notify_handler_html, /* No encoding: Webkit only */ + 0 + }, + [CNP_ATOM_UTF8STRING] = { + "UTF8_STRING", + ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, + text_converter, + NULL, + notify_handler_text, + 0 + }, + [CNP_ATOM_STRING] = { + "STRING", + ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, + text_converter, + NULL, + notify_handler_text, + 0 + }, + [CNP_ATOM_TEXT] = { + "TEXT", + ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, + text_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_plain_utf8] = { + "text/plain;charset=utf-8", + ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, + text_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_plain] = { + "text/plain", + ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML, + text_converter, + NULL, + NULL, + 0 + }, }; static Cnp_Selection selections[ELM_SEL_TYPE_CLIPBOARD + 1] = { - ARRAYINIT(ELM_SEL_TYPE_PRIMARY) { - .debug = "Primary", - .ecore_sel = ECORE_X_SELECTION_PRIMARY, - .set = ecore_x_selection_primary_set, - .clear = ecore_x_selection_primary_clear, - .request = ecore_x_selection_primary_request, - }, - ARRAYINIT(ELM_SEL_TYPE_SECONDARY) { - .debug = "Secondary", - .ecore_sel = ECORE_X_SELECTION_SECONDARY, - .set = ecore_x_selection_secondary_set, - .clear = ecore_x_selection_secondary_clear, - .request = ecore_x_selection_secondary_request, - }, - ARRAYINIT(ELM_SEL_TYPE_XDND) { - .debug = "XDnD", - .ecore_sel = ECORE_X_SELECTION_XDND, - .request = ecore_x_selection_xdnd_request, - }, - ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) { - .debug = "Clipboard", - .ecore_sel = ECORE_X_SELECTION_CLIPBOARD, - .set = ecore_x_selection_clipboard_set, - .clear = ecore_x_selection_clipboard_clear, - .request = ecore_x_selection_clipboard_request, - }, + ARRAYINIT(ELM_SEL_TYPE_PRIMARY) { + .debug = "Primary", + .ecore_sel = ECORE_X_SELECTION_PRIMARY, + .set = ecore_x_selection_primary_set, + .clear = ecore_x_selection_primary_clear, + .request = ecore_x_selection_primary_request, + }, + ARRAYINIT(ELM_SEL_TYPE_SECONDARY) { + .debug = "Secondary", + .ecore_sel = ECORE_X_SELECTION_SECONDARY, + .set = ecore_x_selection_secondary_set, + .clear = ecore_x_selection_secondary_clear, + .request = ecore_x_selection_secondary_request, + }, + ARRAYINIT(ELM_SEL_TYPE_XDND) { + .debug = "XDnD", + .ecore_sel = ECORE_X_SELECTION_XDND, + .request = ecore_x_selection_xdnd_request, + }, + ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) { + .debug = "Clipboard", + .ecore_sel = ECORE_X_SELECTION_CLIPBOARD, + .set = ecore_x_selection_clipboard_set, + .clear = ecore_x_selection_clipboard_clear, + .request = ecore_x_selection_clipboard_request, + }, }; /* Data for DND in progress */ @@ -427,12 +429,12 @@ _elm_widget_xwin_get(const Evas_Object *obj) { Evas_Object *top; Ecore_X_Window xwin = 0; - + top = elm_widget_top_get(obj); if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj)); - + if (top) xwin = elm_win_xwindow_get(top); - + if (!xwin) { Ecore_Evas *ee; @@ -447,6 +449,22 @@ _elm_widget_xwin_get(const Evas_Object *obj) } #endif +#ifdef HAVE_ELEMENTARY_X +static void +_sel_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + Cnp_Selection *sel = data; + if (sel->widget == obj) sel->widget = NULL; +} + +static void +_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + Cnp_Selection *sel = data; + if (sel->requestwidget == obj) sel->requestwidget = NULL; +} +#endif + EAPI Eina_Bool elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen) @@ -454,7 +472,7 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, #ifdef HAVE_ELEMENTARY_X Ecore_X_Window xwin = _elm_widget_xwin_get(obj); Cnp_Selection *sel; - + if ((!xwin) || (selection > ELM_SEL_TYPE_CLIPBOARD)) return EINA_FALSE; if (!_elm_cnp_init_count) _elm_cnp_init(); @@ -463,12 +481,24 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, sel = selections + selection; + if (sel->loss_cb) sel->loss_cb(sel->loss_data, selection); + + if (sel->widget) + evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, + _sel_obj_del, sel); + sel->widget = NULL; + sel->active = EINA_TRUE; sel->widget = obj; sel->xwin = xwin; sel->set(xwin, &selection, sizeof(Elm_Sel_Type)); sel->format = format; + sel->loss_cb = NULL; + sel->loss_data = NULL; + evas_object_event_callback_add + (sel->widget, EVAS_CALLBACK_DEL, _sel_obj_del, sel); + if (selbuf) { if (format == ELM_SEL_FORMAT_IMAGE) @@ -494,6 +524,19 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, #endif } +EAPI void +elm_cnp_selection_loss_callback_set(Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data) +{ +#ifdef HAVE_ELEMENTARY_X + Cnp_Selection *sel; + if (selection > ELM_SEL_TYPE_CLIPBOARD) return; + + sel = selections + selection; + sel->loss_cb = func; + sel->loss_data = (void *)data; +#endif +} + EAPI Eina_Bool elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection) { @@ -509,8 +552,18 @@ elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection) /* No longer this selection: Consider it gone! */ if ((!sel->active) || (sel->widget != obj)) return EINA_TRUE; - sel->active = EINA_FALSE; + if (sel->widget) + evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, + _sel_obj_del, sel); + if (sel->requestwidget) + evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, + _sel_obj_del2, sel); sel->widget = NULL; + sel->requestwidget = NULL; + sel->loss_cb = NULL; + sel->loss_data = NULL; + + sel->active = EINA_FALSE; if (sel->selbuf) { free(sel->selbuf); @@ -539,6 +592,11 @@ elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, sel = selections + selection; if (!xwin) return EINA_FALSE; + if (sel->requestwidget) + evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, + _sel_obj_del2, sel); + sel->requestwidget = NULL; + sel->requestformat = format; sel->requestwidget = obj; sel->xwin = xwin; @@ -546,6 +604,9 @@ elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, sel->datacb = datacb; sel->udata = udata; + evas_object_event_callback_add + (sel->requestwidget, EVAS_CALLBACK_DEL, _sel_obj_del2, sel); + return EINA_TRUE; #else return EINA_FALSE; @@ -590,6 +651,18 @@ selection_clear(void *udata __UNUSED__, int type __UNUSED__, void *event) if (i > ELM_SEL_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON; sel = selections + i; + + if (sel->loss_cb) sel->loss_cb(sel->loss_data, i); + + if (sel->widget) + evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL, + _sel_obj_del, sel); + if (sel->requestwidget) + evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL, + _sel_obj_del2, sel); + sel->widget = NULL; + sel->requestwidget = NULL; + sel->active = EINA_FALSE; sel->widget = NULL; if (sel->selbuf) diff --git a/legacy/elementary/src/lib/elm_cnp.h b/legacy/elementary/src/lib/elm_cnp.h index 2b45c919c9..35fe3b8b6b 100644 --- a/legacy/elementary/src/lib/elm_cnp.h +++ b/legacy/elementary/src/lib/elm_cnp.h @@ -97,6 +97,15 @@ typedef struct _Elm_Selection_Data Elm_Selection_Data; */ typedef Eina_Bool (*Elm_Drop_Cb)(void *data, Evas_Object *obj, Elm_Selection_Data *ev); +/** + * Callback invoked in when the selection ownership for a given selection is lost. + * + * @param data Application specific data + * @param selection The selection that is lost + * @since 1.1 + */ +typedef void (*Elm_Selection_Loss_Cb)(void *data, Elm_Sel_Type selection); + /** * @brief Set copy data for a widget. @@ -158,6 +167,37 @@ EAPI Eina_Bool elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, EAPI Eina_Bool elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection); + +/** + * @brief Set a function to be called when a selection is lost + * + * The function @p func is set of be called when selection @p selection is lost + * to another process or when elm_cnp_selection_set() is called. If @p func + * is NULL then it is not called. @p data is passed as the data parameter to + * the callback functions and selection is passed in as the selection that + * has been lost. + * + * elm_cnp_selection_set() and elm_object_cnp_selection_clear() automatically + * set this los callback to NULL when called. If you wish to take the selection + * and then be notified of loss please do this (for example): + * + * @code + * elm_cnp_selection_set(obj, ELM_SEL_TYPE_PRIMARY, ELM_SEL_FORMAT_TEXT, "hello", strlen(hello)); + * elm_cnp_selection_loss_callback_set(ELM_SEL_TYPE_PRIMARY, loss_cb, NULL); + * @endcode + * + * @see also elm_cnp_selection_set() + * + * @param selection Selection to be notified of for loss + * @param func The function to call + * @param data The data pointer passed to the function. + * + * @ingroup CopyPaste + * + * @since 1.1 + */ +EAPI void elm_cnp_selection_loss_callback_set(Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data); + /** * @} */