From 1beecb72d71a164abc37c2f5c8bcc6a21c8ef8a6 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 4 Aug 2015 18:56:18 -0400 Subject: [PATCH] add server-side wl dnd weston-dnd seems to work as expected --- src/bin/e_comp_wl.c | 33 ++++++++++- src/bin/e_comp_wl.h | 7 ++- src/bin/e_comp_wl_data.c | 119 +++++++++++++++++++++++++++++++++++++-- src/bin/e_comp_wl_data.h | 3 + 4 files changed, 151 insertions(+), 11 deletions(-) diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index b3c6a9783..82d5f482e 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -164,8 +164,12 @@ _e_comp_wl_evas_cb_mouse_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj if (!ec->comp_data->surface) return; e_comp->wl_comp_data->ptr.ec = ec; + if (e_comp->wl_comp_data->drag) + { + e_comp_wl_data_device_send_enter(ec); + return; + } if (!eina_list_count(e_comp->wl_comp_data->ptr.resources)) return; - wc = wl_resource_get_client(ec->comp_data->surface); serial = wl_display_next_serial(e_comp->wl_comp_data->wl.disp); EINA_LIST_FOREACH(e_comp->wl_comp_data->ptr.resources, l, res) @@ -202,7 +206,11 @@ _e_comp_wl_evas_cb_mouse_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *ob if (e_object_is_del(E_OBJECT(ec))) return; if (!ec->comp_data->surface) return; - + if (e_comp->wl_comp_data->drag) + { + e_comp_wl_data_device_send_leave(ec); + return; + } if (!eina_list_count(e_comp->wl_comp_data->ptr.resources)) return; wc = wl_resource_get_client(ec->comp_data->surface); @@ -895,6 +903,16 @@ _e_comp_wl_cb_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mou e_comp->wl_comp_data->ptr.x = wl_fixed_from_int(ev->x); e_comp->wl_comp_data->ptr.y = wl_fixed_from_int(ev->y); e_screensaver_notidle(); + if (e_comp->wl_comp_data->selection.target) + { + struct wl_resource *res; + int x, y; + + res = e_comp_wl_data_find_for_client(wl_resource_get_client(e_comp->wl_comp_data->selection.target->comp_data->surface)); + x = ev->x - e_comp->wl_comp_data->selection.target->client.x; + y = ev->y - e_comp->wl_comp_data->selection.target->client.y; + wl_data_device_send_motion(res, ev->timestamp, wl_fixed_from_int(x), wl_fixed_from_int(y)); + } return ECORE_CALLBACK_RENEW; } @@ -1088,7 +1106,16 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state) ecore_evas_pointer_xy_get(e_comp->ee, &ec->mouse.current.mx, &ec->mouse.current.my); ec->netwm.sync.send_time = ecore_loop_time_get(); } - e_client_util_move_resize_without_frame(ec, x, y, state->bw, state->bh); + if (e_comp->wl_comp_data->drag_client && (e_comp->wl_comp_data->drag_client == ec)) + { + e_comp->wl_comp_data->drag->dx -= state->sx; + e_comp->wl_comp_data->drag->dy -= state->sy; + e_drag_move(e_comp->wl_comp_data->drag, + e_comp->wl_comp_data->drag->x + state->sx, e_comp->wl_comp_data->drag->y + state->sy); + e_drag_resize(e_comp->wl_comp_data->drag, state->bw, state->bh); + } + else + e_client_util_move_resize_without_frame(ec, x, y, state->bw, state->bh); } if (ec->new_client) diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h index 67cb67767..771389d23 100644 --- a/src/bin/e_comp_wl.h +++ b/src/bin/e_comp_wl.h @@ -192,6 +192,7 @@ struct _E_Comp_Wl_Data uint32_t serial; struct wl_signal signal; struct wl_listener data_source_listener; + E_Client *target; } selection; struct @@ -231,9 +232,9 @@ struct _E_Comp_Wl_Data struct wl_client *xwl_client; Eina_List *xwl_pending; - /* Eina_List *retry_clients; */ - /* Ecore_Timer *retry_timer; */ - Eina_Bool restack : 1; + E_Drag *drag; + E_Client *drag_client; + void *drag_source; }; struct _E_Comp_Wl_Client_Data diff --git a/src/bin/e_comp_wl_data.c b/src/bin/e_comp_wl_data.c index 8579d0fb1..f1843dff8 100644 --- a/src/bin/e_comp_wl_data.c +++ b/src/bin/e_comp_wl_data.c @@ -1,3 +1,4 @@ +#define EXECUTIVE_MODE_ENABLED #define E_COMP_WL #include "e.h" @@ -267,26 +268,68 @@ _e_comp_wl_data_device_selection_set(void *data EINA_UNUSED, E_Comp_Wl_Data_Sour } } +static void +_e_comp_wl_data_device_drag_finished(E_Drag *drag, int dropped) +{ + Evas_Object *o; + + o = edje_object_part_swallow_get(drag->comp_object, "e.swallow.content"); + if (eina_streq(evas_object_type_get(o), "e_comp_object")) + edje_object_part_unswallow(drag->comp_object, o); + else + e_zoomap_child_set(o, NULL); + evas_object_hide(o); + evas_object_pass_events_set(o, 1); + if (e_comp->wl_comp_data->drag != drag) return; + if (e_comp->wl_comp_data->selection.target && (!dropped)) + { + struct wl_resource *res; + + res = e_comp_wl_data_find_for_client(wl_resource_get_client(e_comp->wl_comp_data->selection.target->comp_data->surface)); + if (res) + { + wl_data_device_send_drop(res); + wl_data_device_send_leave(res); + } + } + e_comp->wl_comp_data->drag = NULL; + e_comp->wl_comp_data->drag_client = NULL; + e_comp->wl_comp_data->selection.target = NULL; + e_comp->wl_comp_data->drag_source = NULL; +} + static void _e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, struct wl_resource *source_resource, struct wl_resource *origin_resource, struct wl_resource *icon_resource, uint32_t serial) { E_Comp_Wl_Data_Source *source; Eina_List *l; struct wl_resource *res; + E_Client *ec = NULL; + int x, y; DBG("Data Device Drag Start"); if ((e_comp->wl_comp_data->kbd.focus) && (e_comp->wl_comp_data->kbd.focus != origin_resource)) return; if (!(source = wl_resource_get_user_data(source_resource))) return; + e_comp->wl_comp_data->drag_source = source; - /* TODO: create icon for pointer ?? */ if (icon_resource) { - E_Pixmap *cp; - DBG("\tHave Icon Resource: %p", icon_resource); - cp = wl_resource_get_user_data(icon_resource); + ec = wl_resource_get_user_data(icon_resource); + if (!ec->re_manage) + { + ec->re_manage = 1; + + ec->lock_focus_out = ec->override = 1; + ec->icccm.title = eina_stringshare_add("noshadow"); + ec->layer = E_LAYER_CLIENT_DRAG; + evas_object_layer_set(ec->frame, E_LAYER_CLIENT_DRAG); + e_client_focus_stack_set(eina_list_remove(e_client_focus_stack_get(), ec)); + EC_CHANGED(ec); + e_comp->wl_comp_data->drag_client = ec; + } } EINA_LIST_FOREACH(e_comp->wl_comp_data->ptr.resources, l, res) @@ -296,7 +339,14 @@ _e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resourc wl_pointer_send_leave(res, serial, e_comp->wl_comp_data->kbd.focus); } - /* TODO: pointer start drag */ + evas_pointer_canvas_xy_get(e_comp->evas, &x, &y); + e_comp->wl_comp_data->drag = e_drag_new(x, y, + NULL, 0, NULL, 0, NULL, _e_comp_wl_data_device_drag_finished); + if (ec) + e_drag_object_set(e_comp->wl_comp_data->drag, ec->frame); + e_drag_start(e_comp->wl_comp_data->drag, x, y); + if (e_comp->wl_comp_data->ptr.ec) + e_comp_wl_data_device_send_enter(e_comp->wl_comp_data->ptr.ec); } static void @@ -642,6 +692,65 @@ _e_comp_wl_clipboard_create(void) wl_signal_add(&e_comp->wl_comp_data->selection.signal, &e_comp->wl_comp_data->clipboard.listener); } +static void +_e_comp_wl_data_device_target_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + E_Client *ec = data; + + if (e_comp->wl_comp_data->selection.target == ec) + e_comp->wl_comp_data->selection.target = NULL; +} + +EINTERN void +e_comp_wl_data_device_send_enter(E_Client *ec) +{ + struct wl_resource *data_device_res, *offer_res; + uint32_t serial; + int x, y; + + data_device_res = + e_comp_wl_data_find_for_client(wl_resource_get_client(ec->comp_data->surface)); + if (!data_device_res) return; + + offer_res = e_comp_wl_data_device_send_offer(ec); + if (e_comp->wl_comp_data->selection.data_source && (!offer_res)) return; + e_comp->wl_comp_data->selection.target = ec; + evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_DEL, _e_comp_wl_data_device_target_del, ec); + + x = wl_fixed_to_int(e_comp->wl_comp_data->ptr.x) - e_comp->wl_comp_data->selection.target->client.x; + y = wl_fixed_to_int(e_comp->wl_comp_data->ptr.y) - e_comp->wl_comp_data->selection.target->client.y; + serial = wl_display_next_serial(e_comp->wl_comp_data->wl.disp); + wl_data_device_send_enter(data_device_res, serial, ec->comp_data->surface, + wl_fixed_from_int(x), wl_fixed_from_int(y), offer_res); +} + +EINTERN void +e_comp_wl_data_device_send_leave(E_Client *ec) +{ + struct wl_resource *res; + + evas_object_event_callback_del_full(ec->frame, EVAS_CALLBACK_DEL, _e_comp_wl_data_device_target_del, ec); + if (e_comp->wl_comp_data->selection.target == ec) + e_comp->wl_comp_data->selection.target = NULL; + res = e_comp_wl_data_find_for_client(wl_resource_get_client(ec->comp_data->surface)); + wl_data_device_send_leave(res); +} + +EINTERN void * +e_comp_wl_data_device_send_offer(E_Client *ec) +{ + struct wl_resource *data_device_res, *offer_res = NULL; + E_Comp_Wl_Data_Source *source; + + data_device_res = + e_comp_wl_data_find_for_client(wl_resource_get_client(ec->comp_data->surface)); + if (!data_device_res) return NULL; + source = e_comp->wl_comp_data->drag_source; + if (source) + offer_res = _e_comp_wl_data_device_data_offer_create(source, data_device_res); + return offer_res; +} + EINTERN void e_comp_wl_data_device_keyboard_focus_set(void) { diff --git a/src/bin/e_comp_wl_data.h b/src/bin/e_comp_wl_data.h index 69a9efc0b..5fc56c2f7 100644 --- a/src/bin/e_comp_wl_data.h +++ b/src/bin/e_comp_wl_data.h @@ -50,6 +50,9 @@ struct _E_Comp_Wl_Clipboard_Offer size_t offset; }; +EINTERN void e_comp_wl_data_device_send_enter(E_Client *ec); +EINTERN void e_comp_wl_data_device_send_leave(E_Client *ec); +EINTERN void *e_comp_wl_data_device_send_offer(E_Client *ec); EINTERN void e_comp_wl_data_device_keyboard_focus_set(void); EINTERN Eina_Bool e_comp_wl_data_manager_init(void); EINTERN void e_comp_wl_data_manager_shutdown(void);