e_comp_wl: enable drag and drop 93/50293/1 accepted/tizen/mobile/20151029.085727 accepted/tizen/tv/20151029.085737 accepted/tizen/wearable/20151029.085756 submit/tizen/20151029.012747 submit/tizen/20151029.052907
authorMinJeong Kim <minjjj.kim@samsung.com>
Tue, 27 Oct 2015 12:19:31 +0000 (21:19 +0900)
committerMinJeong Kim <minjjj.kim@samsung.com>
Tue, 27 Oct 2015 12:20:06 +0000 (21:20 +0900)
Change-Id: I5cc1cb159c54375fee8dd011cc2d0f25445bdd53

src/bin/e_comp_wl.c
src/bin/e_comp_wl.h
src/bin/e_comp_wl_data.c
src/bin/e_comp_wl_data.h

index 6f6e04bd4606e50fc0f595d6333fb388f6ea2e4e..87da4f0a056fe282fafd44cba1aac8226e64ac91 100644 (file)
@@ -656,6 +656,12 @@ _e_comp_wl_evas_cb_mouse_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj
    if (!ec->comp_data->surface) return;
    if (ec->comp_data->transform.start) return;
 
+   if (e_comp->wl_comp_data->dnd.enabled)
+     {
+        e_comp_wl_data_dnd_focus(ec);
+        return;
+     }
+
    wc = wl_resource_get_client(ec->comp_data->surface);
    serial = wl_display_next_serial(ec->comp->wl_comp_data->wl.disp);
    EINA_LIST_FOREACH(ec->comp->wl_comp_data->ptr.resources, l, res)
@@ -700,6 +706,12 @@ _e_comp_wl_evas_cb_mouse_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *ob
    if (!ec->comp_data->surface) return;
    if (ec->comp_data->transform.start) return;
 
+   if (e_comp->wl_comp_data->dnd.enabled)
+     {
+        if (e_comp->wl_comp_data->dnd.focus == ec->comp_data->surface)
+          e_comp_wl_data_dnd_focus(NULL);
+     }
+
    wc = wl_resource_get_client(ec->comp_data->surface);
    serial = wl_display_next_serial(ec->comp->wl_comp_data->wl.disp);
    EINA_LIST_FOREACH(ec->comp->wl_comp_data->ptr.resources, l, res)
@@ -731,6 +743,14 @@ _e_comp_wl_evas_cb_mouse_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *o
    if (e_client_util_ignored_get(ec)) return;
    if (!ec->comp_data->surface) return;
 
+   if (e_comp->wl_comp_data->dnd.enabled)
+     {
+        e_comp_wl_data_dnd_motion(ec, ev->timestamp,
+                                  ev->cur.canvas.x - ec->client.x,
+                                  ev->cur.canvas.y - ec->client.y);
+        return;
+     }
+
    wc = wl_resource_get_client(ec->comp_data->surface);
    EINA_LIST_FOREACH(ec->comp->wl_comp_data->ptr.resources, l, res)
      {
@@ -781,6 +801,12 @@ _e_comp_wl_evas_handle_mouse_button(E_Client *ec, uint32_t timestamp, uint32_t b
         return EINA_TRUE;
      }
 
+   if (e_comp->wl_comp_data->dnd.enabled)
+     {
+        e_comp_wl_data_dnd_drop(ec, timestamp, btn, state);
+        return EINA_FALSE;
+     }
+
    wc = wl_resource_get_client(ec->comp_data->surface);
    serial = wl_display_next_serial(ec->comp->wl_comp_data->wl.disp);
 
index 2085d9244e89f7e05d1cfc8ceed42b276fec71a6..f1a471eb5af08317608f919a7710225d6e8110cb 100644 (file)
@@ -226,6 +226,18 @@ struct _E_Comp_Wl_Data
         struct wl_listener listener;
      } clipboard;
 
+   struct
+     {
+        void *data_source;
+        E_Client *icon;
+        uint32_t serial;
+        struct wl_signal signal;
+        struct wl_listener data_source_listener;
+        struct wl_client *client;
+        struct wl_resource *focus;
+        Eina_Bool enabled : 1;
+     } dnd;
+
    struct
      {
         struct wl_resource *resource;
index 3654350020da3ece8ec0a51d483099bd7efe3990..068319a7ba32d10018f526f08ebcfb09d88ca43b 100644 (file)
@@ -188,6 +188,38 @@ _e_comp_wl_data_device_destroy_selection_data_source(struct wl_listener *listene
    wl_signal_emit(&cdata->selection.signal, cdata);
 }
 
+static void
+_e_comp_wl_data_device_destroy_dnd_data_source(struct wl_listener *listener EINA_UNUSED, void *data)
+{
+   E_Comp_Data *cdata;
+   E_Comp_Wl_Data_Source *source;
+   struct wl_resource *data_device_res, *focus = NULL;
+
+   if (!(source = (E_Comp_Wl_Data_Source*)data))
+     return;
+
+   if (!(cdata = container_of(listener, E_Comp_Data,
+                              selection.data_source_listener)))
+     return;
+
+   cdata->selection.data_source = NULL;
+
+   if (cdata->kbd.enabled)
+     focus = cdata->kbd.focus;
+
+   if (focus)
+     {
+        data_device_res =
+           _e_comp_wl_data_find_for_client(cdata->mgr.data_resources,
+                                           wl_resource_get_client(source->resource));
+
+        if (data_device_res)
+          wl_data_device_send_selection(data_device_res, NULL);
+     }
+
+   wl_signal_emit(&cdata->selection.signal, cdata);
+}
+
 static struct wl_resource*
 _e_comp_wl_data_device_data_offer_create(E_Comp_Wl_Data_Source *source, struct wl_resource *data_device_res)
 {
@@ -288,6 +320,29 @@ _e_comp_wl_data_device_selection_set(E_Comp_Data *cdata, E_Comp_Wl_Data_Source *
      }
 }
 
+static void
+_e_comp_wl_drag_icon_map(struct wl_resource *resource)
+{
+   E_Pixmap *ep;
+   E_Client *ec;
+
+   if (!(ep = wl_resource_get_user_data(resource))) return;
+   if (!(ec = e_pixmap_client_get(ep))) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+
+   evas_object_show(ec->frame);
+   ec->comp_data->mapped = EINA_TRUE;
+}
+
+static void
+_e_comp_wl_drag_icon_confiugre(struct wl_resource *resource,
+                               Evas_Coord x, Evas_Coord y,
+                               Evas_Coord w, Evas_Coord h)
+{
+   /* do nothing */
+}
+
+
 static void
 _e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resource *resource, struct wl_resource *source_resource, struct wl_resource *origin_resource, struct wl_resource *icon_resource, uint32_t serial)
 {
@@ -295,6 +350,7 @@ _e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resourc
    E_Comp_Wl_Data_Source *source;
    Eina_List *l;
    struct wl_resource *res;
+   E_Client *focused = NULL;
 
    DBG("Data Device Drag Start");
 
@@ -303,14 +359,40 @@ _e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resourc
 
    if (!(source = wl_resource_get_user_data(source_resource))) return;
 
-   /* 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);
-   //  }
+   if (icon_resource)
+     {
+        E_Pixmap *cp;
+        E_Client *ec;
+
+        DBG("\tHave Icon Resource: %p", icon_resource);
+        cp = wl_resource_get_user_data(icon_resource);
+
+        if ((cp) && !(ec = e_pixmap_client_get(cp)))
+          {
+             int x, y;
+
+             ec = e_client_new(NULL, cp, 1, 0);
+             ec->lock_focus_out = ec->layer_block = ec->visible = ec->override = 1;
+             ec->new_client = 0;
+             e_comp->new_clients--;
+             ec->icccm.title = eina_stringshare_add("noshadow");
+             ec->icccm.window_role = eina_stringshare_add("wl_pointer-cursor");
+             evas_object_pass_events_set(ec->frame, 1);
+             ec->client.w = ec->client.h = 1;
+             l = e_client_focus_stack_get();
+             e_client_focus_stack_set(eina_list_remove(l, ec));
+
+             ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
+             evas_object_move(ec->frame, x, y);
+             evas_object_show(ec->frame);
+
+             ec->comp_data->shell.surface = icon_resource;
+             ec->comp_data->shell.configure = _e_comp_wl_drag_icon_confiugre;
+             ec->comp_data->shell.map = _e_comp_wl_drag_icon_map;
+
+             cdata->dnd.icon = ec;
+          }
+     }
 
    EINA_LIST_FOREACH(cdata->ptr.resources, l, res)
      {
@@ -319,7 +401,22 @@ _e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resourc
         wl_pointer_send_leave(res, serial, cdata->kbd.focus);
      }
 
-   /* TODO: pointer start drag */
+   cdata->dnd.enabled = EINA_TRUE;
+   cdata->dnd.data_source = source;
+   cdata->dnd.client = client;
+
+   if (source)
+     {
+        cdata->dnd.data_source_listener.notify =
+           _e_comp_wl_data_device_destroy_dnd_data_source;
+        wl_signal_add(&source->destroy_signal,
+                      &cdata->dnd.data_source_listener);
+     }
+
+   focused = e_client_focused_get();
+   if (!focused) return;
+
+   e_comp_wl_data_dnd_focus(focused);
 }
 
 static void
@@ -774,3 +871,112 @@ e_comp_wl_data_manager_shutdown(E_Comp_Data *cdata)
 
    _e_comp_wl_clipboard_destroy(cdata);
 }
+
+EINTERN Eina_Bool
+e_comp_wl_data_dnd_focus(E_Client *ec)
+{
+   E_Comp_Data *cdata;
+   struct wl_resource *data_device_res = NULL, *surface = NULL;
+   struct wl_resource *offer;
+   uint32_t serial;
+
+   cdata = e_comp->wl_comp_data;
+
+   if (ec && cdata->dnd.focus == ec->comp_data->surface) return EINA_TRUE;
+
+   surface = cdata->dnd.focus?:ec->comp_data->surface;
+   if (surface)
+     data_device_res =
+        _e_comp_wl_data_find_for_client(cdata->mgr.data_resources,
+                                        wl_resource_get_client(surface));
+
+   if (!data_device_res) return EINA_FALSE;
+
+   if (cdata->dnd.focus)
+     {
+        wl_data_device_send_leave(data_device_res);
+        cdata->dnd.focus = NULL;
+     }
+
+   if (!ec) return EINA_FALSE;
+
+   if (!cdata->dnd.data_source &&
+       wl_resource_get_client(ec->comp_data->surface) != cdata->dnd.client)
+     return EINA_FALSE;
+
+   serial = wl_display_next_serial(cdata->wl.disp);
+
+   if (cdata->dnd.data_source)
+     {
+        offer = _e_comp_wl_data_device_data_offer_create(cdata->dnd.data_source,
+                                                         data_device_res);
+     }
+
+   wl_data_device_send_enter(data_device_res, serial,
+                             ec->comp_data->surface,
+                             ec->x, ec->y,
+                             offer);
+
+   cdata->dnd.focus = ec->comp_data->surface;
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_comp_wl_data_dnd_motion(E_Client *ec, unsigned int time, int x, int y)
+{
+   struct wl_resource *data_device_res;
+   E_Comp_Data *cdata;
+
+   cdata = e_comp->wl_comp_data;
+   if (!cdata->dnd.focus) return;
+
+   if (cdata->dnd.icon)
+     evas_object_move(cdata->dnd.icon->frame, x, y);
+
+   data_device_res = _e_comp_wl_data_find_for_client(cdata->mgr.data_resources,
+                                                     wl_resource_get_client(cdata->dnd.focus));
+   if (!data_device_res) return;
+
+   wl_data_device_send_motion(data_device_res,
+                              time,
+                              wl_fixed_from_int(x), wl_fixed_from_int(y));
+}
+
+EINTERN void
+e_comp_wl_data_dnd_drop(E_Client *ec, unsigned int time, uint32_t btn, uint32_t state)
+{
+   E_Comp_Data *cdata;
+   struct wl_resource *data_device_res, *res;
+   struct wl_client *wc;
+   uint32_t serial;
+   Eina_List *l;
+
+   cdata = e_comp->wl_comp_data;
+   if (!cdata->dnd.focus) return;
+
+   data_device_res = _e_comp_wl_data_find_for_client(cdata->mgr.data_resources,
+                                                     wl_resource_get_client(cdata->dnd.focus));
+   if (!data_device_res) return;
+
+   if (state == WL_POINTER_BUTTON_STATE_RELEASED)
+     {
+        wl_data_device_send_drop(data_device_res);
+        e_comp_wl_data_dnd_focus(NULL);
+        if (cdata->dnd.data_source)
+          wl_list_remove(&cdata->dnd.data_source_listener.link);
+        cdata->dnd.enabled = 0;
+
+        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)
+          {
+             if (!e_comp_wl_input_pointer_check(res)) continue;
+             if (wl_resource_get_client(res) != wc) continue;
+             wl_pointer_send_button(res, serial, time, btn, state);
+             wl_pointer_send_enter(res, serial, ec->comp_data->surface,
+                                   wl_fixed_from_int(ec->client.x),
+                                   wl_fixed_from_int(ec->client.y));
+          }
+     }
+}
index 6e3df1153fef974ff59a7b465a109e0097fba92c..6d1b9f3c57de118cba7eff9b538d9f0ea1add61e 100644 (file)
@@ -54,6 +54,9 @@ struct _E_Comp_Wl_Clipboard_Offer
 EINTERN void e_comp_wl_data_device_keyboard_focus_set(E_Comp_Data *cdata);
 EINTERN Eina_Bool e_comp_wl_data_manager_init(E_Comp_Data *cdata);
 EINTERN void e_comp_wl_data_manager_shutdown(E_Comp_Data *cdata);
+EINTERN Eina_Bool e_comp_wl_data_dnd_focus(E_Client *ec);
+EINTERN void e_comp_wl_data_dnd_motion(E_Client *ec, unsigned int time, int x, int y);
+EINTERN void e_comp_wl_data_dnd_drop(E_Client *ec, unsigned int time, uint32_t btn, uint32_t state);
 
 # endif
 #endif