CNP is completely broken -- note where it should be fixed.

come on... I'd rather remove this crap than keep it like that. :-(



SVN revision: 72507
This commit is contained in:
Gustavo Sverzut Barbieri 2012-06-19 23:33:57 +00:00
parent 7e35c19135
commit 866c5b7a98
1 changed files with 98 additions and 51 deletions

View File

@ -8,11 +8,41 @@
# include <sys/mman.h>
#endif
/*
TODO: MUST FIX BUGS
elm_cnp must detect the environment of each engine the window is
running, maybe associate it more with the elm_win code.
It should only call X11 code for X11 windows! Right now it will call
them whenever Elementary is compiled with Ecore_X, but it's not in
use! The recommendation is to make a "engine" structure with
function pointers on what to do for each engine (X11, Wayland,
DirectFB...) and call only those. Splitting different CNP engines to
different files should help detect problems.
At least for X11 it's handled per xwin. We have a single xwin per
window (as opposed of GTK that have (had?) it per widget. But our
high-level code is mapped to widget/objects, then we must
reference-count the actions we enable-disable per window
(dnd-aware), as well as operate on sets (add/del) of supported
formats. It should be possible to have a single window with
different widgets being drop-target, one just for text, one for
image. It should be possible to start-drag from this window without
breaking drop later.
And the dispatch should be abstracted! Right now it's assuming
elm_entry :-(
*/
#ifdef HAVE_ELEMENTARY_X
#define ARRAYINIT(foo) [foo] =
//#define DEBUGON 1
#define DEBUGON 1
#ifdef DEBUGON
# define cnp_debug(x...) fprintf(stderr, __FILE__": " x)
@ -75,6 +105,7 @@ struct _Cnp_Selection
Elm_Sel_Format format;
Ecore_X_Selection ecore_sel;
Ecore_X_Window xwin;
Eina_Bool active : 1;
};
@ -356,6 +387,7 @@ static Cnp_Selection selections[ELM_SEL_TYPE_CLIPBOARD + 1] = {
/* Data for DND in progress */
static Saved_Type savedtypes = { NULL, NULL, 0, 0, 0, EINA_FALSE };
/* TODO BUG: should NEVER have these as globals! They should be per context (window). */
static void (*dragdonecb) (void *data, Evas_Object *obj) = NULL;
static void *dragdonedata = NULL;
@ -389,27 +421,40 @@ elm_selection_selection_has_owner(void)
#endif
}
#ifdef HAVE_ELEMENTARY_X
static Ecore_X_Window
_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;
Evas *evas = evas_object_evas_get(obj);
if (!evas) return 0;
ee = ecore_evas_ecore_evas_get(evas);
if (!ee) return 0;
xwin = (Ecore_X_Window)ecore_evas_window_get(ee);
}
return xwin;
}
#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)
{
#ifdef HAVE_ELEMENTARY_X
Evas_Object *top = elm_widget_top_get(obj);
Ecore_X_Window xwin;
Ecore_X_Window xwin = _elm_widget_xwin_get(obj);
Cnp_Selection *sel;
if (top) xwin = elm_win_xwindow_get(top);
else xwin = elm_win_xwindow_get(obj);
if (!xwin)
{
Evas *evas = evas_object_evas_get(obj);
if (!evas) return EINA_FALSE;
Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas);
if (!ee) return EINA_FALSE;
xwin = (Ecore_X_Window) ecore_evas_window_get(ee);
}
if ((!xwin) || (selection > ELM_SEL_TYPE_CLIPBOARD))
return EINA_FALSE;
if (!_elm_cnp_init_count) _elm_cnp_init();
@ -420,6 +465,7 @@ elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
sel->active = EINA_TRUE;
sel->widget = obj;
sel->xwin = xwin;
sel->set(xwin, &selection, sizeof(Elm_Sel_Type));
sel->format = format;
@ -483,8 +529,7 @@ elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
{
#ifdef HAVE_ELEMENTARY_X
Evas_Object *top;
Ecore_X_Window xwin;
Ecore_X_Window xwin = _elm_widget_xwin_get(obj);
Cnp_Selection *sel;
if (selection > ELM_SEL_TYPE_CLIPBOARD)
@ -492,21 +537,11 @@ elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
if (!_elm_cnp_init_count) _elm_cnp_init();
sel = selections + selection;
top = elm_widget_top_get(obj);
if (top) xwin = elm_win_xwindow_get(top);
else
{
Evas *evas = evas_object_evas_get(obj);
if (!evas) return EINA_FALSE;
Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas);
if (!ee) return EINA_FALSE;
xwin = (Ecore_X_Window) ecore_evas_window_get(ee);
}
if (!xwin) return EINA_FALSE;
sel->requestformat = format;
sel->requestwidget = obj;
sel->xwin = xwin;
sel->request(xwin, ECORE_X_SELECTION_TARGET_TARGETS);
sel->datacb = datacb;
sel->udata = udata;
@ -729,7 +764,6 @@ notify_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notif
{
Ecore_X_Selection_Data_Targets *targets;
Ecore_X_Atom *atomlist;
Evas_Object *top;
int i, j;
targets = notify->data;
@ -758,10 +792,9 @@ notify_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notif
return ECORE_CALLBACK_PASS_ON;
done:
top = elm_widget_top_get(sel->requestwidget);
if (!top) top = sel->requestwidget;
cnp_debug("Sending request for %s\n", atoms[j].name);
sel->request(elm_win_xwindow_get(top), atoms[j].name);
cnp_debug("Sending request for %s, xwin=%#llx\n",
atoms[j].name, (unsigned long long)sel->xwin);
sel->request(sel->xwin, atoms[j].name);
return ECORE_CALLBACK_PASS_ON;
}
@ -771,7 +804,6 @@ response_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *not
{
Ecore_X_Selection_Data_Targets *targets;
Ecore_X_Atom *atomlist;
Evas_Object *top;
int i,j;
targets = notify->data;
@ -793,10 +825,7 @@ response_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *not
return 0;
found:
top = elm_widget_top_get(sel->requestwidget);
if (!top) return 0;
sel->request(elm_win_xwindow_get(top), atoms[j].name);
sel->request(sel->xwin, atoms[j].name);
return 0;
}
@ -830,6 +859,8 @@ notify_handler_text(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
data->length, data->data);
mkupstr = _elm_util_text_to_mkup((const char *)stripstr);
cnp_debug("String is %s (from %s)\n", stripstr, data->data);
/* TODO BUG: should never NEVER assume it's an elm_entry! */
_elm_entry_entry_paste(sel->requestwidget, mkupstr);
free(stripstr);
free(mkupstr);
@ -1026,6 +1057,7 @@ notify_handler_html(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
}
cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
/* TODO BUG: should never NEVER assume it's an elm_entry! */
_elm_entry_entry_paste(sel->requestwidget, stripstr);
free(stripstr);
return 0;
@ -1105,6 +1137,7 @@ pasteimage_append(char *file, Evas_Object *entry)
{
char *entrytag;
int len;
/* TODO BUG: shouldn't define absize=240x180. Prefer data:// instead of href:// -- may need support for evas. See http://dataurl.net/ */
static const char *tagstring = "<item absize=240x180 href=file://%s></item>";
if ((!file) || (!entry)) return EINA_FALSE;
@ -1113,6 +1146,7 @@ pasteimage_append(char *file, Evas_Object *entry)
entrytag = alloca(len + 1);
snprintf(entrytag, len + 1, tagstring, file);
/* TODO BUG: should never NEVER assume it's an elm_entry! */
_elm_entry_entry_paste(entry, entrytag);
return EINA_TRUE;
@ -1125,6 +1159,8 @@ _dnd_enter(void *data __UNUSED__, int etype __UNUSED__, void *ev)
int i;
/* Skip it */
cnp_debug("enter %p\n", enter);
cnp_debug("enter types=%p (%d)\n", enter->types, enter->num_types);
if ((!enter) || (!enter->num_types) || (!enter->types)) return EINA_TRUE;
cnp_debug("Types\n");
@ -1167,6 +1203,8 @@ _dnd_drop(void *data __UNUSED__, int etype __UNUSED__, void *ev)
drop = ev;
cnp_debug("drops %p (%d)\n", drops, eina_list_count(drops));
// check we still have something to drop
if (!drops) return EINA_TRUE;
@ -1174,9 +1212,7 @@ _dnd_drop(void *data __UNUSED__, int etype __UNUSED__, void *ev)
for (l = drops; l; l = l->next)
{
dropable = l->data;
xwin = (Ecore_X_Window)ecore_evas_window_get
(ecore_evas_ecore_evas_get(evas_object_evas_get
(dropable->obj)));
xwin = _elm_widget_xwin_get(dropable->obj);
if (xwin == drop->win) break;
}
/* didn't find a window */
@ -1284,6 +1320,7 @@ found:
}
cnp_debug("doing a request then\n");
selections[ELM_SEL_TYPE_XDND].xwin = xwin;
selections[ELM_SEL_TYPE_XDND].requestwidget = dropable->obj;
selections[ELM_SEL_TYPE_XDND].requestformat = ELM_SEL_FORMAT_MARKUP;
selections[ELM_SEL_TYPE_XDND].active = EINA_TRUE;
@ -1346,13 +1383,14 @@ elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, v
Ecore_X_Window xwin;
Eina_List *item;
int first;
Evas_Object *top;
if (!obj) return EINA_FALSE;
top = elm_widget_top_get(obj);
if (!top || !elm_win_xwindow_get(top)) return EINA_FALSE;
xwin = _elm_widget_xwin_get(obj);
if (!xwin) return EINA_FALSE;
if (!_elm_cnp_init_count) _elm_cnp_init();
/* TODO: check if obj is already a drop target. Do not add twice! */
/* Is this the first? */
first = (!drops) ? 1 : 0;
@ -1390,15 +1428,14 @@ elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, v
obj);
/* FIXME: Handle resizes */
/* TODO BUG: should handle dnd-aware per window, not just the first window that requested it! */
/* If not the first: We're done */
if (!first) return EINA_TRUE;
xwin = (Ecore_X_Window)ecore_evas_window_get
(ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
ecore_x_dnd_aware_set(xwin, EINA_TRUE);
cnp_debug("Adding drop target calls\n");
cnp_debug("Adding drop target calls xwin=%#llx\n", (unsigned long long)xwin);
handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
_dnd_enter, NULL);
handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
@ -1431,12 +1468,14 @@ elm_drop_target_del(Evas_Object *obj)
evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE,
(Evas_Object_Event_Cb)elm_drop_target_del);
free(drop);
/* TODO BUG: we should handle dnd-aware per window, not just the last that reelased it */
/* If still drops there: All fine.. continue */
if (drops) return EINA_TRUE;
cnp_debug("Disabling DND\n");
xwin = (Ecore_X_Window)ecore_evas_window_get
(ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
xwin = _elm_widget_xwin_get(obj);
ecore_x_dnd_aware_set(xwin, EINA_FALSE);
ecore_event_handler_del(handler_pos);
@ -1456,6 +1495,10 @@ _drag_mouse_up(void *un __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *
Ecore_X_Window xwin = *((Ecore_X_Window *)data);
evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _drag_mouse_up);
ecore_x_dnd_drop();
cnp_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin);
/* TODO BUG: should not revert to FALSE if xwin is a drop target! */
ecore_x_dnd_aware_set(xwin, EINA_FALSE);
if (dragdonecb)
{
@ -1491,7 +1534,7 @@ elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (
if (!_elm_cnp_init_count) _elm_cnp_init();
xwin = elm_win_xwindow_get(obj);
xwin = _elm_widget_xwin_get(obj);
cnp_debug("starting drag...\n");
@ -1507,9 +1550,12 @@ elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (
sel->widget = obj;
sel->format = format;
sel->selbuf = data ? strdup(data) : NULL;
/* TODO BUG: should NEVER have these as globals! They should be per context (window). */
dragdonecb = dragdone;
dragdonedata = donecbdata;
/* TODO BUG: should increase dnd-awareness, in case it's drop target as well. See _drag_mouse_up() */
ecore_x_dnd_aware_set(xwin, EINA_TRUE);
ecore_x_dnd_callback_pos_update_set(_drag_move, NULL);
ecore_x_dnd_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type));
@ -1549,6 +1595,7 @@ elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (
return EINA_TRUE;
}
/* TODO: this should not be an actual tempfile, but rather encode the object as http://dataurl.net/ if it's an image or similar. Evas should support decoding it as memfile. */
static Tmp_Info *
elm_cnp_tempfile_create(int size)
{