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