Web Automation: elements larger than the viewport have incorrect in-view center point
[WebKit-https.git] / Source / WebCore / platform / DragImage.cpp
index 3af6b30..112b789 100644 (file)
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 #include "FrameSnapshotting.h"
 #include "FrameView.h"
 #include "ImageBuffer.h"
+#include "NotImplemented.h"
 #include "Range.h"
+#include "RenderElement.h"
 #include "RenderObject.h"
 #include "RenderView.h"
+#include "TextIndicator.h"
 
 namespace WebCore {
 
+#if PLATFORM(COCOA)
+const float ColorSwatchCornerRadius = 4;
+const float ColorSwatchStrokeSize = 4;
+const float ColorSwatchWidth = 24;
+#endif
+
 DragImageRef fitDragImageToMaxSize(DragImageRef image, const IntSize& layoutSize, const IntSize& maxSize)
 {
     float heightResizeRatio = 0.0f;
@@ -97,16 +106,17 @@ static DragImageRef createDragImageFromSnapshot(std::unique_ptr<ImageBuffer> sna
 #if ENABLE(CSS_IMAGE_ORIENTATION)
     if (node) {
         RenderObject* renderer = node->renderer();
-        if (!renderer)
+        if (!renderer || !is<RenderElement>(renderer))
             return nullptr;
 
-        orientation.setRespectImageOrientation(renderer->shouldRespectImageOrientation());
-        orientation.setImageOrientationEnum(renderer->style().imageOrientation());
+        auto& renderElement = downcast<RenderElement>(*renderer);
+        orientation.setRespectImageOrientation(renderElement.shouldRespectImageOrientation());
+        orientation.setImageOrientationEnum(renderElement.style().imageOrientation());
     }
 #else
     UNUSED_PARAM(node);
 #endif
-    RefPtr<Image> image = snapshot->copyImage(ImageBuffer::fastCopyImageMode(), Unscaled);
+    RefPtr<Image> image = ImageBuffer::sinkIntoImage(WTFMove(snapshot), PreserveResolution::Yes);
     if (!image)
         return nullptr;
     return createDragImageFromImage(image.get(), orientation);
@@ -118,33 +128,38 @@ DragImageRef createDragImageForNode(Frame& frame, Node& node)
     return createDragImageFromSnapshot(snapshotNode(frame, node), &node);
 }
 
-DragImageRef createDragImageForSelection(Frame& frame, bool forceBlackText)
+#if !ENABLE(DATA_INTERACTION)
+
+DragImageRef createDragImageForSelection(Frame& frame, TextIndicatorData&, bool forceBlackText)
 {
     SnapshotOptions options = forceBlackText ? SnapshotOptionsForceBlackText : SnapshotOptionsNone;
     return createDragImageFromSnapshot(snapshotSelection(frame, options), nullptr);
 }
 
+#endif
+
 struct ScopedFrameSelectionState {
     ScopedFrameSelectionState(Frame& frame)
         : frame(frame)
     {
-        if (RenderView* root = frame.contentRenderer())
-            root->getSelection(startRenderer, startOffset, endRenderer, endOffset);
+        if (auto* renderView = frame.contentRenderer())
+            selection = renderView->selection().get();
     }
 
     ~ScopedFrameSelectionState()
     {
-        if (RenderView* root = frame.contentRenderer())
-            root->setSelection(startRenderer, startOffset, endRenderer, endOffset, RenderView::RepaintNothing);
+        if (auto* renderView = frame.contentRenderer()) {
+            ASSERT(selection);
+            renderView->selection().set(selection.value(), SelectionRangeData::RepaintMode::Nothing);
+        }
     }
 
     const Frame& frame;
-    RenderObject* startRenderer;
-    RenderObject* endRenderer;
-    int startOffset;
-    int endOffset;
+    Optional<SelectionRangeData::Context> selection;
 };
 
+#if !PLATFORM(IOS_FAMILY)
+
 DragImageRef createDragImageForRange(Frame& frame, Range& range, bool forceBlackText)
 {
     frame.document()->updateLayout();
@@ -174,12 +189,17 @@ DragImageRef createDragImageForRange(Frame& frame, Range& range, bool forceBlack
         return nullptr;
 
     SnapshotOptions options = SnapshotOptionsPaintSelectionOnly | (forceBlackText ? SnapshotOptionsForceBlackText : SnapshotOptionsNone);
-    view->setSelection(startRenderer, start.deprecatedEditingOffset(), endRenderer, end.deprecatedEditingOffset(), RenderView::RepaintNothing);
+    int startOffset = start.deprecatedEditingOffset();
+    int endOffset = end.deprecatedEditingOffset();
+    ASSERT(startOffset >= 0 && endOffset >= 0);
+    view->selection().set({ startRenderer, endRenderer, static_cast<unsigned>(startOffset), static_cast<unsigned>(endOffset) }, SelectionRangeData::RepaintMode::Nothing);
     // We capture using snapshotFrameRect() because we fake up the selection using
     // FrameView but snapshotSelection() uses the selection from the Frame itself.
-    return createDragImageFromSnapshot(snapshotFrameRect(frame, view->selectionBounds(), options), nullptr);
+    return createDragImageFromSnapshot(snapshotFrameRect(frame, view->selection().boundsClippedToVisibleContent(), options), nullptr);
 }
 
+#endif
+
 DragImageRef createDragImageForImage(Frame& frame, Node& node, IntRect& imageRect, IntRect& elementRect)
 {
     ScopedNodeDragEnabler enableDrag(frame, node);
@@ -190,22 +210,119 @@ DragImageRef createDragImageForImage(Frame& frame, Node& node, IntRect& imageRec
 
     // Calculate image and element metrics for the client, then create drag image.
     LayoutRect topLevelRect;
-    IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect));
+    IntRect paintingRect = snappedIntRect(renderer->paintingRootRect(topLevelRect));
 
     if (paintingRect.isEmpty())
         return nullptr;
 
-    elementRect = pixelSnappedIntRect(topLevelRect);
+    elementRect = snappedIntRect(topLevelRect);
     imageRect = paintingRect;
 
     return createDragImageFromSnapshot(snapshotNode(frame, node), &node);
 }
 
-#if !PLATFORM(MAC) && (!PLATFORM(WIN) || OS(WINCE))
-DragImageRef createDragImageForLink(URL&, const String&, FontRenderingMode)
+#if !ENABLE(DATA_INTERACTION)
+DragImageRef platformAdjustDragImageForDeviceScaleFactor(DragImageRef image, float deviceScaleFactor)
+{
+    // Later code expects the drag image to be scaled by device's scale factor.
+    return scaleDragImage(image, { deviceScaleFactor, deviceScaleFactor });
+}
+#endif
+
+#if !PLATFORM(MAC)
+const int linkDragBorderInset = 2;
+
+IntPoint dragOffsetForLinkDragImage(DragImageRef dragImage)
+{
+    IntSize size = dragImageSize(dragImage);
+    return { -size.width() / 2, -linkDragBorderInset };
+}
+
+FloatPoint anchorPointForLinkDragImage(DragImageRef dragImage)
 {
+    IntSize size = dragImageSize(dragImage);
+    return { 0.5, static_cast<float>((size.height() - linkDragBorderInset) / size.height()) };
+}
+#endif
+
+DragImage::DragImage()
+    : m_dragImageRef { nullptr }
+{
+}
+
+DragImage::DragImage(DragImageRef dragImageRef)
+    : m_dragImageRef { dragImageRef }
+{
+}
+
+DragImage::DragImage(DragImage&& other)
+    : m_dragImageRef { std::exchange(other.m_dragImageRef, nullptr) }
+{
+    m_indicatorData = other.m_indicatorData;
+    m_visiblePath = other.m_visiblePath;
+}
+
+DragImage& DragImage::operator=(DragImage&& other)
+{
+    if (m_dragImageRef)
+        deleteDragImage(m_dragImageRef);
+
+    m_dragImageRef = std::exchange(other.m_dragImageRef, nullptr);
+    m_indicatorData = other.m_indicatorData;
+    m_visiblePath = other.m_visiblePath;
+
+    return *this;
+}
+
+DragImage::~DragImage()
+{
+    if (m_dragImageRef)
+        deleteDragImage(m_dragImageRef);
+}
+
+#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WIN)
+
+IntSize dragImageSize(DragImageRef)
+{
+    notImplemented();
+    return { 0, 0 };
+}
+
+void deleteDragImage(DragImageRef)
+{
+    notImplemented();
+}
+
+DragImageRef scaleDragImage(DragImageRef, FloatSize)
+{
+    notImplemented();
+    return nullptr;
+}
+
+DragImageRef dissolveDragImageToFraction(DragImageRef, float)
+{
+    notImplemented();
+    return nullptr;
+}
+
+DragImageRef createDragImageFromImage(Image*, ImageOrientationDescription)
+{
+    notImplemented();
     return nullptr;
 }
+
+DragImageRef createDragImageIconForCachedImageFilename(const String&)
+{
+    notImplemented();
+    return nullptr;
+}
+
+DragImageRef createDragImageForLink(Element&, URL&, const String&, TextIndicatorData&, FontRenderingMode, float)
+{
+    notImplemented();
+    return nullptr;
+}
+
 #endif
 
 } // namespace WebCore