LayoutTests:

        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: http://svn.webkit.org/repository/webkit/trunk@25057 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 27c2fcf..7560ac5 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -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
index 0000000..b5df204
--- /dev/null
+++ b/LayoutTests/editing/selection/5333725-expected.checksum
@@ -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
index 0000000..bdddebf
--- /dev/null
+++ b/LayoutTests/editing/selection/5333725-expected.png
Binary files differ
diff --git a/LayoutTests/editing/selection/5333725-expected.txt b/LayoutTests/editing/selection/5333725-expected.txt
new file mode 100644
index 0000000..aecdf32
--- /dev/null
+++ b/LayoutTests/editing/selection/5333725-expected.txt
@@ -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
index 0000000..e5efb1d
--- /dev/null
+++ b/LayoutTests/editing/selection/5333725.html
@@ -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>
diff --git a/LayoutTests/editing/selection/select-all-user-select-none.html b/LayoutTests/editing/selection/select-all-user-select-none.html
index c05c518..06ecd8b 100644
--- a/LayoutTests/editing/selection/select-all-user-select-none.html
+++ b/LayoutTests/editing/selection/select-all-user-select-none.html
@@ -1,7 +1,7 @@
 <html>
     <head>
         <style>
-        html {
+        body {
             -webkit-user-select: none;
         }
         </style>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 2e4a5dc..07639c5 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -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.
diff --git a/WebCore/editing/SelectionController.cpp b/WebCore/editing/SelectionController.cpp
index f3d9ec1..6d3cdb8 100644
--- a/WebCore/editing/SelectionController.cpp
+++ b/WebCore/editing/SelectionController.cpp
@@ -1171,7 +1171,7 @@
     }
     
     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))
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index ae1d1f6..e635678 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -152,7 +152,7 @@
     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 @@
         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 @@
         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 @@
     RenderObject* targetRenderer = targetNode->renderer();
     if (!targetRenderer)
         return;
-
-    if (!targetRenderer->shouldSelect())
+        
+    if (!canMouseDragExtendSelect(targetNode))
         return;
 
     VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint));
@@ -727,7 +725,7 @@
             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 @@
         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;
diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h
index 98f11e7..92342dd 100644
--- a/WebCore/page/EventHandler.h
+++ b/WebCore/page/EventHandler.h
@@ -195,6 +195,7 @@
     void hoverTimerFired(Timer<EventHandler>*);
 
     static bool canMouseDownStartSelect(Node*);
+    static bool canMouseDragExtendSelect(Node*);
 
     void handleAutoscroll(RenderObject*);
     void startAutoscrollTimer();
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 18d5691..657bc7e 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -2011,40 +2011,6 @@
 
 #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 @@
                 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.
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index bfb07d7..b1ba0ef 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -754,13 +754,6 @@
     // 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;