[WPE][GTK] Expose availability of certain editing commands in WebKitEditorState
authormcatanzaro@igalia.com <mcatanzaro@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Oct 2017 14:20:47 +0000 (14:20 +0000)
committermcatanzaro@igalia.com <mcatanzaro@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Oct 2017 14:20:47 +0000 (14:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=168219

Reviewed by Ryosuke Niwa.

Source/WebCore:

Make Editor::canUndo and Editor::canRedo const.

Also, remove unused allowsCopy from HitTestResult.

* editing/Editor.cpp:
(WebCore::Editor::canUndo const):
(WebCore::Editor::canRedo const):
(WebCore::Editor::canUndo): Deleted.
(WebCore::Editor::canRedo): Deleted.
* editing/Editor.h:
* rendering/HitTestResult.cpp:
(WebCore::HitTestResult::allowsCopy const): Deleted.
* rendering/HitTestResult.h:
* rendering/SelectionRangeData.cpp:

Source/WebKit:

Expose canCut, canCopy, canPaste, canUndo, and canRedo in EditorState::PostLayouData.

Add corresponding new WPE/GTK API.

Remove allowsCopy from WebKitTestResultData. It's unused, does not work correctly in all
circumstances, and irritates Ryosuke.

Also, remove a bunch of #ifs guarding post layout data, since it's now used on all ports.

* Shared/EditorState.cpp:
(WebKit::EditorState::encode const):
(WebKit::EditorState::decode):
(WebKit::EditorState::PostLayoutData::encode const):
(WebKit::EditorState::PostLayoutData::decode):
* Shared/EditorState.h:
(WebKit::EditorState::postLayoutData const const):
* Shared/WebHitTestResultData.cpp:
(WebKit::WebHitTestResultData::WebHitTestResultData):
(WebKit::WebHitTestResultData::encode const):
(WebKit::WebHitTestResultData::decode):
* Shared/WebHitTestResultData.h:
* UIProcess/API/APIHitTestResult.h:
(API::HitTestResult::allowsCopy const): Deleted.
* UIProcess/API/glib/WebKitEditorState.cpp:
(webkitEditorStateChanged):
(webkit_editor_state_is_cut_available):
(webkit_editor_state_is_copy_available):
(webkit_editor_state_is_paste_available):
(webkit_editor_state_is_undo_available):
(webkit_editor_state_is_redo_available):
* UIProcess/API/glib/WebKitWebView.cpp:
(webkit_web_view_can_execute_editing_command):
* UIProcess/API/gtk/WebKitEditorState.h:
* UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
* UIProcess/API/wpe/WebKitEditorState.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState const):
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::performImmediateActionHitTestAtLocation):

Tools:

Test it.

* TestWebKitAPI/Tests/WebKitGtk/TestWebViewEditor.cpp:
(testWebViewEditorCutCopyPasteNonEditable):
(testWebViewEditorCutCopyPasteEditable):
(testWebViewEditorSelectAllNonEditable):
(testWebViewEditorSelectAllEditable):
(loadContentsAndTryToCutSelection):
(testWebViewEditorNonEditable):
(testWebViewEditorEditorStateTypingAttributes):
(testWebViewEditorInsertImage):
(testWebViewEditorCreateLink):

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

20 files changed:
Source/WebCore/ChangeLog
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/Editor.h
Source/WebCore/rendering/HitTestResult.cpp
Source/WebCore/rendering/HitTestResult.h
Source/WebKit/ChangeLog
Source/WebKit/Shared/EditorState.cpp
Source/WebKit/Shared/EditorState.h
Source/WebKit/Shared/WebHitTestResultData.cpp
Source/WebKit/Shared/WebHitTestResultData.h
Source/WebKit/UIProcess/API/APIHitTestResult.h
Source/WebKit/UIProcess/API/glib/WebKitEditorState.cpp
Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
Source/WebKit/UIProcess/API/gtk/WebKitEditorState.h
Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt
Source/WebKit/UIProcess/API/wpe/WebKitEditorState.h
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitGtk/TestWebViewEditor.cpp

index 2a4686d..7be6290 100644 (file)
@@ -1,3 +1,25 @@
+2017-10-30  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        [WPE][GTK] Expose availability of certain editing commands in WebKitEditorState
+        https://bugs.webkit.org/show_bug.cgi?id=168219
+
+        Reviewed by Ryosuke Niwa.
+
+        Make Editor::canUndo and Editor::canRedo const.
+
+        Also, remove unused allowsCopy from HitTestResult.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::canUndo const):
+        (WebCore::Editor::canRedo const):
+        (WebCore::Editor::canUndo): Deleted.
+        (WebCore::Editor::canRedo): Deleted.
+        * editing/Editor.h:
+        * rendering/HitTestResult.cpp:
+        (WebCore::HitTestResult::allowsCopy const): Deleted.
+        * rendering/HitTestResult.h:
+        * rendering/SelectionRangeData.cpp:
+
 2017-10-27  Antti Koivisto  <antti@apple.com>
 
         Destroy all unneeded anonymous wrappers in RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers()
index be3da8e..e463dfc 100644 (file)
@@ -1639,7 +1639,7 @@ void Editor::clearUndoRedoOperations()
         client()->clearUndoRedoOperations();
 }
 
-bool Editor::canUndo()
+bool Editor::canUndo() const
 {
     return client() && client()->canUndo();
 }
@@ -1650,7 +1650,7 @@ void Editor::undo()
         client()->undo();
 }
 
-bool Editor::canRedo()
+bool Editor::canRedo() const
 {
     return client() && client()->canRedo();
 }
index aa885ff..b1e82fe 100644 (file)
@@ -303,9 +303,9 @@ public:
     bool shouldEndEditing(Range*);
 
     void clearUndoRedoOperations();
-    bool canUndo();
+    WEBCORE_EXPORT bool canUndo() const;
     void undo();
-    bool canRedo();
+    WEBCORE_EXPORT bool canRedo() const;
     void redo();
 
     void didBeginEditing();
index 52e4091..acb9edc 100644 (file)
@@ -594,21 +594,6 @@ bool HitTestResult::isOverTextInsideFormControlElement() const
     return !wordRange->text().isEmpty();
 }
 
-bool HitTestResult::allowsCopy() const
-{
-    Node* node = innerNode();
-    if (!node)
-        return false;
-
-    RenderObject* renderer = node->renderer();
-    if (!renderer)
-        return false;
-
-    bool isUserSelectNone = renderer->style().userSelect() == SELECT_NONE;
-    bool isPasswordField = is<HTMLInputElement>(node) && downcast<HTMLInputElement>(*node).isPasswordField();
-    return !isPasswordField && !isUserSelectNone;
-}
-
 URL HitTestResult::absoluteLinkURL() const
 {
     if (m_innerURLElement)
index ba2d7a2..04b3882 100644 (file)
@@ -131,7 +131,6 @@ public:
 
     WEBCORE_EXPORT bool isDownloadableMedia() const;
     WEBCORE_EXPORT bool isOverTextInsideFormControlElement() const;
-    WEBCORE_EXPORT bool allowsCopy() const;
 
     HitTestProgress addNodeToListBasedTestResult(Node*, const HitTestRequest&, const HitTestLocation& pointInContainer, const LayoutRect& = LayoutRect());
     HitTestProgress addNodeToListBasedTestResult(Node*, const HitTestRequest&, const HitTestLocation& pointInContainer, const FloatRect&);
index b41fd45..fa67166 100644 (file)
@@ -1,3 +1,50 @@
+2017-10-30  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        [WPE][GTK] Expose availability of certain editing commands in WebKitEditorState
+        https://bugs.webkit.org/show_bug.cgi?id=168219
+
+        Reviewed by Ryosuke Niwa.
+
+        Expose canCut, canCopy, canPaste, canUndo, and canRedo in EditorState::PostLayouData.
+
+        Add corresponding new WPE/GTK API.
+
+        Remove allowsCopy from WebKitTestResultData. It's unused, does not work correctly in all
+        circumstances, and irritates Ryosuke.
+
+        Also, remove a bunch of #ifs guarding post layout data, since it's now used on all ports.
+
+        * Shared/EditorState.cpp:
+        (WebKit::EditorState::encode const):
+        (WebKit::EditorState::decode):
+        (WebKit::EditorState::PostLayoutData::encode const):
+        (WebKit::EditorState::PostLayoutData::decode):
+        * Shared/EditorState.h:
+        (WebKit::EditorState::postLayoutData const const):
+        * Shared/WebHitTestResultData.cpp:
+        (WebKit::WebHitTestResultData::WebHitTestResultData):
+        (WebKit::WebHitTestResultData::encode const):
+        (WebKit::WebHitTestResultData::decode):
+        * Shared/WebHitTestResultData.h:
+        * UIProcess/API/APIHitTestResult.h:
+        (API::HitTestResult::allowsCopy const): Deleted.
+        * UIProcess/API/glib/WebKitEditorState.cpp:
+        (webkitEditorStateChanged):
+        (webkit_editor_state_is_cut_available):
+        (webkit_editor_state_is_copy_available):
+        (webkit_editor_state_is_paste_available):
+        (webkit_editor_state_is_undo_available):
+        (webkit_editor_state_is_redo_available):
+        * UIProcess/API/glib/WebKitWebView.cpp:
+        (webkit_web_view_can_execute_editing_command):
+        * UIProcess/API/gtk/WebKitEditorState.h:
+        * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
+        * UIProcess/API/wpe/WebKitEditorState.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::editorState const):
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::performImmediateActionHitTestAtLocation):
+
 2017-10-27  Sam Weinig  <sam@webkit.org>
 
         [Settings] Generate more of the WebKit preferences code
index d4d0950..490f30d 100644 (file)
@@ -42,10 +42,8 @@ void EditorState::encode(IPC::Encoder& encoder) const
     encoder << hasComposition;
     encoder << isMissingPostLayoutData;
 
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
     if (!isMissingPostLayoutData)
         m_postLayoutData.encode(encoder);
-#endif
 
 #if PLATFORM(IOS)
     encoder << firstMarkedRect;
@@ -83,12 +81,10 @@ bool EditorState::decode(IPC::Decoder& decoder, EditorState& result)
     if (!decoder.decode(result.isMissingPostLayoutData))
         return false;
 
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
     if (!result.isMissingPostLayoutData) {
         if (!PostLayoutData::decode(decoder, result.postLayoutData()))
             return false;
     }
-#endif
 
 #if PLATFORM(IOS)
     if (!decoder.decode(result.firstMarkedRect))
@@ -102,7 +98,6 @@ bool EditorState::decode(IPC::Decoder& decoder, EditorState& result)
     return true;
 }
 
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
 void EditorState::PostLayoutData::encode(IPC::Encoder& encoder) const
 {
     encoder << typingAttributes;
@@ -135,6 +130,11 @@ void EditorState::PostLayoutData::encode(IPC::Encoder& encoder) const
     encoder << paragraphContextForCandidateRequest;
     encoder << stringForCandidateRequest;
 #endif
+    encoder << canCut;
+    encoder << canCopy;
+    encoder << canPaste;
+    encoder << canUndo;
+    encoder << canRedo;
 }
 
 bool EditorState::PostLayoutData::decode(IPC::Decoder& decoder, PostLayoutData& result)
@@ -194,8 +194,18 @@ bool EditorState::PostLayoutData::decode(IPC::Decoder& decoder, PostLayoutData&
         return false;
 #endif
 
+    if (!decoder.decode(result.canCut))
+        return false;
+    if (!decoder.decode(result.canCopy))
+        return false;
+    if (!decoder.decode(result.canPaste))
+        return false;
+    if (!decoder.decode(result.canUndo))
+        return false;
+    if (!decoder.decode(result.canRedo))
+        return false;
+
     return true;
 }
-#endif // PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
 
 }
index f769720..600f252 100644 (file)
@@ -77,7 +77,6 @@ struct EditorState {
     String markedText;
 #endif
 
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
     struct PostLayoutData {
         uint32_t typingAttributes { AttributeNone };
 #if PLATFORM(IOS) || PLATFORM(GTK)
@@ -110,24 +109,26 @@ struct EditorState {
         String stringForCandidateRequest;
 #endif
 
+        bool canCut { false };
+        bool canCopy { false };
+        bool canPaste { false };
+        bool canUndo { false };
+        bool canRedo { false };
+
         void encode(IPC::Encoder&) const;
         static bool decode(IPC::Decoder&, PostLayoutData&);
     };
 
     const PostLayoutData& postLayoutData() const;
     PostLayoutData& postLayoutData();
-#endif // PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
 
     void encode(IPC::Encoder&) const;
     static bool decode(IPC::Decoder&, EditorState&);
 
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
 private:
     PostLayoutData m_postLayoutData;
-#endif
 };
 
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(MAC)
 inline auto EditorState::postLayoutData() -> PostLayoutData&
 {
     ASSERT_WITH_MESSAGE(!isMissingPostLayoutData, "Attempt to access post layout data before receiving it");
@@ -139,7 +140,6 @@ inline auto EditorState::postLayoutData() const -> const PostLayoutData&
     ASSERT_WITH_MESSAGE(!isMissingPostLayoutData, "Attempt to access post layout data before receiving it");
     return m_postLayoutData;
 }
-#endif
 
 }
 
index bb131ba..179ca4b 100644 (file)
@@ -53,7 +53,6 @@ WebHitTestResultData::WebHitTestResultData(const WebCore::HitTestResult& hitTest
     , isSelected(hitTestResult.isSelected())
     , isTextNode(hitTestResult.innerNode() && hitTestResult.innerNode()->isTextNode())
     , isOverTextInsideFormControlElement(hitTestResult.isOverTextInsideFormControlElement())
-    , allowsCopy(hitTestResult.allowsCopy())
     , isDownloadableMedia(hitTestResult.isDownloadableMedia())
     , imageSize(0)
 {
@@ -73,7 +72,6 @@ WebHitTestResultData::WebHitTestResultData(const WebCore::HitTestResult& hitTest
     , isSelected(hitTestResult.isSelected())
     , isTextNode(hitTestResult.innerNode() && hitTestResult.innerNode()->isTextNode())
     , isOverTextInsideFormControlElement(hitTestResult.isOverTextInsideFormControlElement())
-    , allowsCopy(hitTestResult.allowsCopy())
     , isDownloadableMedia(hitTestResult.isDownloadableMedia())
     , imageSize(0)
 {
@@ -109,7 +107,6 @@ void WebHitTestResultData::encode(IPC::Encoder& encoder) const
     encoder << isSelected;
     encoder << isTextNode;
     encoder << isOverTextInsideFormControlElement;
-    encoder << allowsCopy;
     encoder << isDownloadableMedia;
     encoder << lookupText;
     encoder << dictionaryPopupInfo;
@@ -143,7 +140,6 @@ bool WebHitTestResultData::decode(IPC::Decoder& decoder, WebHitTestResultData& h
         || !decoder.decode(hitTestResultData.isSelected)
         || !decoder.decode(hitTestResultData.isTextNode)
         || !decoder.decode(hitTestResultData.isOverTextInsideFormControlElement)
-        || !decoder.decode(hitTestResultData.allowsCopy)
         || !decoder.decode(hitTestResultData.isDownloadableMedia)
         || !decoder.decode(hitTestResultData.lookupText)
         || !decoder.decode(hitTestResultData.dictionaryPopupInfo))
index 32468ab..d3cfeec 100644 (file)
@@ -57,7 +57,6 @@ struct WebHitTestResultData {
     bool isSelected;
     bool isTextNode;
     bool isOverTextInsideFormControlElement;
-    bool allowsCopy;
     bool isDownloadableMedia;
 
     String lookupText;
index cd939c9..30622b4 100644 (file)
@@ -70,8 +70,6 @@ public:
 
     bool isOverTextInsideFormControlElement() const { return m_data.isOverTextInsideFormControlElement; }
 
-    bool allowsCopy() const { return m_data.allowsCopy; }
-
     bool isDownloadableMedia() const { return m_data.isDownloadableMedia; }
 
 private:
index 6553a8d..406bfdb 100644 (file)
@@ -34,8 +34,8 @@ using namespace WebKit;
  * @See_also: #WebKitWebView
  *
  * WebKitEditorState represents the state of a #WebKitWebView editor.
- * Use webkit_web_view_get_editor_state() to get WebKitEditorState of
- * a #WebKitWebView.
+ * Use webkit_web_view_get_editor_state() to get the WebKitEditorState
+ * of a #WebKitWebView.
  *
  * Since: 2.10
  */
@@ -48,6 +48,11 @@ enum {
 
 struct _WebKitEditorStatePrivate {
     unsigned typingAttributes;
+    unsigned isCutAvailable : 1;
+    unsigned isCopyAvailable : 1;
+    unsigned isPasteAvailable : 1;
+    unsigned isUndoAvailable : 1;
+    unsigned isRedoAvailable : 1;
 };
 
 WEBKIT_DEFINE_TYPE(WebKitEditorState, webkit_editor_state, G_TYPE_OBJECT)
@@ -111,7 +116,6 @@ void webkitEditorStateChanged(WebKitEditorState* editorState, const EditorState&
         return;
 
     unsigned typingAttributes = WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE;
-#if PLATFORM(GTK)
     const auto& postLayoutData = newState.postLayoutData();
     if (postLayoutData.typingAttributes & AttributeBold)
         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD;
@@ -121,8 +125,14 @@ void webkitEditorStateChanged(WebKitEditorState* editorState, const EditorState&
         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE;
     if (postLayoutData.typingAttributes & AttributeStrikeThrough)
         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH;
-#endif
+
     webkitEditorStateSetTypingAttributes(editorState, typingAttributes);
+
+    editorState->priv->isCutAvailable = postLayoutData.canCut;
+    editorState->priv->isCopyAvailable = postLayoutData.canCopy;
+    editorState->priv->isPasteAvailable = postLayoutData.canPaste;
+    editorState->priv->isUndoAvailable = postLayoutData.canUndo;
+    editorState->priv->isRedoAvailable = postLayoutData.canRedo;
 }
 
 /**
@@ -146,3 +156,87 @@ guint webkit_editor_state_get_typing_attributes(WebKitEditorState* editorState)
     return editorState->priv->typingAttributes;
 }
 
+/**
+ * webkit_editor_state_is_cut_available:
+ * @editor_state: a #WebKitEditorState
+ *
+ * Gets whether a cut command can be issued.
+ *
+ * Returns: %TRUE if cut is currently available
+ *
+ * Since: 2.20
+ */
+gboolean webkit_editor_state_is_cut_available(WebKitEditorState* editorState)
+{
+    g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
+
+    return editorState->priv->isCutAvailable;
+}
+
+/**
+ * webkit_editor_state_is_copy_available:
+ * @editor_state: a #WebKitEditorState
+ *
+ * Gets whether a copy command can be issued.
+ *
+ * Returns: %TRUE if copy is currently available
+ *
+ * Since: 2.20
+ */
+gboolean webkit_editor_state_is_copy_available(WebKitEditorState* editorState)
+{
+    g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
+
+    return editorState->priv->isCopyAvailable;
+}
+
+/**
+ * webkit_editor_state_is_paste_available:
+ * @editor_state: a #WebKitEditorState
+ *
+ * Gets whether a paste command can be issued.
+ *
+ * Returns: %TRUE if paste is currently available
+ *
+ * Since: 2.20
+ */
+gboolean webkit_editor_state_is_paste_available(WebKitEditorState* editorState)
+{
+    g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
+
+    return editorState->priv->isPasteAvailable;
+}
+
+/**
+ * webkit_editor_state_is_undo_available:
+ * @editor_state: a #WebKitEditorState
+ *
+ * Gets whether an undo command can be issued.
+ *
+ * Returns: %TRUE if undo is currently available
+ *
+ * Since: 2.20
+ */
+gboolean webkit_editor_state_is_undo_available(WebKitEditorState* editorState)
+{
+    g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
+
+    return editorState->priv->isUndoAvailable;
+}
+
+/**
+ * webkit_editor_state_is_redo_available:
+ * @editor_state: a #WebKitEditorState
+ *
+ * Gets whether a redo command can be issued.
+ *
+ * Returns: %TRUE if redo is currently available
+ *
+ * Since: 2.20
+ */
+gboolean webkit_editor_state_is_redo_available(WebKitEditorState* editorState)
+{
+    g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
+
+    return editorState->priv->isRedoAvailable;
+}
index 1d6a3ab..79b90d0 100644 (file)
@@ -35,6 +35,7 @@
 #include "WebKitContextMenuItemPrivate.h"
 #include "WebKitContextMenuPrivate.h"
 #include "WebKitDownloadPrivate.h"
+#include "WebKitEditingCommands.h"
 #include "WebKitEditorStatePrivate.h"
 #include "WebKitEnumTypes.h"
 #include "WebKitError.h"
@@ -3087,9 +3088,23 @@ void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const c
     g_return_if_fail(command);
 
     GTask* task = g_task_new(webView, cancellable, callback, userData);
-    getPage(webView).validateCommand(String::fromUTF8(command), [task](const String&, bool isEnabled, int32_t, WebKit::CallbackBase::Error) {
-        g_task_return_boolean(adoptGRef(task).get(), isEnabled);        
-    });
+    WebKitEditorState* state = webkit_web_view_get_editor_state(webView);
+
+    if (!strcmp(command, WEBKIT_EDITING_COMMAND_CUT))
+        g_task_return_boolean(adoptGRef(task).get(), webkit_editor_state_is_cut_available(state));
+    else if (!strcmp(command, WEBKIT_EDITING_COMMAND_COPY))
+        g_task_return_boolean(adoptGRef(task).get(), webkit_editor_state_is_copy_available(state));
+    else if (!strcmp(command, WEBKIT_EDITING_COMMAND_PASTE))
+        g_task_return_boolean(adoptGRef(task).get(), webkit_editor_state_is_paste_available(state));
+    else if (!strcmp(command, WEBKIT_EDITING_COMMAND_UNDO))
+        g_task_return_boolean(adoptGRef(task).get(), webkit_editor_state_is_undo_available(state));
+    else if (!strcmp(command, WEBKIT_EDITING_COMMAND_REDO))
+        g_task_return_boolean(adoptGRef(task).get(), webkit_editor_state_is_redo_available(state));
+    else {
+        getPage(webView).validateCommand(String::fromUTF8(command), [task](const String&, bool isEnabled, int32_t, WebKit::CallbackBase::Error) {
+            g_task_return_boolean(adoptGRef(task).get(), isEnabled);        
+        });
+    }
 }
 
 /**
index 8a47755..7014053 100644 (file)
@@ -82,6 +82,21 @@ webkit_editor_state_get_type              (void);
 WEBKIT_API guint
 webkit_editor_state_get_typing_attributes (WebKitEditorState *editor_state);
 
+WEBKIT_API gboolean
+webkit_editor_state_is_cut_available      (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_copy_available     (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_paste_available    (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_undo_available     (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_redo_available     (WebKitEditorState *editor_state);
+
 G_END_DECLS
 
 #endif
index 3f7d828..36f4ff3 100644 (file)
@@ -823,6 +823,11 @@ webkit_hit_test_result_get_type
 WebKitEditorState
 WebKitEditorTypingAttributes
 webkit_editor_state_get_typing_attributes
+webkit_editor_state_is_cut_available
+webkit_editor_state_is_copy_available
+webkit_editor_state_is_paste_available
+webkit_editor_state_is_undo_available
+webkit_editor_state_is_redo_available
 
 <SUBSECTION Standard>
 WebKitEditorStateClass
index 8cf6595..f9e7c7d 100644 (file)
@@ -82,6 +82,21 @@ webkit_editor_state_get_type              (void);
 WEBKIT_API guint
 webkit_editor_state_get_typing_attributes (WebKitEditorState *editor_state);
 
+WEBKIT_API gboolean
+webkit_editor_state_is_cut_available      (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_copy_available     (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_paste_available    (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_undo_available     (WebKitEditorState *editor_state);
+
+WEBKIT_API gboolean
+webkit_editor_state_is_redo_available     (WebKitEditorState *editor_state);
+
 G_END_DECLS
 
 #endif
index 9daa287..58d49b2 100644 (file)
@@ -847,20 +847,27 @@ EditorState WebPage::editorState(IncludePostLayoutDataHint shouldIncludePostLayo
     }
 
     const VisibleSelection& selection = frame.selection().selection();
+    const Editor& editor = frame.editor();
 
     result.selectionIsNone = selection.isNone();
     result.selectionIsRange = selection.isRange();
     result.isContentEditable = selection.isContentEditable();
     result.isContentRichlyEditable = selection.isContentRichlyEditable();
     result.isInPasswordField = selection.isInPasswordField();
-    result.hasComposition = frame.editor().hasComposition();
-    result.shouldIgnoreSelectionChanges = frame.editor().ignoreSelectionChanges();
+    result.hasComposition = editor.hasComposition();
+    result.shouldIgnoreSelectionChanges = editor.ignoreSelectionChanges();
 
-#if PLATFORM(COCOA)
     bool canIncludePostLayoutData = frame.view() && !frame.view()->needsLayout();
-    if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::Yes && canIncludePostLayoutData && result.isContentEditable) {
+    if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::Yes && canIncludePostLayoutData) {
         auto& postLayoutData = result.postLayoutData();
-        if (!selection.isNone()) {
+        postLayoutData.canCut = editor.canCut();
+        postLayoutData.canCopy = editor.canCopy();
+        postLayoutData.canPaste = editor.canPaste();
+        postLayoutData.canUndo = editor.canUndo();
+        postLayoutData.canRedo = editor.canRedo();
+
+#if PLATFORM(COCOA)
+        if (result.isContentEditable && !selection.isNone()) {
             if (auto editingStyle = EditingStyle::styleAtSelectionStart(selection)) {
                 if (editingStyle->hasStyle(CSSPropertyFontWeight, "bold"))
                     postLayoutData.typingAttributes |= AttributeBold;
@@ -912,8 +919,8 @@ EditorState WebPage::editorState(IncludePostLayoutDataHint shouldIncludePostLayo
                     ASSERT_NOT_REACHED();
             }
         }
-    }
 #endif
+    }
 
     platformEditorState(frame, result, shouldIncludePostLayoutData);
 
index cf62992..b70d739 100644 (file)
@@ -1075,7 +1075,6 @@ void WebPage::performImmediateActionHitTestAtLocation(WebCore::FloatPoint locati
                 immediateActionResult.lookupText = selectedText;
                 immediateActionResult.isTextNode = true;
                 immediateActionResult.isSelected = true;
-                immediateActionResult.allowsCopy = true;
 
                 immediateActionResult.dictionaryPopupInfo = dictionaryPopupInfoForSelectionInPDFPlugin(selection, *pdfPugin, &options, TextIndicatorPresentationTransition::FadeIn);
             }
index 70a856f..0bfbc89 100644 (file)
@@ -1,3 +1,23 @@
+2017-10-30  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        [WPE][GTK] Expose availability of certain editing commands in WebKitEditorState
+        https://bugs.webkit.org/show_bug.cgi?id=168219
+
+        Reviewed by Ryosuke Niwa.
+
+        Test it.
+
+        * TestWebKitAPI/Tests/WebKitGtk/TestWebViewEditor.cpp:
+        (testWebViewEditorCutCopyPasteNonEditable):
+        (testWebViewEditorCutCopyPasteEditable):
+        (testWebViewEditorSelectAllNonEditable):
+        (testWebViewEditorSelectAllEditable):
+        (loadContentsAndTryToCutSelection):
+        (testWebViewEditorNonEditable):
+        (testWebViewEditorEditorStateTypingAttributes):
+        (testWebViewEditorInsertImage):
+        (testWebViewEditorCreateLink):
+
 2017-10-28  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         [WPE] Build gst-plugins-base without pango support
index 76fb6ce..862a24d 100644 (file)
@@ -37,6 +37,27 @@ public:
         gtk_clipboard_clear(m_clipboard);
     }
 
+    static gboolean webViewDrawCallback(GMainLoop* mainLoop)
+    {
+        g_main_loop_quit(mainLoop);
+        return G_SOURCE_REMOVE;
+    }
+
+    void flushEditorState()
+    {
+        // FIXME: It would be better to call WebViewTest::showInWindowAndWaitUntilMapped
+        // at the start of the test, rather than creating and destroying temporary windows.
+        showInWindow(GTK_WINDOW_TOPLEVEL);
+
+        g_signal_connect_swapped(m_webView, "draw", G_CALLBACK(webViewDrawCallback), m_mainLoop);
+        gtk_widget_queue_draw(GTK_WIDGET(m_webView));
+        g_main_loop_run(m_mainLoop);
+
+        gtk_container_remove(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView));
+        gtk_widget_destroy(m_parentWindow);
+        m_parentWindow = nullptr;
+    }
+
     static void canExecuteEditingCommandReadyCallback(GObject*, GAsyncResult* result, EditorTest* test)
     {
         GUniqueOutPtr<GError> error;
@@ -50,6 +71,20 @@ public:
         m_canExecuteEditingCommand = false;
         webkit_web_view_can_execute_editing_command(m_webView, command, 0, reinterpret_cast<GAsyncReadyCallback>(canExecuteEditingCommandReadyCallback), this);
         g_main_loop_run(m_mainLoop);
+
+        if (!strcmp(command, WEBKIT_EDITING_COMMAND_CUT))
+            g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_cut_available(editorState()));
+        else if (!strcmp(command, WEBKIT_EDITING_COMMAND_COPY))
+            g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_copy_available(editorState()));
+        else if (!strcmp(command, WEBKIT_EDITING_COMMAND_PASTE))
+            g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_paste_available(editorState()));
+        // FIXME: Figure out how to add tests for undo and redo. It will probably require using user
+        // scripts to message the UI process when the content has been altered.
+        else if (!strcmp(command, WEBKIT_EDITING_COMMAND_UNDO))
+            g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_undo_available(editorState()));
+        else if (!strcmp(command, WEBKIT_EDITING_COMMAND_REDO))
+            g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_redo_available(editorState()));
+
         return m_canExecuteEditingCommand;
     }
 
@@ -140,6 +175,7 @@ static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpoi
     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
     test->loadHtml(selectedSpanHTML.get(), nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
 
     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
     // It's not possible to cut and paste when content is not editable
@@ -166,6 +202,7 @@ static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointe
     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
     test->loadHtml(selectedSpanHTML.get(), nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
 
     // There's a selection.
     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
@@ -184,6 +221,7 @@ static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointe
     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
     test->loadHtml(selectedSpanHTML.get(), nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
 
     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
 
@@ -212,6 +250,7 @@ static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer)
     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
     test->loadHtml(selectedSpanHTML.get(), nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
 
     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
 
@@ -237,11 +276,14 @@ static void loadContentsAndTryToCutSelection(EditorTest* test, bool contentEdita
     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, contentEditable ? "true" : "false"));
     test->loadHtml(selectedSpanHTML.get(), nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
 
     g_assert(!test->isEditable());
     test->setEditable(true);
     g_assert(test->isEditable());
 
+    test->flushEditorState();
+
     // Cut the selection to the clipboard to see if the view is indeed editable.
     GUniquePtr<char> clipboardText(test->cutSelection());
     g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
@@ -256,6 +298,7 @@ static void testWebViewEditorNonEditable(EditorTest* test)
     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
     test->loadHtml(selectedSpanHTML.get(), nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
 
     g_assert(!test->isEditable());
     test->setEditable(true);
@@ -293,9 +336,9 @@ static void testWebViewEditorEditorStateTypingAttributes(EditorTest* test, gcons
         "<b><i>boldanditalic </i></b>"
         "</body></html>";
 
-    test->showInWindowAndWaitUntilMapped();
     test->loadHtml(typingAttributesHTML, nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
     test->setEditable(true);
 
     unsigned typingAttributes = test->typingAttributes();
@@ -406,6 +449,7 @@ static void testWebViewEditorInsertImage(EditorTest* test, gconstpointer)
 {
     test->loadHtml("<html><body></body></html>", "file:///");
     test->waitUntilLoadFinished();
+    test->flushEditorState();
     test->setEditable(true);
 
     GUniquePtr<char> imagePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
@@ -423,6 +467,7 @@ static void testWebViewEditorCreateLink(EditorTest* test, gconstpointer)
 {
     test->loadHtml("<html><body onload=\"document.getSelection().selectAllChildren(document.body);\">webkitgtk.org</body></html>", nullptr);
     test->waitUntilLoadFinished();
+    test->flushEditorState();
     test->setEditable(true);
 
     static const char* webkitGTKURL = "http://www.webkitgtk.org/";