Change cursor to hand over missing plug-in message
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Oct 2011 02:26:10 +0000 (02:26 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Oct 2011 02:26:10 +0000 (02:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=69312

Reviewed by Sam Weinig.

No tests because we currently don't have any test machinery for cursors.

* page/EventHandler.cpp:
(WebCore::OptionalCursor::OptionalCursor): Added. Construct an object
to represent either a cursor, or no cursor change.
(WebCore::OptionalCursor::isCursorChange): Added.
(WebCore::OptionalCursor::cursor): Added.
(WebCore::EventHandler::selectCursor): Changed return type to OptionalCursor,
moved some special cases from handleMouseMoveEvent in here. Moved the logic
for plug-ins and framesets into the specific renderer classes for those.
Added a call to the new getCursor virtual function.
(WebCore::EventHandler::handleMouseMoveEvent): Changed cursor setting code to
just be a call to selectCursor and then setCursor. Plug-in-specific code is now
in RenderWidget.

* page/EventHandler.h: Changed return type of selectCursor.

* page/MouseEventWithHitTestResults.cpp: Made some functions be inline.
* page/MouseEventWithHitTestResults.h:
(WebCore::MouseEventWithHitTestResults::localPoint): Made this inline.
(WebCore::MouseEventWithHitTestResults::scrollbar): Made this inline.
Yes, this has nothing to do with the rest of the patch, but it's good.

* rendering/RenderEmbeddedObject.cpp:
(WebCore::RenderEmbeddedObject::getReplacementTextGeometry): Made const.
(WebCore::RenderEmbeddedObject::isInMissingPluginIndicator): Made const.
Overloaded so it can be called with a point rather than an event.
(WebCore::shouldMissingPluginMessageBeButton): Added. Helps streamline
the logic below.
(WebCore::RenderEmbeddedObject::handleMissingPluginIndicatorEvent):
Changed to use shouldMissingPluginMessageBeButton.
(WebCore::RenderEmbeddedObject::getCursor): Added. Sets the cursor to
a hand when over the missing plug-in message.
* rendering/RenderEmbeddedObject.h: Added getCursor override. Also updated
for other changes above.

* rendering/RenderFrameSet.cpp:
(WebCore::RenderFrameSet::getCursor): Added. Contains the logic that used
to be hardcoded in EventHandler::selectCursor about cursors when over
resizable frame borders.
* rendering/RenderFrameSet.h: Added getCursor.

* rendering/RenderObject.cpp:
(WebCore::RenderObject::getCursor): Added. Returns SetCursorBasedOnStyle.
* rendering/RenderObject.h: Added getCursor.

* rendering/RenderWidget.cpp:
(WebCore::RenderWidget::getCursor): Added. Contains the logic that used
to be hardcoded in EventHandler::handleMouseMoveEvent to prevent setting
the cursor when the pointer is over a plug-in. This new code is much better,
because it only kicks in when there is actually a plug-in present. The old
was based on the HTML tag!
* rendering/RenderWidget.h: Added getCursor.

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

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/page/MouseEventWithHitTestResults.cpp
Source/WebCore/page/MouseEventWithHitTestResults.h
Source/WebCore/rendering/RenderEmbeddedObject.cpp
Source/WebCore/rendering/RenderEmbeddedObject.h
Source/WebCore/rendering/RenderFrameSet.cpp
Source/WebCore/rendering/RenderFrameSet.h
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderObject.h
Source/WebCore/rendering/RenderWidget.cpp
Source/WebCore/rendering/RenderWidget.h

index d70aec9..6871c9d 100644 (file)
@@ -1,3 +1,64 @@
+2011-10-03  Darin Adler  <darin@apple.com>
+
+        Change cursor to hand over missing plug-in message
+        https://bugs.webkit.org/show_bug.cgi?id=69312
+
+        Reviewed by Sam Weinig.
+
+        No tests because we currently don't have any test machinery for cursors.
+
+        * page/EventHandler.cpp:
+        (WebCore::OptionalCursor::OptionalCursor): Added. Construct an object
+        to represent either a cursor, or no cursor change.
+        (WebCore::OptionalCursor::isCursorChange): Added.
+        (WebCore::OptionalCursor::cursor): Added.
+        (WebCore::EventHandler::selectCursor): Changed return type to OptionalCursor,
+        moved some special cases from handleMouseMoveEvent in here. Moved the logic
+        for plug-ins and framesets into the specific renderer classes for those.
+        Added a call to the new getCursor virtual function.
+        (WebCore::EventHandler::handleMouseMoveEvent): Changed cursor setting code to
+        just be a call to selectCursor and then setCursor. Plug-in-specific code is now
+        in RenderWidget.
+
+        * page/EventHandler.h: Changed return type of selectCursor.
+
+        * page/MouseEventWithHitTestResults.cpp: Made some functions be inline.
+        * page/MouseEventWithHitTestResults.h:
+        (WebCore::MouseEventWithHitTestResults::localPoint): Made this inline.
+        (WebCore::MouseEventWithHitTestResults::scrollbar): Made this inline.
+        Yes, this has nothing to do with the rest of the patch, but it's good.
+
+        * rendering/RenderEmbeddedObject.cpp:
+        (WebCore::RenderEmbeddedObject::getReplacementTextGeometry): Made const.
+        (WebCore::RenderEmbeddedObject::isInMissingPluginIndicator): Made const.
+        Overloaded so it can be called with a point rather than an event.
+        (WebCore::shouldMissingPluginMessageBeButton): Added. Helps streamline
+        the logic below.
+        (WebCore::RenderEmbeddedObject::handleMissingPluginIndicatorEvent):
+        Changed to use shouldMissingPluginMessageBeButton.
+        (WebCore::RenderEmbeddedObject::getCursor): Added. Sets the cursor to
+        a hand when over the missing plug-in message.
+        * rendering/RenderEmbeddedObject.h: Added getCursor override. Also updated
+        for other changes above.
+
+        * rendering/RenderFrameSet.cpp:
+        (WebCore::RenderFrameSet::getCursor): Added. Contains the logic that used
+        to be hardcoded in EventHandler::selectCursor about cursors when over
+        resizable frame borders.
+        * rendering/RenderFrameSet.h: Added getCursor.
+
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::getCursor): Added. Returns SetCursorBasedOnStyle.
+        * rendering/RenderObject.h: Added getCursor.
+
+        * rendering/RenderWidget.cpp:
+        (WebCore::RenderWidget::getCursor): Added. Contains the logic that used
+        to be hardcoded in EventHandler::handleMouseMoveEvent to prevent setting
+        the cursor when the pointer is over a plug-in. This new code is much better,
+        because it only kicks in when there is actually a plug-in present. The old
+        was based on the HTML tag!
+        * rendering/RenderWidget.h: Added getCursor.
+
 2011-10-03  Anders Carlsson  <andersca@apple.com>
 
         Work towards making PlatformWheelEvent immutable
index 429b920..efb8269 100644 (file)
@@ -127,6 +127,21 @@ const double autoscrollInterval = 0.05;
 
 const double fakeMouseMoveInterval = 0.1;
 
+enum NoCursorChangeType { NoCursorChange };
+
+class OptionalCursor {
+public:
+    OptionalCursor(NoCursorChangeType) : m_isCursorChange(false) { }
+    OptionalCursor(const Cursor& cursor) : m_isCursorChange(true), m_cursor(cursor) { }
+
+    bool isCursorChange() const { return m_isCursorChange; }
+    const Cursor& cursor() const { return m_cursor; }
+
+private:
+    bool m_isCursorChange;
+    Cursor m_cursor;
+};
+
 static inline bool scrollNode(float delta, WheelEvent::Granularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode)
 {
     if (!delta)
@@ -1150,12 +1165,20 @@ static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
     return frame->selection()->rootEditableElement() != node->rootEditableElement();
 }
 
-Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar)
+OptionalCursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar)
 {
+    if (m_resizeLayer && m_resizeLayer->inResizeMode())
+        return NoCursorChange;
+
+    Page* page = m_frame->page();
+    if (!page)
+        return NoCursorChange;
+    if (page->mainFrame()->eventHandler()->m_panScrollInProgress)
+        return NoCursorChange;
+
     Node* node = targetNode(event);
     RenderObject* renderer = node ? node->renderer() : 0;
     RenderStyle* style = renderer ? renderer->style() : 0;
-
     bool horizontalText = !style || style->isHorizontalWritingMode();
     const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor();
 
@@ -1164,12 +1187,16 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr
     if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode)
         return iBeam;
 
-    if (renderer && renderer->isFrameSet()) {
-        RenderFrameSet* frameSetRenderer = toRenderFrameSet(renderer);
-        if (frameSetRenderer->canResizeRow(event.localPoint()))
-            return rowResizeCursor();
-        if (frameSetRenderer->canResizeColumn(event.localPoint()))
-            return columnResizeCursor();
+    if (renderer) {
+        Cursor overrideCursor;
+        switch (renderer->getCursor(event.localPoint(), overrideCursor)) {
+        case SetCursorBasedOnStyle:
+            break;
+        case SetCursor:
+            return overrideCursor;
+        case DoNotSetCursor:
+            return NoCursorChange;
+        }
     }
 
     if (style && style->cursors()) {
@@ -1629,21 +1656,10 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
     } else {
         if (scrollbar && !m_mousePressed)
             scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
-        if (Page* page = m_frame->page()) {
-            if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->m_panScrollInProgress) {
-                // Plugins set cursor on their own. The only case WebKit intervenes is resetting cursor to arrow on mouse enter,
-                // in case the particular plugin doesn't manipulate cursor at all. Thus,  even a CSS cursor set on body has no
-                // effect on plugins (which matches Firefox).
-                bool overPluginElement = false;
-                if (targetNode(mev) && targetNode(mev)->isHTMLElement()) {
-                    HTMLElement* el = toHTMLElement(targetNode(mev));
-                    overPluginElement = el->hasTagName(appletTag) || el->hasTagName(objectTag) || el->hasTagName(embedTag);
-                }
-                if (!overPluginElement) {
-                    if (FrameView* view = m_frame->view())
-                        view->setCursor(selectCursor(mev, scrollbar));
-                }
-            }
+        if (FrameView* view = m_frame->view()) {
+            OptionalCursor optionalCursor = selectCursor(mev, scrollbar);
+            if (optionalCursor.isCursorChange())
+                view->setCursor(optionalCursor.cursor());
         }
     }
     
index cf2fe81..9cc03bf 100644 (file)
@@ -50,7 +50,6 @@ class NSView;
 namespace WebCore {
 
 class Clipboard;
-class Cursor;
 class Event;
 class EventTarget;
 class FloatPoint;
@@ -62,6 +61,7 @@ class HitTestResult;
 class KeyboardEvent;
 class MouseEventWithHitTestResults;
 class Node;
+class OptionalCursor;
 class PlatformKeyboardEvent;
 class PlatformTouchEvent;
 class PlatformWheelEvent;
@@ -238,7 +238,7 @@ private:
 #endif
     bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
 
-    Cursor selectCursor(const MouseEventWithHitTestResults&, Scrollbar*);
+    OptionalCursor selectCursor(const MouseEventWithHitTestResults&, Scrollbar*);
 #if ENABLE(PAN_SCROLLING)
     void updatePanScrollState();
 #endif
index 3406247..e33ddce 100644 (file)
@@ -33,16 +33,6 @@ MouseEventWithHitTestResults::MouseEventWithHitTestResults(const PlatformMouseEv
 {
 }
 
-const LayoutPoint MouseEventWithHitTestResults::localPoint() const
-{
-    return m_hitTestResult.localPoint();
-}
-
-Scrollbar* MouseEventWithHitTestResults::scrollbar() const
-{
-    return m_hitTestResult.scrollbar();
-}
-
 bool MouseEventWithHitTestResults::isOverLink() const
 {
     return m_hitTestResult.URLElement() && m_hitTestResult.URLElement()->isLink();
index c74e84a..1182e90 100644 (file)
@@ -34,8 +34,8 @@ public:
 
     const PlatformMouseEvent& event() const { return m_event; }
     const HitTestResult& hitTestResult() const { return m_hitTestResult; }
-    const LayoutPoint localPoint() const;
-    Scrollbar* scrollbar() const;
+    LayoutPoint localPoint() const { return m_hitTestResult.localPoint(); }
+    Scrollbar* scrollbar() const { return m_hitTestResult.scrollbar(); }
     bool isOverLink() const;
     bool isOverWidget() const { return m_hitTestResult.isOverWidget(); }
 
index 4c2fe50..57d47a7 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "Chrome.h"
 #include "ChromeClient.h"
+#include "Cursor.h"
 #include "CSSValueKeywords.h"
 #include "Font.h"
 #include "FontSelector.h"
@@ -180,7 +181,7 @@ void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint
     context->drawBidiText(font, run, FloatPoint(labelX, labelY));
 }
 
-bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth)
+bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) const
 {
     contentRect = contentBoxRect();
     contentRect.moveBy(accumulatedOffset);
@@ -249,7 +250,7 @@ void RenderEmbeddedObject::viewCleared()
     }
 }
  
-bool RenderEmbeddedObject::isInMissingPluginIndicator(MouseEvent* event)
+bool RenderEmbeddedObject::isInMissingPluginIndicator(const LayoutPoint& point) const
 {
     FloatRect contentRect;
     Path path;
@@ -257,18 +258,25 @@ bool RenderEmbeddedObject::isInMissingPluginIndicator(MouseEvent* event)
     Font font;
     TextRun run("");
     float textWidth;
-    if (!getReplacementTextGeometry(IntPoint(), contentRect, path, replacementTextRect, font, run, textWidth))
-        return false;
-    
-    return path.contains(absoluteToLocal(event->absoluteLocation(), false, true));
+    return getReplacementTextGeometry(IntPoint(), contentRect, path, replacementTextRect, font, run, textWidth)
+        && path.contains(point);
+}
+
+bool RenderEmbeddedObject::isInMissingPluginIndicator(MouseEvent* event) const
+{
+    return isInMissingPluginIndicator(roundedLayoutPoint(absoluteToLocal(event->absoluteLocation(), false, true)));
+}
+
+static bool shouldMissingPluginMessageBeButton(Document* document)
+{
+    Page* page = document->page();
+    return page && page->chrome()->client()->shouldMissingPluginMessageBeButton();
 }
 
 void RenderEmbeddedObject::handleMissingPluginIndicatorEvent(Event* event)
 {
-    if (Page* page = document()->page()) {
-        if (!page->chrome()->client()->shouldMissingPluginMessageBeButton())
-            return;
-    }
+    if (!shouldMissingPluginMessageBeButton(document()))
+        return;
     
     if (!event->isMouseEvent())
         return;
@@ -307,4 +315,13 @@ void RenderEmbeddedObject::handleMissingPluginIndicatorEvent(Event* event)
     }
 }
 
+CursorDirective RenderEmbeddedObject::getCursor(const LayoutPoint& point, Cursor& cursor) const
+{
+    if (m_showsMissingPluginIndicator && shouldMissingPluginMessageBeButton(document()) && isInMissingPluginIndicator(point)) {
+        cursor = handCursor();
+        return SetCursor;
+    }
+    return RenderPart::getCursor(point, cursor);
+}
+
 }
index beda658..685b15b 100644 (file)
@@ -58,6 +58,7 @@ private:
 
     virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
     virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
 
 #if USE(ACCELERATED_COMPOSITING)
     virtual bool requiresLayer() const;
@@ -67,8 +68,9 @@ private:
     virtual void viewCleared();
     
     void setMissingPluginIndicatorIsPressed(bool);
-    bool isInMissingPluginIndicator(MouseEvent*);
-    bool getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth);
+    bool isInMissingPluginIndicator(MouseEvent*) const;
+    bool isInMissingPluginIndicator(const LayoutPoint&) const;
+    bool getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth) const;
 
     String m_replacementText;
     bool m_hasFallbackContent; // FIXME: This belongs on HTMLObjectElement.
index ee0e7bb..00d9c0d 100644 (file)
@@ -24,6 +24,7 @@
 #include "config.h"
 #include "RenderFrameSet.h"
 
+#include "Cursor.h"
 #include "Document.h"
 #include "EventHandler.h"
 #include "EventNames.h"
@@ -799,4 +800,17 @@ bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle*) const
     return child->isFrame() || child->isFrameSet();
 }
 
+CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const
+{
+    if (canResizeRow(point)) {
+        cursor = rowResizeCursor();
+        return SetCursor;
+    }
+    if (canResizeColumn(point)) {
+        cursor = columnResizeCursor();
+        return SetCursor;
+    }
+    return RenderBox::getCursor(point, cursor);
+}
+
 } // namespace WebCore
index b36f036..63ae2a8 100644 (file)
@@ -68,8 +68,8 @@ public:
     bool isResizingRow() const;
     bool isResizingColumn() const;
 
-    bool canResizeRow(const IntPoint&) const;
-    bool canResizeColumn(const IntPoint&) const;
+    bool canResizeRow(const LayoutPoint&) const;
+    bool canResizeColumn(const LayoutPoint&) const;
 
     void notifyFrameEdgeInfoChanged();
 
@@ -99,6 +99,7 @@ private:
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
     virtual void paint(PaintInfo&, const LayoutPoint&);
     virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
 
     inline HTMLFrameSetElement* frameSet() const;
 
index 0c676d4..91f23e0 100644 (file)
@@ -2690,7 +2690,13 @@ VisiblePosition RenderObject::createVisiblePosition(const Position& position)
     return createVisiblePosition(0, DOWNSTREAM);
 }
 
+CursorDirective RenderObject::getCursor(const LayoutPoint&, Cursor&) const
+{
+    return SetCursorBasedOnStyle;
+}
+
 #if ENABLE(SVG)
+
 RenderSVGResourceContainer* RenderObject::toRenderSVGResourceContainer()
 {
     ASSERT_NOT_REACHED();
index 377ea4c..6dd4bac 100644 (file)
@@ -46,6 +46,7 @@ namespace WebCore {
 
 class AffineTransform;
 class AnimationController;
+class Cursor;
 class HitTestResult;
 class InlineBox;
 class InlineFlowBox;
@@ -66,6 +67,12 @@ class RenderSVGResourceContainer;
 
 struct PaintInfo;
 
+enum CursorDirective {
+    SetCursorBasedOnStyle,
+    SetCursor,
+    DoNotSetCursor
+};
+
 enum HitTestFilter {
     HitTestAll,
     HitTestSelf,
@@ -658,8 +665,9 @@ public:
     // This is typically only relevant when repainting.
     virtual RenderStyle* outlineStyleForRepaint() const { return style(); }
     
-    void getTextDecorationColors(int decorations, Color& underline, Color& overline,
-                                 Color& linethrough, bool quirksMode = false);
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
+
+    void getTextDecorationColors(int decorations, Color& underline, Color& overline, Color& linethrough, bool quirksMode = false);
 
     // Return the RenderBox in the container chain which is responsible for painting this object, or 0
     // if painting is root-relative. This is the container that should be passed to the 'forRepaint'
index 7295fe7..fde3f8d 100644 (file)
@@ -385,4 +385,13 @@ bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& res
     return inside;
 }
 
+CursorDirective RenderWidget::getCursor(const LayoutPoint& point, Cursor& cursor) const
+{
+    if (widget() && widget()->isPluginViewBase()) {
+        // A plug-in is responsible for setting the cursor when the pointer is over it.
+        return DoNotSetCursor;
+    }
+    return RenderReplaced::getCursor(point, cursor);
+}
+
 } // namespace WebCore
index 3f2062c..04bd639 100644 (file)
@@ -59,6 +59,7 @@ protected:
     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
     virtual void layout();
     virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
 
 private:
     virtual bool isWidget() const { return true; }