663e2b139ed110fd64118a912fe8ab540701d8e6
[WebKit-https.git] / WebKit / gtk / WebCoreSupport / EditorClientGtk.cpp
1 /*
2  *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
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
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of 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 Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "config.h"
20 #include "EditorClientGtk.h"
21
22 #include "EditCommand.h"
23 #include "Editor.h"
24 #include "FocusController.h"
25 #include "Frame.h"
26 #include "KeyboardCodes.h"
27 #include "KeyboardEvent.h"
28 #include "NotImplemented.h"
29 #include "Page.h"
30 #include "PlatformKeyboardEvent.h"
31 #include "webkitprivate.h"
32
33 using namespace WebCore;
34
35 namespace WebKit {
36
37 static void imContextCommitted(GtkIMContext* context, const char* str, EditorClient* client)
38 {
39     Frame* frame = core(client->m_webView)->focusController()->focusedOrMainFrame();
40     frame->editor()->insertTextWithoutSendingTextEvent(str, false);
41 }
42
43 bool EditorClient::shouldDeleteRange(Range*)
44 {
45     notImplemented();
46     return true;
47 }
48
49 bool EditorClient::shouldShowDeleteInterface(HTMLElement*)
50 {
51     return false;
52 }
53
54 bool EditorClient::isContinuousSpellCheckingEnabled()
55 {
56     notImplemented();
57     return false;
58 }
59
60 bool EditorClient::isGrammarCheckingEnabled()
61 {
62     notImplemented();
63     return false;
64 }
65
66 int EditorClient::spellCheckerDocumentTag()
67 {
68     notImplemented();
69     return 0;
70 }
71
72 bool EditorClient::shouldBeginEditing(WebCore::Range*)
73 {
74     notImplemented();
75     return true;
76 }
77
78 bool EditorClient::shouldEndEditing(WebCore::Range*)
79 {
80     notImplemented();
81     return true;
82 }
83
84 bool EditorClient::shouldInsertText(String, Range*, EditorInsertAction)
85 {
86     notImplemented();
87     return true;
88 }
89
90 bool EditorClient::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool)
91 {
92     notImplemented();
93     return true;
94 }
95
96 bool EditorClient::shouldApplyStyle(WebCore::CSSStyleDeclaration*,
97                                       WebCore::Range*)
98 {
99     notImplemented();
100     return true;
101 }
102
103 bool EditorClient::shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*)
104 {
105     notImplemented();
106     return true;
107 }
108
109 void EditorClient::didBeginEditing()
110 {
111     notImplemented();
112 }
113
114 void EditorClient::respondToChangedContents()
115 {
116     notImplemented();
117 }
118
119 void EditorClient::respondToChangedSelection()
120 {
121     notImplemented();
122 }
123
124 void EditorClient::didEndEditing()
125 {
126     notImplemented();
127 }
128
129 void EditorClient::didWriteSelectionToPasteboard()
130 {
131     notImplemented();
132 }
133
134 void EditorClient::didSetSelectionTypesForPasteboard()
135 {
136     notImplemented();
137 }
138
139 bool EditorClient::isEditable()
140 {
141     return webkit_web_view_get_editable(m_webView);
142 }
143
144 void EditorClient::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand>)
145 {
146     notImplemented();
147 }
148
149 void EditorClient::registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand>)
150 {
151     notImplemented();
152 }
153
154 void EditorClient::clearUndoRedoOperations()
155 {
156     notImplemented();
157 }
158
159 bool EditorClient::canUndo() const
160 {
161     notImplemented();
162     return false;
163 }
164
165 bool EditorClient::canRedo() const
166 {
167     notImplemented();
168     return false;
169 }
170
171 void EditorClient::undo()
172 {
173     notImplemented();
174 }
175
176 void EditorClient::redo()
177 {
178     notImplemented();
179 }
180
181 bool EditorClient::shouldInsertNode(Node*, Range*, EditorInsertAction)
182 {
183     notImplemented();
184     return true;
185 }
186
187 void EditorClient::pageDestroyed()
188 {
189     delete this;
190 }
191
192 bool EditorClient::smartInsertDeleteEnabled()
193 {
194     notImplemented();
195     return false;
196 }
197
198 void EditorClient::toggleContinuousSpellChecking()
199 {
200     notImplemented();
201 }
202
203 void EditorClient::toggleGrammarChecking()
204 {
205 }
206
207 void EditorClient::handleKeyboardEvent(KeyboardEvent* event)
208 {
209     Frame* frame = core(m_webView)->focusController()->focusedOrMainFrame();
210     if (!frame || !frame->document()->focusedNode())
211         return;
212
213     const PlatformKeyboardEvent* kevent = event->keyEvent();
214     if (!kevent || kevent->type() == PlatformKeyboardEvent::KeyUp)
215         return;
216
217     Node* start = frame->selectionController()->start().node();
218     if (!start)
219         return;
220
221     // FIXME: Use GtkBindingSet instead of this hard-coded switch
222     // http://bugs.webkit.org/show_bug.cgi?id=15911
223
224     if (start->isContentEditable()) {
225         switch (kevent->windowsVirtualKeyCode()) {
226             case VK_BACK:
227                 frame->editor()->deleteWithDirection(SelectionController::BACKWARD,
228                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity, false, true);
229                 break;
230             case VK_DELETE:
231                 frame->editor()->deleteWithDirection(SelectionController::FORWARD,
232                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity, false, true);
233                 break;
234             case VK_LEFT:
235                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
236                         SelectionController::LEFT,
237                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity,
238                         true);
239                 break;
240             case VK_RIGHT:
241                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
242                         SelectionController::RIGHT,
243                         kevent->ctrlKey() ? WordGranularity : CharacterGranularity,
244                         true);
245                 break;
246             case VK_UP:
247                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
248                         SelectionController::BACKWARD,
249                         kevent->ctrlKey() ? ParagraphGranularity : LineGranularity,
250                         true);
251                 break;
252             case VK_DOWN:
253                 frame->selectionController()->modify(kevent->shiftKey() ? SelectionController::EXTEND : SelectionController::MOVE,
254                         SelectionController::FORWARD,
255                         kevent->ctrlKey() ? ParagraphGranularity : LineGranularity,
256                         true);
257                 break;
258             case VK_PRIOR:  // PageUp
259                 frame->editor()->command("MovePageUp").execute();
260                 break;
261             case VK_NEXT:  // PageDown
262                 frame->editor()->command("MovePageDown").execute();
263                 break;
264             case VK_HOME:
265                 if (kevent->ctrlKey() && kevent->shiftKey())
266                     frame->editor()->command("MoveToBeginningOfDocumentAndModifySelection").execute();
267                 else if (kevent->ctrlKey())
268                     frame->editor()->command("MoveToBeginningOfDocument").execute();
269                 else if (kevent->shiftKey())
270                     frame->editor()->command("MoveToBeginningOfLineAndModifySelection").execute();
271                 else
272                     frame->editor()->command("MoveToBeginningOfLine").execute();
273                 break;
274             case VK_END:
275                 if (kevent->ctrlKey() && kevent->shiftKey())
276                     frame->editor()->command("MoveToEndOfDocumentAndModifySelection").execute();
277                 else if (kevent->ctrlKey())
278                     frame->editor()->command("MoveToEndOfDocument").execute();
279                 else if (kevent->shiftKey())
280                     frame->editor()->command("MoveToEndOfLineAndModifySelection").execute();
281                 else
282                     frame->editor()->command("MoveToEndOfLine").execute();
283                 break;
284             case VK_RETURN:
285                 frame->editor()->command("InsertLineBreak").execute();
286                 break;
287             case VK_TAB:
288                 return;
289             default:
290                 if (!kevent->ctrlKey() && !kevent->altKey() && !kevent->text().isEmpty()) {
291                     if (kevent->text().length() == 1) {
292                         UChar ch = kevent->text()[0];
293                         // Don't insert null or control characters as they can result in unexpected behaviour
294                         if (ch < ' ')
295                             break;
296                     }
297                     frame->editor()->insertText(kevent->text(), event);
298                 } else if (kevent->ctrlKey()) {
299                     switch (kevent->windowsVirtualKeyCode()) {
300                         case VK_B:
301                             frame->editor()->command("ToggleBold").execute();
302                             break;
303                         case VK_I:
304                             frame->editor()->command("ToggleItalic").execute();
305                             break;
306                         case VK_Y:
307                             frame->editor()->command("Redo").execute();
308                             break;
309                         case VK_Z:
310                             frame->editor()->command("Undo").execute();
311                             break;
312                         default:
313                             return;
314                     }
315                 } else return;
316         }
317     } else {
318         switch (kevent->windowsVirtualKeyCode()) {
319             case VK_UP:
320                 frame->editor()->command("MoveUp").execute();
321                 break;
322             case VK_DOWN:
323                 frame->editor()->command("MoveDown").execute();
324                 break;
325             case VK_PRIOR:  // PageUp
326                 frame->editor()->command("MovePageUp").execute();
327                 break;
328             case VK_NEXT:  // PageDown
329                 frame->editor()->command("MovePageDown").execute();
330                 break;
331             case VK_HOME:
332                 if (kevent->ctrlKey())
333                     frame->editor()->command("MoveToBeginningOfDocument").execute();
334                 break;
335             case VK_END:
336                 if (kevent->ctrlKey())
337                     frame->editor()->command("MoveToEndOfDocument").execute();
338                 break;
339             default:
340                 return;
341         }
342     }
343     event->setDefaultHandled();
344 }
345
346
347 void EditorClient::handleInputMethodKeydown(KeyboardEvent*)
348 {
349     notImplemented();
350 }
351
352 EditorClient::EditorClient(WebKitWebView* webView)
353     : m_webView(webView)
354 {
355     WebKitWebViewPrivate* priv = m_webView->priv;
356     g_signal_connect(priv->imContext, "commit", G_CALLBACK(imContextCommitted), this);
357 }
358
359 EditorClient::~EditorClient()
360 {
361     WebKitWebViewPrivate* priv = m_webView->priv;
362     g_signal_handlers_disconnect_by_func(priv->imContext, (gpointer)imContextCommitted, this);
363 }
364
365 void EditorClient::textFieldDidBeginEditing(Element*)
366 {
367     gtk_im_context_focus_in(WEBKIT_WEB_VIEW_GET_PRIVATE(m_webView)->imContext);
368 }
369
370 void EditorClient::textFieldDidEndEditing(Element*)
371 {
372     WebKitWebViewPrivate* priv = m_webView->priv;
373
374     gtk_im_context_focus_out(priv->imContext);
375 #ifdef MAEMO_CHANGES
376     hildon_gtk_im_context_hide(priv->imContext);
377 #endif
378 }
379
380 void EditorClient::textDidChangeInTextField(Element*)
381 {
382     notImplemented();
383 }
384
385 bool EditorClient::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
386 {
387     notImplemented();
388     return false;
389 }
390
391 void EditorClient::textWillBeDeletedInTextField(Element*)
392 {
393     notImplemented();
394 }
395
396 void EditorClient::textDidChangeInTextArea(Element*)
397 {
398     notImplemented();
399 }
400
401 void EditorClient::ignoreWordInSpellDocument(const String&)
402 {
403     notImplemented();
404 }
405
406 void EditorClient::learnWord(const String&)
407 {
408     notImplemented();
409 }
410
411 void EditorClient::checkSpellingOfString(const UChar*, int, int*, int*)
412 {
413     notImplemented();
414 }
415
416 void EditorClient::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
417 {
418     notImplemented();
419 }
420
421 void EditorClient::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
422 {
423     notImplemented();
424 }
425
426 void EditorClient::updateSpellingUIWithMisspelledWord(const String&)
427 {
428     notImplemented();
429 }
430
431 void EditorClient::showSpellingUI(bool)
432 {
433     notImplemented();
434 }
435
436 bool EditorClient::spellingUIIsShowing()
437 {
438     notImplemented();
439     return false;
440 }
441
442 void EditorClient::getGuessesForWord(const String&, Vector<String>&)
443 {
444     notImplemented();
445 }
446
447 void EditorClient::setInputMethodState(bool)
448 {
449 }
450
451 }