Changeset 260759 in webkit


Ignore:
Timestamp:
Apr 27, 2020 9:08:21 AM (4 years ago)
Author:
dbates@webkit.org
Message:

Caret may be placed in the wrong spot for text input context that is a form control
https://bugs.webkit.org/show_bug.cgi?id=210939
<rdar://problem/61943089>

Reviewed by Darin Adler.

Source/WebCore:

Add a helper function that returns the closest editable position inside an element
for a given point (if any).

  • editing/Editing.cpp:

(WebCore::closestEditablePositionInElementForAbsolutePoint): Added.

  • editing/Editing.h:

Source/WebKit:

Find the closest editable position in the element for the point using the
newly introduced closestEditablePositionInElementForAbsolutePoint().

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::focusTextInputContextAndPlaceCaret):

Tools:

Add a test.

  • TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r260755 r260759  
     12020-04-27  Daniel Bates  <dabates@apple.com>
     2
     3        Caret may be placed in the wrong spot for text input context that is a form control
     4        https://bugs.webkit.org/show_bug.cgi?id=210939
     5        <rdar://problem/61943089>
     6
     7        Reviewed by Darin Adler.
     8
     9        Add a helper function that returns the closest editable position inside an element
     10        for a given point (if any).
     11
     12        * editing/Editing.cpp:
     13        (WebCore::closestEditablePositionInElementForAbsolutePoint): Added.
     14        * editing/Editing.h:
     15
    1162020-04-27  Alicia Boya García  <aboya@igalia.com>
    217
  • trunk/Source/WebCore/editing/Editing.cpp

    r260753 r260759  
    5151#include "RenderElement.h"
    5252#include "RenderTableCell.h"
     53#include "RenderTextControlSingleLine.h"
    5354#include "ShadowRoot.h"
    5455#include "Text.h"
     56#include "TextControlInnerElements.h"
    5557#include "TextIterator.h"
    5658#include "VisibleUnits.h"
     
    560562    ASSERT(!node.parentNode()->isShadowRoot());
    561563    return positionInParentAfterNode(&node);
     564}
     565
     566VisiblePosition closestEditablePositionInElementForAbsolutePoint(const Element& element, const IntPoint& point)
     567{
     568    if (!element.isConnected() || !element.document().frame())
     569        return { };
     570
     571    Ref<const Element> protectedElement { element };
     572    auto frame = makeRef(*element.document().frame());
     573
     574    element.document().updateLayoutIgnorePendingStylesheets();
     575
     576    RenderObject* renderer = element.renderer();
     577    // Look at the inner element of a form control, not the control itself, as it is the editable part.
     578    if (is<HTMLTextFormControlElement>(element)) {
     579        auto& formControlElement = downcast<HTMLTextFormControlElement>(element);
     580        if (!formControlElement.isInnerTextElementEditable())
     581            return { };
     582        if (auto innerTextElement = formControlElement.innerTextElement())
     583            renderer = innerTextElement->renderer();
     584    }
     585    if (!renderer)
     586        return { };
     587    auto absoluteBoundingBox = renderer->absoluteBoundingBoxRect();
     588    auto constrainedPoint = point.constrainedBetween(absoluteBoundingBox.minXMinYCorner(), absoluteBoundingBox.maxXMaxYCorner());
     589    auto visiblePosition = frame->visiblePositionForPoint(constrainedPoint);
     590    return isEditablePosition(visiblePosition.deepEquivalent()) ? visiblePosition : VisiblePosition { };
    562591}
    563592
  • trunk/Source/WebCore/editing/Editing.h

    r260753 r260759  
    157157VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node&, int index); // FIXME: Why do we need this version?
    158158
     159WEBCORE_EXPORT VisiblePosition closestEditablePositionInElementForAbsolutePoint(const Element&, const IntPoint&);
     160
    159161// -------------------------------------------------------------------------
    160162// HTMLElement
  • trunk/Source/WebKit/ChangeLog

    r260757 r260759  
     12020-04-27  Daniel Bates  <dabates@apple.com>
     2
     3        Caret may be placed in the wrong spot for text input context that is a form control
     4        https://bugs.webkit.org/show_bug.cgi?id=210939
     5        <rdar://problem/61943089>
     6
     7        Reviewed by Darin Adler.
     8
     9        Find the closest editable position in the element for the point using the
     10        newly introduced closestEditablePositionInElementForAbsolutePoint().
     11
     12        * WebProcess/WebPage/ios/WebPageIOS.mm:
     13        (WebKit::WebPage::focusTextInputContextAndPlaceCaret):
     14
    1152020-04-27  Darin Adler  <darin@apple.com>
    216
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r260739 r260759  
    100100#import <WebCore/HTMLSummaryElement.h>
    101101#import <WebCore/HTMLTextAreaElement.h>
    102 #import <WebCore/HTMLTextFormControlElement.h>
    103102#import <WebCore/HistoryItem.h>
    104103#import <WebCore/HitTestResult.h>
     
    43514350    }
    43524351
     4352    // FIXME: Do not focus an element if it moved or the caret point is outside its bounds
     4353    // because we only want to do so if the caret can be placed.
    43534354    UserGestureIndicator gestureIndicator { ProcessingUserGesture, &target->document() };
    43544355    SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
     
    43604361        return;
    43614362    }
    4362     // The function visiblePositionInFocusedNodeForPoint constrains the point to be inside
    4363     // the bounds of the target element.
    4364     auto position = visiblePositionInFocusedNodeForPoint(targetFrame, point, true /* isInteractingWithFocusedElement */);
     4363
     4364    ASSERT(targetFrame->view());
     4365    auto position = closestEditablePositionInElementForAbsolutePoint(*target, targetFrame->view()->rootViewToContents(point));
     4366    if (position.isNull()) {
     4367        completionHandler(false);
     4368        return;
     4369    }
    43654370    targetFrame->selection().setSelectedRange(Range::create(*targetFrame->document(), position, position).ptr(), position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
    43664371    completionHandler(true);
  • trunk/Tools/ChangeLog

    r260758 r260759  
     12020-04-27  Daniel Bates  <dabates@apple.com>
     2
     3        Caret may be placed in the wrong spot for text input context that is a form control
     4        https://bugs.webkit.org/show_bug.cgi?id=210939
     5        <rdar://problem/61943089>
     6
     7        Reviewed by Darin Adler.
     8
     9        Add a test.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
     12        (TestWebKitAPI::TEST):
     13
    1142020-04-27  Alexey Proskuryakov  <ap@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm

    r260756 r260759  
    465465}
    466466
     467TEST(RequestTextInputContext, FocusFieldWithPaddingAndPlaceCaretAtEnd)
     468{
     469    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     470    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     471
     472    constexpr char exampleText[] = "hello world";
     473    constexpr size_t exampleTextLength = sizeof(exampleText) - 1;
     474    [webView synchronouslyLoadHTMLString:applyStyle([NSString stringWithFormat:@"<input type='text' value='%s' style='width: 100px; height: 50px; padding: 20px'>", exampleText])];
     475    NSArray<_WKTextInputContext *> *contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
     476    EXPECT_EQ(1UL, contexts.count);
     477    RetainPtr<_WKTextInputContext> inputElement = contexts[0];
     478
     479    CGRect boundingRect = [inputElement boundingRect];
     480    CGPoint endPosition = CGPointMake(boundingRect.origin.x + boundingRect.size.width, boundingRect.origin.y);
     481    EXPECT_EQ((UIResponder<UITextInput> *)[webView textInputContentView], [webView synchronouslyFocusTextInputContext:inputElement.get() placeCaretAt:endPosition]);
     482    EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]);
     483    EXPECT_EQ(static_cast<int>(exampleTextLength), [[webView objectByEvaluatingJavaScript:@"document.activeElement.selectionStart"] intValue]);
     484    EXPECT_EQ(static_cast<int>(exampleTextLength), [[webView objectByEvaluatingJavaScript:@"document.activeElement.selectionEnd"] intValue]);
     485}
     486
    467487TEST(RequestTextInputContext, FocusFieldAndPlaceCaretOutsideField)
    468488{
Note: See TracChangeset for help on using the changeset viewer.