[evolution/wip/webkit2] Composer - Fix more drag and drop related bugs



commit 8a34441aa08fbcdebe694fc9208bdefe37235efb
Author: Tomas Popela <tpopela redhat com>
Date:   Tue Mar 24 15:41:57 2015 +0100

    Composer - Fix more drag and drop related bugs
    
    This fixes the following bugs:
    - DnD inside the view was still copying things not moving them
    - Prevent WebKit to insert the URI inside the view when DnD'ing some
      file inside the view
    - DnD'ed inline image was inserted on the caret position and not on the
      position we dropped it.

 composer/e-composer-private.c                     |    2 +-
 composer/e-composer-private.h                     |    2 +-
 composer/e-msg-composer.c                         |  119 +++++++++++++--------
 e-util/e-html-editor-view.c                       |   35 ++++---
 e-util/e-html-editor-view.h                       |    4 +
 web-extensions/e-composer-private-dom-functions.c |   17 +---
 web-extensions/e-composer-private-dom-functions.h |    3 +-
 web-extensions/e-html-editor-web-extension.c      |    6 +-
 8 files changed, 110 insertions(+), 78 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index c7b2c3b..1ae2428 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -137,7 +137,7 @@ e_composer_private_constructed (EMsgComposer *composer)
        priv->busy = FALSE;
        priv->saved_editable = FALSE;
        priv->drop_occured = FALSE;
-       priv->remove_inserted_uri_on_drop = FALSE;
+       priv->dnd_is_uri = FALSE;
 
        priv->focused_entry = NULL;
 
diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h
index 69ebd90..7f798b4 100644
--- a/composer/e-composer-private.h
+++ b/composer/e-composer-private.h
@@ -101,7 +101,7 @@ struct _EMsgComposerPrivate {
        gboolean saved_editable;
        gboolean set_signature_from_message;
        gboolean drop_occured;
-       gboolean remove_inserted_uri_on_drop;
+       gboolean dnd_is_uri;
 
        gint focused_entry_selection_start;
        gint focused_entry_selection_end;
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index d1d7390..b7688f0 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -110,7 +110,8 @@ enum DndTargetType {
        DND_TARGET_TYPE_TEXT_HTML,
        DND_TARGET_TYPE_UTF8_STRING,
        DND_TARGET_TYPE_TEXT_PLAIN,
-       DND_TARGET_TYPE_STRING
+       DND_TARGET_TYPE_STRING,
+       DND_TARGET_TYPE_TEXT_PLAIN_UTF8
 };
 
 static GtkTargetEntry drag_dest_targets[] = {
@@ -120,6 +121,7 @@ static GtkTargetEntry drag_dest_targets[] = {
        { (gchar *) "UTF8_STRING", 0, DND_TARGET_TYPE_UTF8_STRING },
        { (gchar *) "text/plain", 0, DND_TARGET_TYPE_TEXT_PLAIN },
        { (gchar *) "STRING", 0, DND_TARGET_TYPE_STRING },
+       { (gchar *) "text/plain;charset=utf-8", 0, DND_TARGET_TYPE_TEXT_PLAIN_UTF8 },
 };
 
 static guint signals[LAST_SIGNAL];
@@ -1761,31 +1763,6 @@ msg_composer_drag_motion_cb (GtkWidget *widget,
        return FALSE;
 }
 
-static gchar *
-next_uri (guchar **uri_list,
-          gint *len,
-          gint *list_len)
-{
-       guchar *uri, *begin;
-
-       begin = *uri_list;
-       *len = 0;
-       while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
-               (*uri_list) ++;
-               (*len) ++;
-               (*list_len) --;
-       }
-
-       uri = (guchar *) g_strndup ((gchar *) begin, *len);
-
-       while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
-               (*uri_list) ++;
-               (*list_len) --;
-       }
-
-       return (gchar *) uri;
-}
-
 static gboolean
 msg_composer_drag_drop_cb (GtkWidget *widget,
                            GdkDragContext *context,
@@ -1812,6 +1789,12 @@ msg_composer_drag_drop_cb (GtkWidget *widget,
        if (target == GDK_NONE)
                gdk_drag_status (context, 0, time);
        else {
+               /* Prevent WebKit from pasting the URI of file into the view. */
+               if (composer->priv->dnd_is_uri)
+                       g_signal_stop_emission_by_name (widget, "drag-drop");
+
+               composer->priv->dnd_is_uri = FALSE;
+
                gdk_drag_status (context, GDK_ACTION_COPY, time);
                composer->priv->drop_occured = TRUE;
                gtk_drag_get_data (widget, context, target, time);
@@ -1834,6 +1817,11 @@ msg_composer_drag_data_received_after_cb (GtkWidget *widget,
        EHTMLEditorView *view;
        GDBusProxy *web_extension;
 
+       if (!composer->priv->drop_occured)
+               return;
+
+       composer->priv->drop_occured = FALSE;
+
        editor = e_msg_composer_get_editor (composer);
        view = e_html_editor_get_view (editor);
        web_extension = e_html_editor_view_get_web_extension_proxy (view);
@@ -1844,15 +1832,39 @@ msg_composer_drag_data_received_after_cb (GtkWidget *widget,
                web_extension,
                "DOMCleanAfterDragAndDrop",
                g_variant_new (
-                       "(tb)",
-                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)),
-                       composer->priv->remove_inserted_uri_on_drop),
+                       "(t)",
+                       webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view))),
                G_DBUS_CALL_FLAGS_NONE,
                -1,
                NULL,
                NULL);
 }
 
+static gchar *
+next_uri (guchar **uri_list,
+          gint *len,
+          gint *list_len)
+{
+       guchar *uri, *begin;
+
+       begin = *uri_list;
+       *len = 0;
+       while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
+               (*uri_list) ++;
+               (*len) ++;
+               (*list_len) --;
+       }
+
+       uri = (guchar *) g_strndup ((gchar *) begin, *len);
+
+       while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
+               (*uri_list) ++;
+               (*list_len) --;
+       }
+
+       return (gchar *) uri;
+}
+
 static void
 msg_composer_drag_data_received_cb (GtkWidget *widget,
                                     GdkDragContext *context,
@@ -1865,19 +1877,13 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
 {
        EHTMLEditor *editor;
        EHTMLEditorView *view;
-       gboolean html_mode;
+       gboolean html_mode, same_widget = FALSE;
        GtkWidget *source_widget;
 
        editor = e_msg_composer_get_editor (composer);
        view = e_html_editor_get_view (editor);
        html_mode = e_html_editor_view_get_html_mode (view);
 
-       if (!composer->priv->drop_occured)
-               return;
-
-       composer->priv->remove_inserted_uri_on_drop = FALSE;
-       composer->priv->drop_occured = FALSE;
-
        /* When we are doind DnD just inside the web view, the DnD is supposed
         * to move things around. */
        source_widget = gtk_drag_get_source_widget (context);
@@ -1886,13 +1892,38 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
                EHTMLEditorView *editor_view = e_html_editor_get_view (editor);
 
                if ((gpointer) editor_view == (gpointer) source_widget)
-                       return;
+                       same_widget = TRUE;
+       }
+
+       /* Leave DnD inside the view on WebKit. */
+       if (composer->priv->drop_occured && same_widget) {
+               gdk_drag_status (context, 0, time);
+               return;
        }
 
+       if (!composer->priv->drop_occured) {
+               if (!same_widget) {
+                       /* Check if we are DnD'ing some URI, if so WebKit will
+                        * insert the URI into the view and we have to prevent it
+                        * from doing that. */
+                       if (info == DND_TARGET_TYPE_TEXT_URI_LIST) {
+                               gchar **uris;
+
+                               uris = gtk_selection_data_get_uris (selection);
+                               composer->priv->dnd_is_uri = uris != NULL;
+                               g_strfreev (uris);
+                       }
+               }
+               return;
+       }
+
+       composer->priv->dnd_is_uri = FALSE;
+
        /* Leave the text on WebKit to handle it. */
        if (info == DND_TARGET_TYPE_UTF8_STRING ||
            info == DND_TARGET_TYPE_STRING ||
-           info == DND_TARGET_TYPE_TEXT_PLAIN) {
+           info == DND_TARGET_TYPE_TEXT_PLAIN ||
+           info == DND_TARGET_TYPE_TEXT_PLAIN_UTF8) {
                gdk_drag_status (context, 0, time);
                return;
        }
@@ -1911,6 +1942,8 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
                        return;
                }
 
+               e_html_editor_view_move_selection_on_point (view, x, y);
+
                list_len = length;
                do {
                        text = next_uri ((guchar **) &data, &len, &list_len);
@@ -1944,6 +1977,8 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
                        return;
                }
 
+               e_html_editor_view_move_selection_on_point (view, x, y);
+
                list_len = length;
                do {
                        uri = next_uri ((guchar **) &data, &len, &list_len);
@@ -1965,6 +2000,8 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
                        return;
                }
 
+               e_html_editor_view_move_selection_on_point (view, x, y);
+
                list_len = length;
                do {
                        uri = next_uri ((guchar **) &data, &len, &list_len);
@@ -1976,12 +2013,6 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
        } else {
                EAttachmentView *attachment_view =
                        e_msg_composer_get_attachment_view (composer);
-               /* FIXME When the user drops something inside the view and it is
-                * added as an EAttachment, WebKit still inserts the URI of the
-                * resource into the view. Now we are deleting it in
-                * msg_composer_drag_data_received_after_cb, but there has to be
-                * a way how to tell the WebKit to not process this drop. */
-               composer->priv->remove_inserted_uri_on_drop = TRUE;
                /* Forward the data to the attachment view.  Note that calling
                 * e_attachment_view_drag_data_received() will not work because
                 * that function only handles the case where all the other drag
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 08c7b8b..5a24bf5 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -589,21 +589,16 @@ html_editor_view_constructed (GObject *object)
        webkit_web_view_load_html (WEBKIT_WEB_VIEW (object), "", "file://");
 }
 
-static void
-html_editor_view_move_selection_on_point (EHTMLEditorView *view)
+void
+e_html_editor_view_move_selection_on_point (EHTMLEditorView *view,
+                                            gint x,
+                                            gint y)
 {
-       gint x, y;
-       GdkDeviceManager *device_manager;
-       GdkDevice *pointer;
        GDBusProxy *web_extension;
 
        g_return_if_fail (E_IS_HTML_EDITOR_VIEW (view));
-
-       device_manager = gdk_display_get_device_manager (
-               gtk_widget_get_display (GTK_WIDGET (view)));
-       pointer = gdk_device_manager_get_client_pointer (device_manager);
-       gdk_window_get_device_position (
-               gtk_widget_get_window (GTK_WIDGET (view)), pointer, &x, &y, NULL);
+       g_return_if_fail (x >= 0);
+       g_return_if_fail (y >= 0);
 
        web_extension = e_html_editor_view_get_web_extension_proxy (view);
        if (web_extension)
@@ -621,6 +616,20 @@ html_editor_view_move_selection_on_point (EHTMLEditorView *view)
                NULL);
 }
 
+static void
+html_editor_view_move_selection_on_point (GtkWidget *widget)
+{
+       gint x, y;
+       GdkDeviceManager *device_manager;
+       GdkDevice *pointer;
+
+       device_manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
+       pointer = gdk_device_manager_get_client_pointer (device_manager);
+       gdk_window_get_device_position (gtk_widget_get_window (widget), pointer, &x, &y, NULL);
+
+       e_html_editor_view_move_selection_on_point (E_HTML_EDITOR_VIEW (widget), x, y);
+}
+
 static gboolean
 html_editor_view_button_press_event (GtkWidget *widget,
                                      GdkEventButton *event)
@@ -632,7 +641,7 @@ html_editor_view_button_press_event (GtkWidget *widget,
                g_signal_emit (widget, signals[PASTE_PRIMARY_CLIPBOARD], 0);
                event_handled = TRUE;
        } else if (event->button == 3) {
-               html_editor_view_move_selection_on_point (E_HTML_EDITOR_VIEW (widget));
+               html_editor_view_move_selection_on_point (widget);
                g_signal_emit (
                        widget, signals[POPUP_EVENT],
                        0, event, &event_handled);
@@ -681,7 +690,7 @@ html_editor_view_key_press_event (GtkWidget *widget,
        if (event->keyval == GDK_KEY_Menu) {
                gboolean event_handled;
 
-               html_editor_view_move_selection_on_point (E_HTML_EDITOR_VIEW (widget));
+               html_editor_view_move_selection_on_point (widget);
                g_signal_emit (
                        widget, signals[POPUP_EVENT],
                        0, event, &event_handled);
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index bb12c83..1fc5bc5 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -202,6 +202,10 @@ void               e_html_editor_view_restore_selection
                                                (EHTMLEditorView *view);
 void           e_html_editor_view_save_selection
                                                (EHTMLEditorView *view);
+void           e_html_editor_view_move_selection_on_point
+                                               (EHTMLEditorView *view,
+                                                gint x,
+                                                gint y);
 G_END_DECLS
 
 #endif /* E_HTML_EDITOR_VIEW_H */
diff --git a/web-extensions/e-composer-private-dom-functions.c 
b/web-extensions/e-composer-private-dom-functions.c
index 3d700c3..d549867 100644
--- a/web-extensions/e-composer-private-dom-functions.c
+++ b/web-extensions/e-composer-private-dom-functions.c
@@ -329,8 +329,7 @@ dom_insert_signature (WebKitDOMDocument *document,
 
 void
 dom_clean_after_drag_and_drop (WebKitDOMDocument *document,
-                               EHTMLEditorWebExtension *extension,
-                               gboolean remove_inserted_uri_on_drop)
+                               EHTMLEditorWebExtension *extension)
 {
        WebKitDOMDOMWindow *dom_window;
        WebKitDOMDOMSelection *dom_selection;
@@ -338,18 +337,10 @@ dom_clean_after_drag_and_drop (WebKitDOMDocument *document,
        dom_window = webkit_dom_document_get_default_view (document);
        dom_selection = webkit_dom_dom_window_get_selection (dom_window);
 
-       /* FIXME When the user drops something inside the view and it is
-        * added as an EAttachment, WebKit still inserts the URI of the
-        * resource into the view. Let's delete it as it is selected. */
-       if (remove_inserted_uri_on_drop)
-               webkit_dom_dom_selection_delete_from_document (dom_selection);
-       else {
-               /* When text is DnD'ed into the view, WebKit will select it. So let's
-                * collapse it to its end to have the caret after the DnD'ed text. */
-               webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
-       }
-
+       /* When text is DnD'ed into the view, WebKit will select it. So let's
+        * collapse it to its end to have the caret after the DnD'ed text. */
        webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
+
        dom_check_magic_links (document, extension, FALSE);
        /* Also force spell check on view. */
        dom_force_spell_check (document, extension);
diff --git a/web-extensions/e-composer-private-dom-functions.h 
b/web-extensions/e-composer-private-dom-functions.h
index 466372b..894d2a0 100644
--- a/web-extensions/e-composer-private-dom-functions.h
+++ b/web-extensions/e-composer-private-dom-functions.h
@@ -35,8 +35,7 @@ void          dom_insert_signature            (WebKitDOMDocument *document,
                                                 gboolean top_signature,
                                                 gboolean start_bottom);
 void           dom_clean_after_drag_and_drop   (WebKitDOMDocument *document,
-                                                EHTMLEditorWebExtension *extension,
-                                                gboolean remove_inserted_uri_on_drop);
+                                                EHTMLEditorWebExtension *extension);
 
 G_END_DECLS
 
diff --git a/web-extensions/e-html-editor-web-extension.c b/web-extensions/e-html-editor-web-extension.c
index 8228fb4..f171e75 100644
--- a/web-extensions/e-html-editor-web-extension.c
+++ b/web-extensions/e-html-editor-web-extension.c
@@ -1674,10 +1674,8 @@ handle_method_call (GDBusConnection *connection,
 
                g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "DOMCleanAfterDragAndDrop") == 0) {
-               gboolean remove_inserted_uri_on_drop;
-
                g_variant_get (
-                       parameters, "(tb)", &page_id, &remove_inserted_uri_on_drop);
+                       parameters, "(t)", &page_id);
 
                web_page = get_webkit_web_page_or_return_dbus_error (
                        invocation, web_extension, page_id);
@@ -1685,7 +1683,7 @@ handle_method_call (GDBusConnection *connection,
                        return;
 
                document = webkit_web_page_get_dom_document (web_page);
-               dom_clean_after_drag_and_drop (document, extension, remove_inserted_uri_on_drop);
+               dom_clean_after_drag_and_drop (document, extension);
 
                g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "DOMGetActiveSignatureUid") == 0) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]