LayoutTests:
authorjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Aug 2007 19:14:49 +0000 (19:14 +0000)
committerjusting <justing@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Aug 2007 19:14:49 +0000 (19:14 +0000)
        Reviewed by Darin.

        <rdar://problem/5333725> -webkit-user-select: none makes selection difficult

        * editing/selection/5333725-expected.checksum: Added.
        * editing/selection/5333725-expected.png: Added.
        * editing/selection/5333725-expected.txt: Added.
        * editing/selection/5333725.html: Added.

        Added a workaround for a bug where -webkit-user-select:none
        has no effect on the body if placed on the html element:
        * editing/selection/select-all-user-select-none.html:

WebCore:

        Reviewed by Darin.

        <rdar://problem/5333725> -webkit-user-select: none makes selection difficult

        Let users create selections if they mouse down in a -webkit-user-select:none
        region, just (continue to) disallow selection endpoints in those regions, and
        don't paint those regions as selected if they are fully enclosed by a selection.
        For example, in xxyyyxx where x is -webkit-user-select:none, a user can mouse down
        between the first two xs and drag across yyy to the second two xs to create a
        selection xx^yyy^xx.

        * editing/SelectionController.cpp:
        (WebCore::SelectionController::selectAll): Allow selectAll inside a root
        that has -webkit-user-select:none, because it may contain content that
        is selectable (VisiblePosition and Selection creation will keep Selection
        endpoints out of -webkit-user-select:none regions).
        * page/EventHandler.cpp:
        (WebCore::EventHandler::selectClosestWordFromMouseEvent): Use canMouseDownStartSelect
        instead of the ambiguously named shouldSelect().
        (WebCore::EventHandler::handleMousePressEventTripleClick): Ditto.
        (WebCore::EventHandler::handleMousePressEventSingleClick): Ditto.
        (WebCore::EventHandler::updateSelectionForMouseDrag): Use canMouseDragExtendSelect.
        (WebCore::EventHandler::selectCursor): Paint an ibeam in -webkit-user-select:none regions,
        because you can click in those regions to create a selection.
        (WebCore::EventHandler::canMouseDownStartSelect): Now fires the selectStart event, and
        returns true in -webkit-user-select: none regions.
        (WebCore::EventHandler::canMouseDragExtendSelect): This is identical to
        canMouseDownStartSelect because of 12823, even though it seems strange that we would fire
        the selectStart event here.
        * page/EventHandler.h:
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::draggableNode): Only -webkit-user-select:ignore regions will
        prevent selection creation.
        * rendering/RenderObject.h:

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/selection/5333725-expected.checksum [new file with mode: 0644]
LayoutTests/editing/selection/5333725-expected.png [new file with mode: 0644]
LayoutTests/editing/selection/5333725-expected.txt [new file with mode: 0644]
LayoutTests/editing/selection/5333725.html [new file with mode: 0644]
LayoutTests/editing/selection/select-all-user-select-none.html
WebCore/ChangeLog
WebCore/editing/SelectionController.cpp
WebCore/page/EventHandler.cpp
WebCore/page/EventHandler.h
WebCore/rendering/RenderObject.cpp
WebCore/rendering/RenderObject.h

index 27c2fcf916d4043c465d16e895ea7497f4a77f3e..7560ac5e254a039e92a67257833b9f19db92671b 100644 (file)
@@ -1,3 +1,18 @@
+2007-08-13  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by Darin.
+        
+        <rdar://problem/5333725> -webkit-user-select: none makes selection difficult
+
+        * editing/selection/5333725-expected.checksum: Added.
+        * editing/selection/5333725-expected.png: Added.
+        * editing/selection/5333725-expected.txt: Added.
+        * editing/selection/5333725.html: Added.
+        
+        Added a workaround for a bug where -webkit-user-select:none
+        has no effect on the body if placed on the html element:
+        * editing/selection/select-all-user-select-none.html:
+
 2007-08-13  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Maciej.
diff --git a/LayoutTests/editing/selection/5333725-expected.checksum b/LayoutTests/editing/selection/5333725-expected.checksum
new file mode 100644 (file)
index 0000000..b5df204
--- /dev/null
@@ -0,0 +1 @@
+bf4c7f58044f385ff40ffc133572fa98
\ No newline at end of file
diff --git a/LayoutTests/editing/selection/5333725-expected.png b/LayoutTests/editing/selection/5333725-expected.png
new file mode 100644 (file)
index 0000000..bdddebf
Binary files /dev/null and b/LayoutTests/editing/selection/5333725-expected.png differ
diff --git a/LayoutTests/editing/selection/5333725-expected.txt b/LayoutTests/editing/selection/5333725-expected.txt
new file mode 100644 (file)
index 0000000..aecdf32
--- /dev/null
@@ -0,0 +1,16 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x18
+        RenderInline {SPAN} at (0,0) size 32x18
+          RenderText {#text} at (0,0) size 32x18
+            text run at (0,0) width 32: "0123"
+        RenderText {#text} at (32,0) size 16x18
+          text run at (32,0) width 16: "45"
+        RenderInline {SPAN} at (0,0) size 32x18
+          RenderText {#text} at (48,0) size 32x18
+            text run at (48,0) width 32: "6789"
+selection start: position 0 of child 1 {#text} of child 0 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+selection end:   position 2 of child 1 {#text} of child 0 {DIV} of child 0 {BODY} of child 0 {HTML} of document
diff --git a/LayoutTests/editing/selection/5333725.html b/LayoutTests/editing/selection/5333725.html
new file mode 100644 (file)
index 0000000..e5efb1d
--- /dev/null
@@ -0,0 +1,23 @@
+<div><span id="start" style="-webkit-user-select:none;">0123</span>45<span id="end" style="-webkit-user-select:none;">6789</span></div>
+
+<script>
+if (window.layoutTestController) {
+    start = document.getElementById("start");
+    x1 = start.offsetParent.offsetLeft + start.offsetLeft + start.offsetWidth / 2;
+    y1 = start.offsetParent.offsetTop + start.offsetTop + start.offsetHeight / 2;
+    eventSender.mouseMoveTo(x1, y1);
+    eventSender.mouseDown();
+    
+    eventSender.leapForward(100);
+    eventSender.mouseMoveTo(x1 + 5, y1);
+    eventSender.leapForward(100);
+    eventSender.mouseMoveTo(x1 + 10, y1);
+    
+    end = document.getElementById("end");
+    x2 = end.offsetParent.offsetLeft + end.offsetLeft + end.offsetWidth / 2;
+    y2 = end.offsetParent.offsetTop + end.offsetTop + end.offsetHeight / 2;
+    
+    eventSender.mouseMoveTo(x2, y2);
+    eventSender.mouseUp();
+}
+</script>
index c05c518ac0c3ee99d0348a7762674c797aee81e5..06ecd8b2ef5202dbde3c2ba85847d1b2648e513d 100644 (file)
@@ -1,7 +1,7 @@
 <html>
     <head>
         <style>
-        html {
+        body {
             -webkit-user-select: none;
         }
         </style>
index 2e4a5dce4e7410418b9ac51f0e09bba8e5549239..07639c563ba9417923def1175f4350ec3fb265a2 100644 (file)
@@ -1,3 +1,40 @@
+2007-08-13  Justin Garcia  <justin.garcia@apple.com>
+
+        Reviewed by Darin.
+        
+        <rdar://problem/5333725> -webkit-user-select: none makes selection difficult
+        
+        Let users create selections if they mouse down in a -webkit-user-select:none
+        region, just (continue to) disallow selection endpoints in those regions, and
+        don't paint those regions as selected if they are fully enclosed by a selection. 
+        For example, in xxyyyxx where x is -webkit-user-select:none, a user can mouse down
+        between the first two xs and drag across yyy to the second two xs to create a 
+        selection xx^yyy^xx.
+        
+        * editing/SelectionController.cpp:
+        (WebCore::SelectionController::selectAll): Allow selectAll inside a root
+        that has -webkit-user-select:none, because it may contain content that
+        is selectable (VisiblePosition and Selection creation will keep Selection
+        endpoints out of -webkit-user-select:none regions).
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::selectClosestWordFromMouseEvent): Use canMouseDownStartSelect
+        instead of the ambiguously named shouldSelect().
+        (WebCore::EventHandler::handleMousePressEventTripleClick): Ditto.
+        (WebCore::EventHandler::handleMousePressEventSingleClick): Ditto.
+        (WebCore::EventHandler::updateSelectionForMouseDrag): Use canMouseDragExtendSelect.
+        (WebCore::EventHandler::selectCursor): Paint an ibeam in -webkit-user-select:none regions,
+        because you can click in those regions to create a selection.
+        (WebCore::EventHandler::canMouseDownStartSelect): Now fires the selectStart event, and
+        returns true in -webkit-user-select: none regions.
+        (WebCore::EventHandler::canMouseDragExtendSelect): This is identical to 
+        canMouseDownStartSelect because of 12823, even though it seems strange that we would fire 
+        the selectStart event here.
+        * page/EventHandler.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::draggableNode): Only -webkit-user-select:ignore regions will
+        prevent selection creation.
+        * rendering/RenderObject.h:
+
 2007-08-13  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Maciej.
index f3d9ec1ad639cc11c8fc5c632ae4aab164ba9d62..6d3cdb844201e2473688b4c3cd05d282f8f4d0a0 100644 (file)
@@ -1171,7 +1171,7 @@ void SelectionController::selectAll()
     }
     
     Node* root = isContentEditable() ? highestEditableRoot(m_sel.start()) : document->documentElement();
-    if (!root || !root->renderer() || !root->renderer()->canSelect())
+    if (!root)
         return;
     Selection newSelection(Selection::selectionFromContentsOfNode(root));
     if (m_frame->shouldChangeSelection(newSelection))
index ae1d1f6816bd97dfe15bfd79a5eb90c7749d5c14..e6356785369f8d50c02f8f1475860bde15712517 100644 (file)
@@ -152,7 +152,7 @@ void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe
     Node* innerNode = result.targetNode();
     Selection newSelection;
 
-    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect && innerNode->renderer()->shouldSelect()) {
+    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
         VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
         if (pos.isNotNull()) {
             newSelection = Selection(pos);
@@ -193,8 +193,7 @@ bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR
         return false;
     
     Node* innerNode = event.targetNode();
-    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect
-          && innerNode->renderer()->shouldSelect()))
+    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
         return false;
 
     Selection newSelection;
@@ -220,8 +219,7 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR
         return false;
     
     Node* innerNode = event.targetNode();
-    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect
-          && innerNode->renderer()->shouldSelect()))
+    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
         return false;
 
     // Extend the selection if the Shift key is down, unless the click is in a link.
@@ -408,8 +406,8 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint&
     RenderObject* targetRenderer = targetNode->renderer();
     if (!targetRenderer)
         return;
-
-    if (!targetRenderer->shouldSelect())
+        
+    if (!canMouseDragExtendSelect(targetNode))
         return;
 
     VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint));
@@ -727,7 +725,7 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Pla
             bool inResizer = false;
             if (m_frame->view() && layer && layer->isPointInResizeControl(m_frame->view()->windowToContents(event.event().pos())))
                 inResizer = true;
-            if ((editable || (renderer && renderer->isText() && renderer->canSelect())) && !inResizer && !scrollbar)
+            if ((editable || (renderer && renderer->isText() && renderer->style()->userSelect() != SELECT_IGNORE)) && !inResizer && !scrollbar)
                 return iBeamCursor();
             return pointerCursor();
         }
@@ -1360,23 +1358,29 @@ void EventHandler::scheduleHoverStateUpdate()
         m_hoverTimer.startOneShot(0);
 }
 
+// Whether or not a mouse down can begin the creation of a selection.  Fires the selectStart event.
 bool EventHandler::canMouseDownStartSelect(Node* node)
 {
     if (!node || !node->renderer())
         return true;
     
-    // Check to see if -webkit-user-select has been set to none
-    if (!node->renderer()->canSelect())
-        return false;
-    
     // Some controls and images can't start a select on a mouse down.
     for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
         if (curr->style()->userSelect() == SELECT_IGNORE)
             return false;
+            
+    for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())    
+        if (Node* node = curr->element())
+            return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent, true, true);
     
     return true;
 }
 
+bool EventHandler::canMouseDragExtendSelect(Node* node)
+{
+    return canMouseDownStartSelect(node);
+}
+
 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
 {
     m_frameSetBeingResized = frameSet;
index 98f11e73750eb83e78bc839b9ab4110116576603..92342dd436ba20c41c14327c7a1192ce04abceed 100644 (file)
@@ -195,6 +195,7 @@ private:
     void hoverTimerFired(Timer<EventHandler>*);
 
     static bool canMouseDownStartSelect(Node*);
+    static bool canMouseDragExtendSelect(Node*);
 
     void handleAutoscroll(RenderObject*);
     void startAutoscrollTimer();
index 18d5691a59b7bfb2b7ea18a71ee85a04a326cd87..657bc7e08ed9063ff11c2be85c6c33ad8e963982 100644 (file)
@@ -2011,40 +2011,6 @@ void RenderObject::showTreeForThis() const
 
 #endif // NDEBUG
 
-static Node* selectStartNode(const RenderObject* object)
-{
-    Node* node = 0;
-    bool forcedOn = false;
-
-    for (const RenderObject* curr = object; curr; curr = curr->parent()) {
-        if (curr->style()->userSelect() == SELECT_TEXT)
-            forcedOn = true;
-        if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
-            return 0;
-
-        if (!node)
-            node = curr->element();
-    }
-
-    // somewhere up the render tree there must be an element!
-    ASSERT(node);
-
-    return node;
-}
-
-bool RenderObject::canSelect() const
-{
-    return selectStartNode(this) != 0;
-}
-
-bool RenderObject::shouldSelect() const
-{
-    if (Node* node = selectStartNode(this))
-        return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent, true, true);
-
-    return false;
-}
-
 Color RenderObject::selectionBackgroundColor() const
 {
     Color color;
@@ -2093,7 +2059,7 @@ Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& d
                 dhtmlWillDrag = false;
                 return curr->node();
             }
-            if (curr->shouldSelect())
+            if (curr->style()->userSelect() != SELECT_IGNORE)
                 // In this case we have a click in the unselected portion of text.  If this text is
                 // selectable, we want to start the selection process instead of looking for a parent
                 // to try to drag.
index bfb07d7a9683e0b22f340f077f564ba114f58e0e..b1ba0ef51bc7fa79ead2bb09ce98bfab7edfdbe7 100644 (file)
@@ -754,13 +754,6 @@ public:
     // Whether or not a block has selected children.
     virtual bool hasSelectedChildren() const { return false; }
 
-    // Whether or not a selection can be attempted on this object.
-    bool canSelect() const;
-
-    // Whether or not a selection can be attempted on this object.  Should only be called right before actually beginning a selection,
-    // since it fires the selectstart DOM event.
-    bool shouldSelect() const;
-
     // Obtains the selection colors that should be used when painting a selection.
     Color selectionBackgroundColor() const;
     Color selectionForegroundColor() const;