WebCore headers should not be included relatively within dependent projects
[WebKit-https.git] / Source / WebKit / WebProcess / WebCoreSupport / gtk / WebEditorClientGtk.cpp
1 /*
2  *  Copyright (C) 2011 Igalia S.L.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public License
6  *  as published by the Free Software Foundation; either version 2 of
7  *  the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free
16  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301 USA
18  */
19
20 #include "config.h"
21 #include "WebEditorClient.h"
22
23 #include <WebCore/Document.h>
24 #include <WebCore/Editor.h>
25 #include <WebCore/EventNames.h>
26 #include <WebCore/Frame.h>
27 #include <WebCore/KeyboardEvent.h>
28 #include <WebCore/Pasteboard.h>
29 #include <WebCore/PlatformKeyboardEvent.h>
30 #include <WebCore/markup.h>
31 #include <wtf/glib/GRefPtr.h>
32
33 namespace WebKit {
34 using namespace WebCore;
35
36 bool WebEditorClient::executePendingEditorCommands(Frame* frame, const Vector<WTF::String>& pendingEditorCommands, bool allowTextInsertion)
37 {
38     Vector<Editor::Command> commands;
39     for (auto& commandString : pendingEditorCommands) {
40         Editor::Command command = frame->editor().command(commandString);
41         if (command.isTextInsertion() && !allowTextInsertion)
42             return false;
43
44         commands.append(WTFMove(command));
45     }
46
47     for (auto& command : commands) {
48         if (!command.execute())
49             return false;
50     }
51
52     return true;
53 }
54
55 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
56 {
57     auto* platformEvent = event->underlyingPlatformEvent();
58     if (!platformEvent)
59         return;
60
61     // If this was an IME event don't do anything.
62     if (platformEvent->handledByInputMethod())
63         return;
64
65     ASSERT(event->target());
66     auto* frame = downcast<Node>(event->target())->document().frame();
67     ASSERT(frame);
68
69     const Vector<String> pendingEditorCommands = platformEvent->commands();
70     if (!pendingEditorCommands.isEmpty()) {
71
72         // During RawKeyDown events if an editor command will insert text, defer
73         // the insertion until the keypress event. We want keydown to bubble up
74         // through the DOM first.
75         if (platformEvent->type() == PlatformEvent::RawKeyDown) {
76             if (executePendingEditorCommands(frame, pendingEditorCommands, false))
77                 event->setDefaultHandled();
78
79             return;
80         }
81
82         // Only allow text insertion commands if the current node is editable.
83         if (executePendingEditorCommands(frame, pendingEditorCommands, frame->editor().canEdit())) {
84             event->setDefaultHandled();
85             return;
86         }
87     }
88
89     // Don't allow text insertion for nodes that cannot edit.
90     if (!frame->editor().canEdit())
91         return;
92
93     // This is just a normal text insertion, so wait to execute the insertion
94     // until a keypress event happens. This will ensure that the insertion will not
95     // be reflected in the contents of the field until the keyup DOM event.
96     if (event->type() != eventNames().keypressEvent)
97         return;
98
99     // Don't insert null or control characters as they can result in unexpected behaviour
100     if (event->charCode() < ' ')
101         return;
102
103     // Don't insert anything if a modifier is pressed
104     if (platformEvent->ctrlKey() || platformEvent->altKey())
105         return;
106
107     if (frame->editor().insertText(platformEvent->text(), event))
108         event->setDefaultHandled();
109 }
110
111 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* event)
112 {
113     auto* platformEvent = event->underlyingPlatformEvent();
114     if (platformEvent && platformEvent->handledByInputMethod())
115         event->setDefaultHandled();
116 }
117
118 void WebEditorClient::updateGlobalSelection(Frame* frame)
119 {
120     if (!frame->selection().isRange())
121         return;
122     RefPtr<Range> range = frame->selection().toNormalizedRange();
123     if (!range)
124         return;
125
126     PasteboardWebContent pasteboardContent;
127     pasteboardContent.canSmartCopyOrDelete = false;
128     pasteboardContent.text = range->text();
129     pasteboardContent.markup = createMarkup(*range, nullptr, AnnotateForInterchange, false, ResolveNonLocalURLs);
130     Pasteboard::createForGlobalSelection()->write(pasteboardContent);
131 }
132
133 bool WebEditorClient::shouldShowUnicodeMenu()
134 {
135     return true;
136 }
137
138 }