REGRESSION: Dragging plain text into a styled text region does not acquire the correc...
authorenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Feb 2010 21:50:23 +0000 (21:50 +0000)
committerenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Feb 2010 21:50:23 +0000 (21:50 +0000)
<rdar://problem/7595685>
https://bugs.webkit.org/show_bug.cgi?id=34609

Reviewed by Oliver Hunt.

WebCore:

Test: editing/pasteboard/drop-inputtext-acquires-style.html

The dragging code did not distinguish the case of dragging the content of an input control
as a special case. The markup placed in the pasteboard included the style information.
I've modified the Clipboard class interface adding a new method writePlainText to match the
behavior of the copy and cut commands and modified the drag code to detect the special case.
I've modified all the platform specific implementations of the Clipboard class.

* dom/Clipboard.h: Added writePlainText pure virtual function.
* editing/Editor.cpp:
(WebCore::Editor::cut): Renamed nodeIsTextFormControl to isNodeInTextFormControl.
(WebCore::Editor::copy): Renamed nodeIsTextFormControl to isNodeInTextFormControl.
* editing/htmlediting.cpp:
(WebCore::isNodeInTextFormControl): Added, after removing the implementation with the old name
in Editor.cpp
* editing/htmlediting.h:
* page/DragController.cpp:
(WebCore::DragController::startDrag):
* platform/Pasteboard.h:
* platform/android/ClipboardAndroid.cpp:
(WebCore::ClipboardAndroid::writePlainText): Added.
* platform/android/ClipboardAndroid.h:
* platform/chromium/ClipboardChromium.cpp:
(WebCore::ClipboardChromium::writePlainText): Added.
* platform/chromium/ClipboardChromium.h:
* platform/gtk/ClipboardGtk.cpp:
(WebCore::ClipboardGtk::writePlainText): Added.
* platform/gtk/ClipboardGtk.h:
* platform/haiku/ClipboardHaiku.cpp:
(WebCore::ClipboardHaiku::writePlainText): Added.
* platform/haiku/ClipboardHaiku.h:
* platform/mac/ClipboardMac.h:
* platform/mac/ClipboardMac.mm:
(WebCore::ClipboardMac::writePlainText): Added.
* platform/mac/PasteboardMac.mm:
(WebCore::Pasteboard::writePlainText): Added helper function.
* platform/qt/ClipboardQt.cpp:
(WebCore::ClipboardQt::writePlainText): Added.
* platform/qt/ClipboardQt.h:
* platform/win/ClipboardWin.cpp:
(WebCore::ClipboardWin::writePlainText): Added.
* platform/win/ClipboardWin.h:

LayoutTests:

* editing/pasteboard/drop-inputtext-acquires-style-expected.txt: Added.
* editing/pasteboard/drop-inputtext-acquires-style.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@54368 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/drop-inputtext-acquires-style-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/drop-inputtext-acquires-style.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/dom/Clipboard.h
WebCore/editing/Editor.cpp
WebCore/editing/htmlediting.cpp
WebCore/editing/htmlediting.h
WebCore/page/DragController.cpp
WebCore/platform/Pasteboard.h
WebCore/platform/android/ClipboardAndroid.cpp
WebCore/platform/android/ClipboardAndroid.h
WebCore/platform/chromium/ClipboardChromium.cpp
WebCore/platform/chromium/ClipboardChromium.h
WebCore/platform/gtk/ClipboardGtk.cpp
WebCore/platform/gtk/ClipboardGtk.h
WebCore/platform/haiku/ClipboardHaiku.cpp
WebCore/platform/haiku/ClipboardHaiku.h
WebCore/platform/mac/ClipboardMac.h
WebCore/platform/mac/ClipboardMac.mm
WebCore/platform/mac/PasteboardMac.mm
WebCore/platform/qt/ClipboardQt.cpp
WebCore/platform/qt/ClipboardQt.h
WebCore/platform/win/ClipboardWin.cpp
WebCore/platform/win/ClipboardWin.h

index 8c3a15b..d6d3d19 100644 (file)
@@ -1,3 +1,14 @@
+2010-02-04  Enrica Casucci  <enrica@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        REGRESSION: Dragging plain text into a styled text region does not acquire the correct style info.
+        <rdar://problem/7595685>
+        https://bugs.webkit.org/show_bug.cgi?id=34609
+
+        * editing/pasteboard/drop-inputtext-acquires-style-expected.txt: Added.
+        * editing/pasteboard/drop-inputtext-acquires-style.html: Added.
+
 2010-02-04  Gustavo Noronha Silva  <gustavo.noronha@collabora.co.uk>
 
         Reviewed by Xan Lopez.
diff --git a/LayoutTests/editing/pasteboard/drop-inputtext-acquires-style-expected.txt b/LayoutTests/editing/pasteboard/drop-inputtext-acquires-style-expected.txt
new file mode 100644 (file)
index 0000000..5022ddf
--- /dev/null
@@ -0,0 +1,8 @@
+This test checks that the plain text dropped into a styled text region will acquire the appropriate style.
+To run this test manually, drag the text in the input element below into the bold text region. The dropped text should be bold. Click the verify button to check.
+
+Drag the text from the above iDrag this textnput element into this bold text
+<b contenteditable="true" id="destination">Drag the text from the above iDrag this textnput element into this bold text</b>
+SUCCESS
diff --git a/LayoutTests/editing/pasteboard/drop-inputtext-acquires-style.html b/LayoutTests/editing/pasteboard/drop-inputtext-acquires-style.html
new file mode 100644 (file)
index 0000000..7a27d45
--- /dev/null
@@ -0,0 +1,63 @@
+<html>
+<script>
+if (window.layoutTestController)
+     layoutTestController.dumpAsText();
+</script>
+<div>This test checks that the plain text dropped into a styled text region will acquire the appropriate style.</div>
+<p>To run this test manually, drag the text in the input element below into the bold text region.  The dropped text should be bold.
+Click the verify button to check.</p>
+<input type="button" value="Verify" onClick="verifier()">
+<br />
+<input id="grabme" value="Drag this text" >
+<br />
+<b contenteditable="true" id="destination">Drag the text from the above input element into this bold text</b>
+<ul id="console"></ul>
+
+<script>
+function log(message) {
+    var console = document.getElementById("console");
+    var li = document.createElement("li");
+    var pre = document.createElement("pre");
+    pre.appendChild(document.createTextNode(message));
+    li.appendChild(pre);
+    console.appendChild(li);
+}
+
+function runTest() {
+    var textToDrag = document.getElementById("grabme");
+    textToDrag.focus();
+
+    if (!window.layoutTestController)
+        return;
+    
+    var x = textToDrag.offsetLeft + textToDrag.offsetWidth / 2;
+    var y = textToDrag.offsetTop + textToDrag.offsetHeight / 2;
+
+    eventSender.mouseMoveTo(x, y);
+
+    eventSender.mouseDown();
+    // Wait a moment so that the mouseDown will kick off a drag
+    eventSender.leapForward(400);
+    
+    var destinationObject = document.getElementById("destination");
+    var x = destinationObject.offsetLeft + destinationObject.offsetWidth / 2;
+    var y = destinationObject.offsetTop + destinationObject.offsetHeight / 2;
+
+
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseUp();
+
+    verifier();
+}
+
+function verifier() {
+    log(document.getElementById("destination").outerHTML);
+    if (document.getElementById("destination").childNodes.length == 1)
+        log("SUCCESS");
+    else
+        log("FAILURE");
+}
+
+runTest();
+</script>
+</html>
index 84e6b91..cd5a1d0 100644 (file)
@@ -1,3 +1,54 @@
+2010-02-04  Enrica Casucci  <enrica@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        REGRESSION: Dragging plain text into a styled text region does not acquire the correct style info.
+        <rdar://problem/7595685>
+        https://bugs.webkit.org/show_bug.cgi?id=34609
+
+        Test: editing/pasteboard/drop-inputtext-acquires-style.html
+
+        The dragging code did not distinguish the case of dragging the content of an input control
+        as a special case. The markup placed in the pasteboard included the style information.
+        I've modified the Clipboard class interface adding a new method writePlainText to match the
+        behavior of the copy and cut commands and modified the drag code to detect the special case.
+        I've modified all the platform specific implementations of the Clipboard class.
+        
+        * dom/Clipboard.h: Added writePlainText pure virtual function.
+        * editing/Editor.cpp:
+        (WebCore::Editor::cut): Renamed nodeIsTextFormControl to isNodeInTextFormControl.
+        (WebCore::Editor::copy): Renamed nodeIsTextFormControl to isNodeInTextFormControl.
+        * editing/htmlediting.cpp:
+        (WebCore::isNodeInTextFormControl): Added, after removing the implementation with the old name
+        in Editor.cpp
+        * editing/htmlediting.h:
+        * page/DragController.cpp:
+        (WebCore::DragController::startDrag):
+        * platform/Pasteboard.h:
+        * platform/android/ClipboardAndroid.cpp:
+        (WebCore::ClipboardAndroid::writePlainText): Added.
+        * platform/android/ClipboardAndroid.h:
+        * platform/chromium/ClipboardChromium.cpp:
+        (WebCore::ClipboardChromium::writePlainText): Added.
+        * platform/chromium/ClipboardChromium.h:
+        * platform/gtk/ClipboardGtk.cpp:
+        (WebCore::ClipboardGtk::writePlainText): Added.
+        * platform/gtk/ClipboardGtk.h:
+        * platform/haiku/ClipboardHaiku.cpp:
+        (WebCore::ClipboardHaiku::writePlainText): Added.
+        * platform/haiku/ClipboardHaiku.h:
+        * platform/mac/ClipboardMac.h:
+        * platform/mac/ClipboardMac.mm:
+        (WebCore::ClipboardMac::writePlainText): Added.
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::Pasteboard::writePlainText): Added helper function.
+        * platform/qt/ClipboardQt.cpp:
+        (WebCore::ClipboardQt::writePlainText): Added.
+        * platform/qt/ClipboardQt.h:
+        * platform/win/ClipboardWin.cpp:
+        (WebCore::ClipboardWin::writePlainText): Added.
+        * platform/win/ClipboardWin.h:
+
 2010-02-04  Steve Block  <steveblock@google.com>
 
         Reviewed by Nate Chapin.
index 042cd82..2f4dc6f 100644 (file)
@@ -69,6 +69,7 @@ namespace WebCore {
 #endif
         virtual void writeURL(const KURL&, const String&, Frame*) = 0;
         virtual void writeRange(Range*, Frame*) = 0;
+        virtual void writePlainText(const String&) = 0;
 
         virtual bool hasData() = 0;
         
index 5798452..1061dd2 100644 (file)
@@ -1004,16 +1004,6 @@ bool Editor::insertParagraphSeparator()
     return true;
 }
 
-static bool nodeIsInTextFormControl(Node* node)
-{
-    if (!node)
-        return false;
-    Node* ancestor = node->shadowAncestorNode();
-    if (ancestor == node)
-        return false;
-    return ancestor->isElementNode() && static_cast<Element*>(ancestor)->isTextFormControl();
-}
-
 void Editor::cut()
 {
     if (tryDHTMLCut())
@@ -1024,7 +1014,7 @@ void Editor::cut()
     }
     RefPtr<Range> selection = selectedRange();
     if (shouldDeleteRange(selection.get())) {
-        if (nodeIsInTextFormControl(m_frame->selection()->start().node()))
+        if (isNodeInTextFormControl(m_frame->selection()->start().node()))
             Pasteboard::generalPasteboard()->writePlainText(m_frame->selectedText());
         else
             Pasteboard::generalPasteboard()->writeSelection(selection.get(), canSmartCopyOrDelete(), m_frame);
@@ -1042,7 +1032,7 @@ void Editor::copy()
         return;
     }
 
-    if (nodeIsInTextFormControl(m_frame->selection()->start().node()))
+    if (isNodeInTextFormControl(m_frame->selection()->start().node()))
         Pasteboard::generalPasteboard()->writePlainText(m_frame->selectedText());
     else {
         Document* document = m_frame->document();
index b58dff3..6140353 100644 (file)
@@ -911,6 +911,16 @@ Node *tabSpanNode(const Node *node)
     return isTabSpanTextNode(node) ? node->parentNode() : 0;
 }
 
+bool isNodeInTextFormControl(Node* node)
+{
+    if (!node)
+        return false;
+    Node* ancestor = node->shadowAncestorNode();
+    if (ancestor == node)
+        return false;
+    return ancestor->isElementNode() && static_cast<Element*>(ancestor)->isTextFormControl();
+}
+    
 Position positionBeforeTabSpan(const Position& pos)
 {
     Node *node = pos.node();
index c5a44ac..d523b40 100644 (file)
@@ -93,7 +93,7 @@ bool isListElement(Node*);
 bool isNodeRendered(const Node*);
 bool isNodeVisiblyContainedWithin(Node*, const Range*);
 bool isRenderedAsNonInlineTableImageOrHR(const Node*);
-    
+bool isNodeInTextFormControl(Node* node);
     
 // -------------------------------------------------------------------------
 // Position
index bde38bc..c9769df 100644 (file)
@@ -697,10 +697,16 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
         }
         doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true);
     } else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) {
-        RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
-        ASSERT(selectionRange);
-        if (!clipboard->hasData())
-            clipboard->writeRange(selectionRange.get(), src);
+        if (!clipboard->hasData()) {
+            if (isNodeInTextFormControl(src->selection()->start().node()))
+                clipboard->writePlainText(src->selectedText());
+            else {
+                RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
+                ASSERT(selectionRange);
+
+                clipboard->writeRange(selectionRange.get(), src);
+            }
+        }
         m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
         if (!dragImage) {
             dragImage = createDragImageForSelection(src);
index 188b962..7a47f00 100644 (file)
@@ -82,6 +82,7 @@ public:
     //Helper functions to allow Clipboard to share code
     static void writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame);
     static void writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame);
+    static void writePlainText(NSPasteboard* pasteboard, const String& text);
 #endif
     
     static Pasteboard* generalPasteboard();
index da2c230..375f980 100644 (file)
@@ -103,6 +103,10 @@ void ClipboardAndroid::writeRange(Range* selectedRange, Frame*)
     ASSERT(selectedRange);
 }
 
+void ClipboardAndroid::writePlainText(const String&)
+{
+}
+
 bool ClipboardAndroid::hasData()
 {
     return false;
index 723c991..23bfdf6 100644 (file)
@@ -56,6 +56,7 @@ public:
     virtual void declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*);
     virtual void writeURL(const KURL&, const String&, Frame*);
     virtual void writeRange(Range*, Frame*);
+    virtual void writePlainText(const String&);
 
     virtual bool hasData();
 };
index 32f7d50..89fd61d 100644 (file)
@@ -376,6 +376,19 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame)
     m_dataObject->plainText = str;
 }
 
+void ClipboardChromium::writePlainText(const String& text)
+{
+    if (!m_dataObject)
+        return;
+
+    String str = text;
+#if OS(WINDOWS)
+    replaceNewlinesWithWindowsStyleNewlines(str);
+#endif
+    replaceNBSPWithSpace(str);
+    m_dataObject->plainText = str;
+}
+
 bool ClipboardChromium::hasData()
 {
     if (!m_dataObject)
index cf2f046..fbebde2 100644 (file)
@@ -74,6 +74,7 @@ namespace WebCore {
         virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
         virtual void writeURL(const KURL&, const String&, Frame*);
         virtual void writeRange(Range*, Frame*);
+        virtual void writePlainText(const String&);
 
         virtual bool hasData();
 
index 450966e..6122d8f 100644 (file)
@@ -176,6 +176,15 @@ void ClipboardGtk::writeRange(Range* range, Frame* frame)
     gtk_clipboard_set_text(htmlClipboard, createMarkup(range, 0, AnnotateForInterchange).utf8().data(), -1);
 }
 
+void ClipboardGtk::writePlainText(const String& text)
+{
+    GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText"));
+    
+    gtk_clipboard_clear(textClipboard);
+    
+    gtk_clipboard_set_text(textClipboard, text.utf8().data(), -1);
+}
+    
 bool ClipboardGtk::hasData()
 {
     notImplemented();
index bb21d92..74e36b1 100644 (file)
@@ -60,6 +60,7 @@ namespace WebCore {
         virtual void declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*);
         virtual void writeURL(const KURL&, const String&, Frame*);
         virtual void writeRange(Range*, Frame*);
+        virtual void writePlainText(const String&);
 
         virtual bool hasData();
 
index a62c30c..f73be01 100644 (file)
@@ -187,6 +187,11 @@ void ClipboardHaiku::writeRange(Range*, Frame*)
     notImplemented();
 }
 
+void ClipboardHaiku::writePlainText(const String&)
+{
+    notImplemented();
+}
+
 bool ClipboardHaiku::hasData()
 {
     bool result = false;
index 23e3d7b..37ffe5c 100644 (file)
@@ -61,6 +61,7 @@ namespace WebCore {
         virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
         virtual void writeURL(const KURL&, const String&, Frame*);
         virtual void writeRange(Range*, Frame*);
+        virtual void writePlainText(const String&);
 
         virtual bool hasData();
 
index 3d3c78e..adde09c 100644 (file)
@@ -72,6 +72,7 @@ public:
 #endif
     virtual void writeRange(Range*, Frame* frame);
     virtual void writeURL(const KURL&, const String&, Frame* frame);
+    virtual void writePlainText(const String&);
     
     // Methods for getting info in Cocoa's type system
     NSImage *dragNSImage(NSPoint&) const; // loc converted from dragLoc, based on whole image size
index f4321ad..ddfa0d5 100644 (file)
@@ -367,7 +367,12 @@ void ClipboardMac::writeRange(Range* range, Frame* frame)
     ASSERT(frame);
     Pasteboard::writeSelection(m_pasteboard.get(), range, frame->editor()->smartInsertDeleteEnabled() && frame->selectionGranularity() == WordGranularity, frame);
 }
-    
+
+void ClipboardMac::writePlainText(const String& text)
+{
+    Pasteboard::writePlainText(m_pasteboard.get(), text);
+}
+
 void ClipboardMac::writeURL(const KURL& url, const String& title, Frame* frame)
 {   
     ASSERT(frame);
index 8aa7f2c..690637a 100644 (file)
@@ -197,6 +197,14 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange,
         [pasteboard setData:nil forType:WebSmartPastePboardType];
     }
 }
+
+void Pasteboard::writePlainText(NSPasteboard* pasteboard, const String& text)
+{
+    NSArray *types = [NSArray arrayWithObject:NSStringPboardType];
+    [pasteboard declareTypes:types owner:nil];
+    
+    [pasteboard setString:text forType:NSStringPboardType];
+}
     
 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
 {
index f9940a6..5ed4cb0 100644 (file)
@@ -290,6 +290,17 @@ void ClipboardQt::writeRange(Range* range, Frame* frame)
 #endif
 }
 
+void ClipboardQt::writePlainText(const String& str)
+{
+    QString text = str;
+    text.replace(QChar(0xa0), QLatin1Char(' '));
+    m_writableData->setText(text);
+#ifndef QT_NO_CLIPBOARD
+    if (!isForDragging())
+        QApplication::clipboard()->setMimeData(m_writableData);
+#endif
+}
+
 bool ClipboardQt::hasData()
 {
     const QMimeData *data = m_readableData ? m_readableData : m_writableData;
index 9a918ed..9b54d5f 100644 (file)
@@ -66,6 +66,7 @@ namespace WebCore {
         virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
         virtual void writeURL(const KURL&, const String&, Frame*);
         virtual void writeRange(Range*, Frame*);
+        virtual void writePlainText(const String&);
 
         virtual bool hasData();
 
index f83927d..d61e681 100644 (file)
@@ -776,6 +776,25 @@ void ClipboardWin::writeRange(Range* selectedRange, Frame* frame)
         m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE);
 }
 
+void ClipboardWin::writePlainText(const String& text)
+{
+    if (!m_writableDataObject)
+        return;
+    
+    STGMEDIUM medium = {0};
+    medium.tymed = TYMED_HGLOBAL;
+    ExceptionCode ec = 0;
+    
+    String str = text;
+    replaceNewlinesWithWindowsStyleNewlines(str);
+    replaceNBSPWithSpace(str);
+    medium.hGlobal = createGlobalData(str);
+    if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE)))
+        ::GlobalFree(medium.hGlobal);        
+
+    medium.hGlobal = 0;
+}
+    
 bool ClipboardWin::hasData()
 {
     if (!m_dataObject)
index 6e60254..49fdcfe 100644 (file)
@@ -67,6 +67,7 @@ namespace WebCore {
         virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
         virtual void writeURL(const KURL&, const String&, Frame*);
         virtual void writeRange(Range*, Frame*);
+        virtual void writePlainText(const String&);
 
         virtual bool hasData();