ecore-wl2: split data offers into selection and drag

these are distinct objects and can coexist simultaneously; a drag
source should not overwrite an existing selection source

@fix
This commit is contained in:
Mike Blumenkrantz 2017-05-12 12:08:32 -04:00
parent 8afe0a7a6c
commit 44f22a250e
3 changed files with 68 additions and 38 deletions

View File

@ -136,18 +136,24 @@ data_source_send(void *data, struct wl_data_source *source EINA_UNUSED, const ch
}
static void
data_source_event_emit(Ecore_Wl2_Input *input, int event)
event_fill(struct _Ecore_Wl2_Event_Data_Source_Event *ev, Ecore_Wl2_Input *input)
{
Ecore_Wl2_Event_Data_Source_End *ev;
ev = calloc(1, sizeof(Ecore_Wl2_Event_Data_Source_End));
if (!ev) return;
if (input->focus.keyboard)
ev->source = input->focus.keyboard->id;
ev->win = _win_id_get(input);
ev->action = input->data.action;
ev->action = input->data.drag.action;
}
static void
data_source_event_emit(Ecore_Wl2_Input *input, int event, Eina_Bool cancel)
{
struct _Ecore_Wl2_Event_Data_Source_Event *ev;
ev = calloc(1, sizeof(struct _Ecore_Wl2_Event_Data_Source_Event));
EINA_SAFETY_ON_NULL_RETURN(ev);
event_fill((void*)ev, input);
ecore_event_add(event, ev, NULL, NULL);
}
@ -157,8 +163,8 @@ data_source_cancelled(void *data, struct wl_data_source *source)
{
Ecore_Wl2_Input *input = data;
if (input->data.source == source) input->data.source = NULL;
input->data.action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
if (input->data.drag.source == source) input->data.drag.source = NULL;
input->data.drag.action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
wl_data_source_destroy(source);
data_source_event_emit(input, ECORE_WL2_EVENT_DATA_SOURCE_END);
}
@ -175,7 +181,7 @@ data_source_dnd_finished(void *data, struct wl_data_source *source)
{
Ecore_Wl2_Input *input = data;
if (input->data.source == source) input->data.source = NULL;
if (input->data.drag.source == source) input->data.drag.source = NULL;
wl_data_source_destroy(source);
data_source_event_emit(input, ECORE_WL2_EVENT_DATA_SOURCE_END);
}
@ -185,7 +191,7 @@ data_source_action(void *data, struct wl_data_source *source EINA_UNUSED, uint32
{
Ecore_Wl2_Input *input = data;
input->data.action = dnd_action;
input->data.drag.action = dnd_action;
data_source_event_emit(input, ECORE_WL2_EVENT_DATA_SOURCE_ACTION);
}
@ -379,19 +385,19 @@ ecore_wl2_dnd_drag_types_set(Ecore_Wl2_Input *input, const char **types)
manager = input->display->wl.data_device_manager;
if (!manager) return;
if (input->data.types.data)
if (input->data.drag.types.data)
{
wl_array_for_each(t, &input->data.types)
wl_array_for_each(t, &input->data.drag.types)
free(*t);
wl_array_release(&input->data.types);
wl_array_init(&input->data.types);
wl_array_release(&input->data.drag.types);
wl_array_init(&input->data.drag.types);
}
if (input->data.source) wl_data_source_destroy(input->data.source);
input->data.source = NULL;
if (input->data.drag.source) wl_data_source_destroy(input->data.drag.source);
input->data.drag.source = NULL;
input->data.source = wl_data_device_manager_create_data_source(manager);
if (!input->data.source)
input->data.drag.source = wl_data_device_manager_create_data_source(manager);
if (!input->data.drag.source)
{
ERR("Could not create data source");
return;
@ -400,11 +406,11 @@ ecore_wl2_dnd_drag_types_set(Ecore_Wl2_Input *input, const char **types)
for (type = types; *type; type++)
{
if (!*type) continue;
t = wl_array_add(&input->data.types, sizeof(*t));
t = wl_array_add(&input->data.drag.types, sizeof(*t));
if (t)
{
*t = strdup(*type);
wl_data_source_offer(input->data.source, *t);
wl_data_source_offer(input->data.drag.source, *t);
}
}
}
@ -415,23 +421,23 @@ ecore_wl2_dnd_drag_start(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window, Ecore
struct wl_surface *dsurface, *osurface;
EINA_SAFETY_ON_NULL_RETURN(input);
EINA_SAFETY_ON_NULL_RETURN(input->data.source);
EINA_SAFETY_ON_NULL_RETURN(input->data.drag.source);
EINA_SAFETY_ON_NULL_RETURN(drag_window);
dsurface = ecore_wl2_window_surface_get(drag_window);
_ecore_wl2_input_ungrab(input);
wl_data_source_add_listener(input->data.source, &_source_listener, input);
wl_data_source_add_listener(input->data.drag.source, &_source_listener, input);
osurface = ecore_wl2_window_surface_get(window);
if (osurface)
{
if (input->display->wl.data_device_manager_version >= WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
wl_data_source_set_actions(input->data.source,
wl_data_source_set_actions(input->data.drag.source,
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
wl_data_device_start_drag(input->data.device, input->data.source,
wl_data_device_start_drag(input->data.device, input->data.drag.source,
osurface, dsurface, input->display->serial);
ecore_wl2_window_cursor_from_name_set(window, "move");
@ -445,14 +451,14 @@ ecore_wl2_dnd_drag_end(Ecore_Wl2_Input *input)
EINA_SAFETY_ON_NULL_RETURN(input);
if (input->data.types.data)
if (input->data.drag.types.data)
{
char **t;
wl_array_for_each(t, &input->data.types)
wl_array_for_each(t, &input->data.drag.types)
free(*t);
wl_array_release(&input->data.types);
wl_array_init(&input->data.types);
wl_array_release(&input->data.drag.types);
wl_array_init(&input->data.drag.types);
}
ev = calloc(1, sizeof(Ecore_Wl2_Event_Dnd_End));
@ -463,8 +469,11 @@ ecore_wl2_dnd_drag_end(Ecore_Wl2_Input *input)
ev->win = _win_id_get(input);
ev->seat = input->id;
ev->display = input->display;
ev->display->refs++;
ecore_event_add(ECORE_WL2_EVENT_DND_END, ev, NULL, NULL);
ecore_event_add(ECORE_WL2_EVENT_DND_END, ev, _display_event_free, ev->display);
}
EAPI Ecore_Wl2_Offer*

View File

@ -1431,7 +1431,8 @@ _ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id, unsigned int v
input->repeat.delay = 0.4;
input->repeat.enabled = EINA_TRUE;
wl_array_init(&input->data.types);
wl_array_init(&input->data.selection.types);
wl_array_init(&input->data.drag.types);
/* setup cursor size and theme */
_ecore_wl2_input_cursor_setup(input);
@ -1487,17 +1488,27 @@ _ecore_wl2_input_del(Ecore_Wl2_Input *input)
if (input->cursor.name) eina_stringshare_del(input->cursor.name);
if (input->data.types.data)
if (input->data.selection.types.data)
{
char **t;
wl_array_for_each(t, &input->data.types)
wl_array_for_each(t, &input->data.selection.types)
free(*t);
wl_array_release(&input->data.types);
wl_array_release(&input->data.selection.types);
}
if (input->data.drag.types.data)
{
char **t;
wl_array_for_each(t, &input->data.drag.types)
free(*t);
wl_array_release(&input->data.drag.types);
}
if (input->data.source) wl_data_source_destroy(input->data.source);
if (input->data.selection.source) wl_data_source_destroy(input->data.selection.source);
if (input->data.drag.source) wl_data_source_destroy(input->data.drag.source);
if (input->drag) _ecore_wl2_offer_unref(input->drag);
if (input->selection) _ecore_wl2_offer_unref(input->selection);
if (input->data.device) wl_data_device_destroy(input->data.device);

View File

@ -348,9 +348,19 @@ struct _Ecore_Wl2_Input
struct
{
struct wl_data_device *device;
struct wl_data_source *source;
struct wl_array types;
uint32_t action;
struct
{
struct wl_data_source *source;
struct wl_array types;
uint32_t serial;
} selection;
struct
{
struct wl_data_source *source;
struct wl_array types;
uint32_t action;
uint32_t serial;
} drag;
} data;
struct