Skip to content

Commit

Permalink
[Unified Text Replacement] [macOS] Add SPI to WKWebViewConfiguration …
Browse files Browse the repository at this point in the history
…to configure unified text replacement behavior

https://bugs.webkit.org/show_bug.cgi?id=273886
rdar://127749267

Reviewed by Wenson Hsieh.

* Source/WebKit/Shared/WebUnifiedTextReplacementContextData.h:
* Source/WebKit/UIProcess/API/APIPageConfiguration.h:
(API::PageConfiguration::unifiedTextReplacementBehavior const):
(API::PageConfiguration::setUnifiedTextReplacementBehavior):
* Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
(convertToPlatformBehavior):
(convertToWebBehavior):
(-[WKWebViewConfiguration _setUnifiedTextReplacementBehavior:]):
(-[WKWebViewConfiguration _unifiedTextReplacementBehavior]):
* Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
* Source/WebKit/UIProcess/mac/WebViewImpl.h:
* Source/WebKit/UIProcess/mac/WebViewImpl.mm:
(WebKit::WebViewImpl::selectionDidChange):
(WebKit::WebViewImpl::wantsCompleteUnifiedTextReplacementBehavior const):
(WebKit::WebViewImpl::unifiedTextReplacementBehavior const):
(WebKit::WebViewImpl::canHandleSwapCharacters const):
(WebKit::WebViewImpl::willBeginTextReplacementSession): Deleted.
(WebKit::WebViewImpl::didBeginTextReplacementSession): Deleted.
(WebKit::WebViewImpl::textReplacementSessionDidReceiveReplacements): Deleted.
(WebKit::WebViewImpl::textReplacementSessionDidUpdateStateForReplacement): Deleted.
(WebKit::WebViewImpl::didEndTextReplacementSession): Deleted.
(WebKit::WebViewImpl::textReplacementSessionDidReceiveTextWithReplacementRange): Deleted.
(WebKit::WebViewImpl::textReplacementSessionDidReceiveEditAction): Deleted.

Canonical link: https://commits.webkit.org/278617@main
  • Loading branch information
rr-codes committed May 10, 2024
1 parent cdde289 commit df94cb9
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 65 deletions.
18 changes: 10 additions & 8 deletions Source/WebKit/Shared/WebUnifiedTextReplacementContextData.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,9 @@

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)

namespace WTF {
class UUID;
}

namespace WebCore {
struct AttributedString;
struct CharacterRange;
}
#import <WebCore/AttributedString.h>
#import <WebCore/CharacterRange.h>
#import <wtf/UUID.h>

namespace WebKit {

Expand All @@ -49,6 +44,13 @@ struct WebUnifiedTextReplacementContextData {
WebCore::CharacterRange range;
};

enum class WebUnifiedTextReplacementBehavior : uint8_t {
None,
Default,
Limited,
Complete,
};

}

#endif
10 changes: 10 additions & 0 deletions Source/WebKit/UIProcess/API/APIPageConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "APIObject.h"
#include "WebPreferencesDefaultValues.h"
#include "WebURLSchemeHandler.h"
#include "WebUnifiedTextReplacementContextData.h"
#include <WebCore/ContentSecurityPolicy.h>
#include <WebCore/FrameIdentifier.h>
#include <WebCore/ShouldRelaxThirdPartyCookieBlocking.h>
Expand Down Expand Up @@ -376,6 +377,11 @@ class PageConfiguration : public ObjectImpl<Object::Type::PageConfiguration> {
bool allowsInlinePredictions() const { return m_data.allowsInlinePredictions; }
void setAllowsInlinePredictions(bool allows) { m_data.allowsInlinePredictions = allows; }

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
WebKit::WebUnifiedTextReplacementBehavior unifiedTextReplacementBehavior() const { return m_data.unifiedTextReplacementBehavior; }
void setUnifiedTextReplacementBehavior(WebKit::WebUnifiedTextReplacementBehavior behavior) { m_data.unifiedTextReplacementBehavior = behavior; }
#endif

void setShouldRelaxThirdPartyCookieBlocking(WebCore::ShouldRelaxThirdPartyCookieBlocking value) { m_data.shouldRelaxThirdPartyCookieBlocking = value; }
WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking() const { return m_data.shouldRelaxThirdPartyCookieBlocking; }

Expand Down Expand Up @@ -572,6 +578,10 @@ class PageConfiguration : public ObjectImpl<Object::Type::PageConfiguration> {
bool scrollToTextFragmentIndicatorEnabled { true };
bool scrollToTextFragmentMarkingEnabled { true };

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
WebKit::WebUnifiedTextReplacementBehavior unifiedTextReplacementBehavior { WebKit::WebUnifiedTextReplacementBehavior::Default };
#endif

WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No };
WTF::String attributedBundleIdentifier;

Expand Down
54 changes: 54 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,60 @@ - (BOOL)allowsInlinePredictions
return _pageConfiguration->allowsInlinePredictions();
}

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)

static _WKUnifiedTextReplacementBehavior convertToPlatformBehavior(WebKit::WebUnifiedTextReplacementBehavior behavior)
{
switch (behavior) {
case WebKit::WebUnifiedTextReplacementBehavior::None:
return _WKUnifiedTextReplacementBehaviorNone;

case WebKit::WebUnifiedTextReplacementBehavior::Default:
return _WKUnifiedTextReplacementBehaviorDefault;

case WebKit::WebUnifiedTextReplacementBehavior::Limited:
return _WKUnifiedTextReplacementBehaviorLimited;

case WebKit::WebUnifiedTextReplacementBehavior::Complete:
return _WKUnifiedTextReplacementBehaviorComplete;
}
}

static WebKit::WebUnifiedTextReplacementBehavior convertToWebBehavior(_WKUnifiedTextReplacementBehavior behavior)
{
switch (behavior) {
case _WKUnifiedTextReplacementBehaviorNone:
return WebKit::WebUnifiedTextReplacementBehavior::None;

case _WKUnifiedTextReplacementBehaviorDefault:
return WebKit::WebUnifiedTextReplacementBehavior::Default;

case _WKUnifiedTextReplacementBehaviorLimited:
return WebKit::WebUnifiedTextReplacementBehavior::Limited;

case _WKUnifiedTextReplacementBehaviorComplete:
return WebKit::WebUnifiedTextReplacementBehavior::Complete;
}
}

#endif

- (void)_setUnifiedTextReplacementBehavior:(_WKUnifiedTextReplacementBehavior)behavior
{
#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
_pageConfiguration->setUnifiedTextReplacementBehavior(convertToWebBehavior(behavior));
#endif
}

- (_WKUnifiedTextReplacementBehavior)_unifiedTextReplacementBehavior
{
#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
return convertToPlatformBehavior(_pageConfiguration->unifiedTextReplacementBehavior());
#else
return _WKUnifiedTextReplacementBehaviorNone;
#endif
}

#if PLATFORM(IOS_FAMILY)
- (void)setAllowsInlineMediaPlayback:(BOOL)allows
{
Expand Down
10 changes: 10 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ typedef NS_ENUM(NSUInteger, _WKContentSecurityPolicyModeForExtension) {
_WKContentSecurityPolicyModeForExtensionManifestV3
} WK_API_AVAILABLE(macos(13.0), ios(16.0));

typedef NS_ENUM(NSUInteger, _WKUnifiedTextReplacementBehavior) {
_WKUnifiedTextReplacementBehaviorNone = 0,
_WKUnifiedTextReplacementBehaviorDefault,
_WKUnifiedTextReplacementBehaviorLimited,
_WKUnifiedTextReplacementBehaviorComplete
} WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));

@class WKWebView;
@class _WKApplicationManifest;
@class _WKVisitedLinkStore;
Expand Down Expand Up @@ -172,6 +179,9 @@ typedef NS_ENUM(NSUInteger, _WKContentSecurityPolicyModeForExtension) {
@property (nonatomic, setter=_setScrollToTextFragmentIndicatorEnabled:) BOOL _scrollToTextFragmentIndicatorEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA), visionos(WK_XROS_TBA));

@property (nonatomic, setter=_setScrollToTextFragmentMarkingEnabled:) BOOL _scrollToTextFragmentMarkingEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA), visionos(WK_XROS_TBA));

@property (nonatomic, setter=_setUnifiedTextReplacementBehavior:) _WKUnifiedTextReplacementBehavior _unifiedTextReplacementBehavior WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));

@end

#if TARGET_OS_IPHONE
Expand Down
24 changes: 9 additions & 15 deletions Source/WebKit/UIProcess/mac/WebViewImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ struct WebHitTestResultData;
enum class ContinueUnsafeLoad : bool;
enum class UndoOrRedo : bool;

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
enum class WebUnifiedTextReplacementBehavior : uint8_t;
#endif

typedef id <NSValidatedUserInterfaceItem> ValidationItem;
typedef Vector<RetainPtr<ValidationItem>> ValidationVector;
typedef HashMap<String, ValidationVector> ValidationMap;
Expand Down Expand Up @@ -695,6 +699,10 @@ class WebViewImpl final : public CanMakeWeakPtr<WebViewImpl>, public CanMakeChec
void handleContextMenuTranslation(const WebCore::TranslationContextMenuInfo&);
#endif

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
WebUnifiedTextReplacementBehavior unifiedTextReplacementBehavior() const;
#endif

#if ENABLE(UNIFIED_TEXT_REPLACEMENT) && ENABLE(CONTEXT_MENUS)
bool canHandleSwapCharacters() const;
void handleContextMenuSwapCharacters(WebCore::IntRect selectionBoundsInRootView);
Expand Down Expand Up @@ -722,22 +730,8 @@ class WebViewImpl final : public CanMakeWeakPtr<WebViewImpl>, public CanMakeChec
#endif

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
void willBeginTextReplacementSession(const WTF::UUID&, WebUnifiedTextReplacementType, CompletionHandler<void(const Vector<WebUnifiedTextReplacementContextData>&)>&&);

void didBeginTextReplacementSession(const WTF::UUID&, const Vector<WebUnifiedTextReplacementContextData>&);
bool wantsCompleteUnifiedTextReplacementBehavior() const;

void textReplacementSessionDidReceiveReplacements(const WTF::UUID&, const Vector<WebTextReplacementData>&, const WebUnifiedTextReplacementContextData&, bool finished);

void textReplacementSessionDidUpdateStateForReplacement(const WTF::UUID&, WebTextReplacementDataState, const WebTextReplacementData&, const WebUnifiedTextReplacementContextData&);

void didEndTextReplacementSession(const WTF::UUID&, bool accepted);

void textReplacementSessionDidReceiveTextWithReplacementRange(const WTF::UUID&, const WebCore::AttributedString&, const WebCore::CharacterRange&, const WebUnifiedTextReplacementContextData&);

void textReplacementSessionDidReceiveEditAction(const WTF::UUID&, WebTextReplacementDataEditAction);
#endif

#if ENABLE(UNIFIED_TEXT_REPLACEMENT_UI)
void addTextIndicatorStyleForID(WTF::UUID, WKTextIndicatorStyleType);
void removeTextIndicatorStyleForID(WTF::UUID);
#endif
Expand Down
57 changes: 15 additions & 42 deletions Source/WebKit/UIProcess/mac/WebViewImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2789,8 +2789,7 @@ static String commandNameForSelector(SEL selector)
#endif

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
// FIXME: (rdar://123767495) Remove the `isEditable() && m_page->editorState().selectionIsRange` restriction when possible.
if (m_page->editorState().hasPostLayoutData() && isEditable() && m_page->editorState().selectionIsRange) {
if (m_page->editorState().hasPostLayoutData() && wantsCompleteUnifiedTextReplacementBehavior() && m_page->editorState().selectionIsRange) {
auto selectionRect = m_page->editorState().postLayoutData->selectionBoundingRect;
scheduleShowSwapCharactersViewForSelectionRectOfView(selectionRect, m_view.getAutoreleased());
}
Expand Down Expand Up @@ -4557,7 +4556,12 @@ static NSPasteboardName pasteboardNameForAccessCategory(WebCore::DOMPasteAccessC
completionHandler();
}

#if ENABLE(UNIFIED_TEXT_REPLACEMENT_UI)
#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
bool WebViewImpl::wantsCompleteUnifiedTextReplacementBehavior() const
{
return isEditable() || unifiedTextReplacementBehavior() == WebUnifiedTextReplacementBehavior::Complete;
}

void WebViewImpl::addTextIndicatorStyleForID(WTF::UUID uuid, WKTextIndicatorStyleType styleType)
{
if (!m_page->preferences().textIndicatorStylingEnabled())
Expand Down Expand Up @@ -6371,11 +6375,18 @@ static NSTextAlignment nsTextAlignmentFromTextAlignment(TextAlignment textAlignm

#endif // HAVE(TRANSLATION_UI_SERVICES) && ENABLE(CONTEXT_MENUS)

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
WebUnifiedTextReplacementBehavior WebViewImpl::unifiedTextReplacementBehavior() const
{
return m_page->configuration().unifiedTextReplacementBehavior();
}
#endif

#if ENABLE(UNIFIED_TEXT_REPLACEMENT) && ENABLE(CONTEXT_MENUS)

bool WebViewImpl::canHandleSwapCharacters() const
{
return webViewCanHandleSwapCharacters();
return webViewCanHandleSwapCharacters() && unifiedTextReplacementBehavior() != WebUnifiedTextReplacementBehavior::None;
}

void WebViewImpl::handleContextMenuSwapCharacters(IntRect selectionBoundsInRootView)
Expand Down Expand Up @@ -6598,44 +6609,6 @@ static NSTextAlignment nsTextAlignmentFromTextAlignment(TextAlignment textAlignm

#endif // ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS)

#if ENABLE(UNIFIED_TEXT_REPLACEMENT)
void WebViewImpl::willBeginTextReplacementSession(const WTF::UUID& uuid, WebUnifiedTextReplacementType type, CompletionHandler<void(const Vector<WebUnifiedTextReplacementContextData>&)>&& completionHandler)
{
protectedPage()->willBeginTextReplacementSession(uuid, type, WTFMove(completionHandler));
}

void WebViewImpl::didBeginTextReplacementSession(const WTF::UUID& uuid, const Vector<WebUnifiedTextReplacementContextData>& contexts)
{
protectedPage()->didBeginTextReplacementSession(uuid, contexts);
}

void WebViewImpl::textReplacementSessionDidReceiveReplacements(const WTF::UUID& uuid, const Vector<WebTextReplacementData>& replacements, const WebUnifiedTextReplacementContextData& context, bool finished)
{
protectedPage()->textReplacementSessionDidReceiveReplacements(uuid, replacements, context, finished);
}

void WebViewImpl::textReplacementSessionDidUpdateStateForReplacement(const WTF::UUID& uuid, WebTextReplacementData::State state, const WebTextReplacementData& replacement, const WebUnifiedTextReplacementContextData& context)
{
protectedPage()->textReplacementSessionDidUpdateStateForReplacement(uuid, state, replacement, context);
}

void WebViewImpl::didEndTextReplacementSession(const WTF::UUID& uuid, bool accepted)
{
protectedPage()->didEndTextReplacementSession(uuid, accepted);
}

void WebViewImpl::textReplacementSessionDidReceiveTextWithReplacementRange(const WTF::UUID& uuid, const WebCore::AttributedString& attributedText, const WebCore::CharacterRange& range, const WebUnifiedTextReplacementContextData& context)
{
protectedPage()->textReplacementSessionDidReceiveTextWithReplacementRange(uuid, attributedText, range, context);
}

void WebViewImpl::textReplacementSessionDidReceiveEditAction(const WTF::UUID& uuid, WebKit::WebTextReplacementData::EditAction action)
{
protectedPage()->textReplacementSessionDidReceiveEditAction(uuid, action);
}

#endif

Ref<WebPageProxy> WebViewImpl::protectedPage() const
{
return m_page.get();
Expand Down

0 comments on commit df94cb9

Please sign in to comment.