18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Alp Toker <alp@atoker.com> 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Nuanti Ltd. 40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Diego Escalante Urrelo <diegoe@gnome.org> 50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * Copyright (C) 2009, 2010 Igalia S.L. 7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2010, Martin Robinson <mrobinson@webkit.org> 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Lesser General Public 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful, 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Lesser General Public License for more details. 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Lesser General Public 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License along with this library; if not, write to the Free Software 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EditorClientGtk.h" 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 27d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "DataObjectGtk.h" 2881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "DumpRenderTreeSupportGtk.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EditCommand.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Editor.h" 310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "EventNames.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FocusController.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h" 340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <glib.h> 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "KeyboardEvent.h" 36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "markup.h" 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h" 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h" 39d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "PasteboardHelperGtk.h" 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PlatformKeyboardEvent.h" 414576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#include "WebKitDOMBinding.h" 424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#include "WebKitDOMCSSStyleDeclarationPrivate.h" 434576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#include "WebKitDOMHTMLElementPrivate.h" 444576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#include "WebKitDOMNodePrivate.h" 454576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#include "WebKitDOMRangePrivate.h" 46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "WindowsKeyboardCodes.h" 47cad810f21b803229eb11403f9209855525a25d57Steve Block#include "webkitglobalsprivate.h" 48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "webkitmarshal.h" 49f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "webkitwebsettingsprivate.h" 50f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "webkitwebviewprivate.h" 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h> 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Arbitrary depth limit for the undo stack, to keep it from using 540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// unbounded memory. This is the maximum number of distinct undoable 550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// actions -- unbroken stretches of typed characters are coalesced 560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// into a single action. 570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#define maximumUndoStackDepth 1000 580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WebCore; 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebKit { 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic void imContextCommitted(GtkIMContext* context, const gchar* compositionString, EditorClient* client) 64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Frame* frame = core(client->webView())->focusController()->focusedOrMainFrame(); 66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!frame || !frame->editor()->canEdit()) 67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // If this signal fires during a keydown event when we are not in the middle 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // of a composition, then treat this 'commit' as a normal key event and just 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // change the editable area right before the keypress event. 72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (client->treatContextCommitAsKeyEvent()) { 73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block client->updatePendingComposition(compositionString); 74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 77f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // If this signal fires during a mousepress event when we are in the middle 78f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // of a composition, skip this 'commit' because the composition is already confirmed. 79f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (client->preventNextCompositionCommit()) 80f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return; 81f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 82dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block frame->editor()->confirmComposition(String::fromUTF8(compositionString)); 83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block client->clearPendingComposition(); 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void imContextPreeditChanged(GtkIMContext* context, EditorClient* client) 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Frame* frame = core(client->webView())->focusController()->focusedOrMainFrame(); 89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!frame || !frame->editor()->canEdit()) 90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We ignore the provided PangoAttrList for now. 93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block GOwnPtr<gchar> newPreedit(0); 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block gtk_im_context_get_preedit_string(context, &newPreedit.outPtr(), 0, 0); 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block String preeditString = String::fromUTF8(newPreedit.get()); 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Vector<CompositionUnderline> underlines; 98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false)); 99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block frame->editor()->setComposition(preeditString, underlines, 0, 0); 100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 1026c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void backspaceCallback(GtkWidget* widget, EditorClient* client) 1036c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1046c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "backspace"); 1056c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("DeleteBackward"); 1066c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1076c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1086c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void selectAllCallback(GtkWidget* widget, gboolean select, EditorClient* client) 1096c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1106c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "select-all"); 1116c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand(select ? "SelectAll" : "Unselect"); 1126c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1136c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1146c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void cutClipboardCallback(GtkWidget* widget, EditorClient* client) 1156c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1166c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "cut-clipboard"); 1176c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("Cut"); 1186c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1196c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1206c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void copyClipboardCallback(GtkWidget* widget, EditorClient* client) 1216c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1226c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "copy-clipboard"); 1236c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("Copy"); 1246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1256c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1266c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void pasteClipboardCallback(GtkWidget* widget, EditorClient* client) 1276c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1286c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "paste-clipboard"); 1296c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("Paste"); 1306c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1316c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic void toggleOverwriteCallback(GtkWidget* widget, EditorClient*) 13368513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 13468513a70bcd92384395513322f1b801e7bf9c729Steve Block // We don't support toggling the overwrite mode, but the default callback expects 13568513a70bcd92384395513322f1b801e7bf9c729Steve Block // the GtkTextView to have a layout, so we handle this signal just to stop it. 13668513a70bcd92384395513322f1b801e7bf9c729Steve Block g_signal_stop_emission_by_name(widget, "toggle-overwrite"); 13768513a70bcd92384395513322f1b801e7bf9c729Steve Block} 13868513a70bcd92384395513322f1b801e7bf9c729Steve Block 1396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner// GTK+ will still send these signals to the web view. So we can safely stop signal 1406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner// emission without breaking accessibility. 1416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic void popupMenuCallback(GtkWidget* widget, EditorClient*) 1426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{ 1436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner g_signal_stop_emission_by_name(widget, "popup-menu"); 1446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} 1456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerstatic void showHelpCallback(GtkWidget* widget, EditorClient*) 1476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{ 1486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner g_signal_stop_emission_by_name(widget, "show-help"); 1496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} 1506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1516c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic const char* const gtkDeleteCommands[][2] = { 1526c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteBackward", "DeleteForward" }, // Characters 1536c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteWordBackward", "DeleteWordForward" }, // Word ends 1546c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteWordBackward", "DeleteWordForward" }, // Words 1556c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Lines 1566c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Line ends 1576c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraph ends 1586c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraphs 1596c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { 0, 0 } // Whitespace (M-\ in Emacs) 1606c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen}; 1616c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1626c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void deleteFromCursorCallback(GtkWidget* widget, GtkDeleteType deleteType, gint count, EditorClient* client) 1636c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1646c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "delete-from-cursor"); 1656c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen int direction = count > 0 ? 1 : 0; 1666c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1676c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // Ensuring that deleteType <= G_N_ELEMENTS here results in a compiler warning 1686c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // that the condition is always true. 1696c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1706c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (deleteType == GTK_DELETE_WORDS) { 1716c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!direction) { 1726c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveWordForward"); 1736c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveWordBackward"); 1746c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } else { 1756c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveWordBackward"); 1766c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveWordForward"); 1776c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 1786c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } else if (deleteType == GTK_DELETE_DISPLAY_LINES) { 1796c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!direction) 1806c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveToBeginningOfLine"); 1816c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen else 1826c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveToEndOfLine"); 1836c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } else if (deleteType == GTK_DELETE_PARAGRAPHS) { 1846c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!direction) 1856c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveToBeginningOfParagraph"); 1866c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen else 1876c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand("MoveToEndOfParagraph"); 1886c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 1896c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1906c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen const char* rawCommand = gtkDeleteCommands[deleteType][direction]; 1916c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!rawCommand) 1926c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return; 1936c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1946c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen for (int i = 0; i < abs(count); i++) 1956c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand(rawCommand); 1966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 1976c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1986c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic const char* const gtkMoveCommands[][4] = { 1996c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveBackward", "MoveForward", 2006c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Forward/backward grapheme 201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch { "MoveLeft", "MoveRight", 2026c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Left/right grapheme 2036c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveWordBackward", "MoveWordForward", 2046c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveWordBackwardAndModifySelection", "MoveWordForwardAndModifySelection" }, // Forward/backward word 2056c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveUp", "MoveDown", 2066c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveUpAndModifySelection", "MoveDownAndModifySelection" }, // Up/down line 2076c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveToBeginningOfLine", "MoveToEndOfLine", 2086c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveToBeginningOfLineAndModifySelection", "MoveToEndOfLineAndModifySelection" }, // Up/down line ends 2096c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveParagraphForward", "MoveParagraphBackward", 2106c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveParagraphForwardAndModifySelection", "MoveParagraphBackwardAndModifySelection" }, // Up/down paragraphs 2116c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveToBeginningOfParagraph", "MoveToEndOfParagraph", 2126c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveToBeginningOfParagraphAndModifySelection", "MoveToEndOfParagraphAndModifySelection" }, // Up/down paragraph ends. 2136c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MovePageUp", "MovePageDown", 2146c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MovePageUpAndModifySelection", "MovePageDownAndModifySelection" }, // Up/down page 2156c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { "MoveToBeginningOfDocument", "MoveToEndOfDocument", 2166c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen "MoveToBeginningOfDocumentAndModifySelection", "MoveToEndOfDocumentAndModifySelection" }, // Begin/end of buffer 2176c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen { 0, 0, 2186c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 0, 0 } // Horizontal page movement 2196c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen}; 2206c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 2216c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint count, gboolean extendSelection, EditorClient* client) 2226c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 2236c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_stop_emission_by_name(widget, "move-cursor"); 2246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen int direction = count > 0 ? 1 : 0; 2256c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (extendSelection) 2266c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen direction += 2; 2276c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 2286c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (static_cast<unsigned>(step) >= G_N_ELEMENTS(gtkMoveCommands)) 2296c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return; 2306c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 2316c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen const char* rawCommand = gtkMoveCommands[step][direction]; 2326c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!rawCommand) 2336c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return; 2346c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 2356c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen for (int i = 0; i < abs(count); i++) 2366c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen client->addPendingEditorCommand(rawCommand); 2376c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 2386c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid EditorClient::updatePendingComposition(const gchar* newComposition) 240dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 241dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // The IMContext may signal more than one completed composition in a row, 242dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // in which case we want to append them, rather than overwrite the old one. 243dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!m_pendingComposition) 244dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_pendingComposition.set(g_strdup(newComposition)); 245dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block else 246dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_pendingComposition.set(g_strconcat(m_pendingComposition.get(), newComposition, NULL)); 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 249967717af5423377c967781471ee106e2bb4e11c8Ben Murdochvoid EditorClient::willSetInputMethodState() 250967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch{ 251967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch} 252967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::setInputMethodState(bool active) 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebKitWebViewPrivate* priv = m_webView->priv; 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (active) 25868513a70bcd92384395513322f1b801e7bf9c729Steve Block gtk_im_context_focus_in(priv->imContext.get()); 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 26068513a70bcd92384395513322f1b801e7bf9c729Steve Block gtk_im_context_focus_out(priv->imContext.get()); 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef MAEMO_CHANGES 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (active) 26468513a70bcd92384395513322f1b801e7bf9c729Steve Block hildon_gtk_im_context_show(priv->imContext.get()); 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 26668513a70bcd92384395513322f1b801e7bf9c729Steve Block hildon_gtk_im_context_hide(priv->imContext.get()); 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2704576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldDeleteRange(Range* range) 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2724576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 273cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); 2744576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-delete-range", kitRange.get(), &accept); 2754576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2784576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldShowDeleteInterface(HTMLElement* element) 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2804576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 281cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMHTMLElement> kitElement(adoptGRef(kit(element))); 2824576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-show-delete-interface-for-element", kitElement.get(), &accept); 2834576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::isContinuousSpellCheckingEnabled() 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch WebKitWebSettings* settings = webkit_web_view_get_settings(m_webView); 2890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch gboolean enabled; 2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch g_object_get(settings, "enable-spell-checking", &enabled, NULL); 2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return enabled; 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::isGrammarCheckingEnabled() 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint EditorClient::spellCheckerDocumentTag() 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3084576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldBeginEditing(WebCore::Range* range) 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 310dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block clearPendingComposition(); 311231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3124576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 313cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); 3144576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-begin-editing", kitRange.get(), &accept); 3154576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3184576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldEndEditing(WebCore::Range* range) 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 320dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block clearPendingComposition(); 321231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3224576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 323cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); 3244576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-end-editing", kitRange.get(), &accept); 3254576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3284576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangstatic WebKitInsertAction kit(EditorInsertAction action) 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3304576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang switch (action) { 3314576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang case EditorInsertActionTyped: 3324576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_INSERT_ACTION_TYPED; 3334576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang case EditorInsertActionPasted: 3344576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_INSERT_ACTION_PASTED; 3354576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang case EditorInsertActionDropped: 3364576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_INSERT_ACTION_DROPPED; 3374576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang } 3384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang ASSERT_NOT_REACHED(); 3394576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_INSERT_ACTION_TYPED; 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldInsertText(const String& string, Range* range, EditorInsertAction action) 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3444576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 345cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); 3464576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-insert-text", string.utf8().data(), kitRange.get(), kit(action), &accept); 3474576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3504576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangstatic WebKitSelectionAffinity kit(EAffinity affinity) 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3524576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang switch (affinity) { 3534576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang case UPSTREAM: 3544576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_SELECTION_AFFINITY_UPSTREAM; 3554576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang case DOWNSTREAM: 3564576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_SELECTION_AFFINITY_DOWNSTREAM; 3574576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang } 3584576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang ASSERT_NOT_REACHED(); 3594576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return WEBKIT_SELECTION_AFFINITY_UPSTREAM; 3604576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang} 3614576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 3624576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting) 3634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{ 3644576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 365cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitFromRange(fromRange ? adoptGRef(kit(fromRange)) : 0); 366cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitToRange(toRange ? adoptGRef(kit(toRange)) : 0); 3674576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-change-selected-range", kitFromRange.get(), kitToRange.get(), 3684576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang kit(affinity), stillSelecting, &accept); 3694576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 3704576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang} 3714576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 3724576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldApplyStyle(WebCore::CSSStyleDeclaration* declaration, WebCore::Range* range) 3734576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{ 3744576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 375cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMCSSStyleDeclaration> kitDeclaration(kit(declaration)); 376cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); 3774576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-apply-style", kitDeclaration.get(), kitRange.get(), &accept); 3784576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*) 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::didBeginEditing() 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3894576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "editing-began"); 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::respondToChangedContents() 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3944576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "user-changed-contents"); 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 397dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic WebKitWebView* viewSettingClipboard = 0; 398dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic void collapseSelection(GtkClipboard* clipboard, WebKitWebView* webView) 399dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (viewSettingClipboard && viewSettingClipboard == webView) 401dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 402dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block WebCore::Page* corePage = core(webView); 404dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!corePage || !corePage->focusController()) 405dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 406dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 407dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Frame* frame = corePage->focusController()->focusedOrMainFrame(); 408dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 409dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Collapse the selection without clearing it 410dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(frame); 411dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity()); 412dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 413dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 41468513a70bcd92384395513322f1b801e7bf9c729Steve Block#if PLATFORM(X11) 41568513a70bcd92384395513322f1b801e7bf9c729Steve Blockstatic void setSelectionPrimaryClipboardIfNeeded(WebKitWebView* webView) 41668513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 41768513a70bcd92384395513322f1b801e7bf9c729Steve Block if (!gtk_widget_has_screen(GTK_WIDGET(webView))) 41868513a70bcd92384395513322f1b801e7bf9c729Steve Block return; 41968513a70bcd92384395513322f1b801e7bf9c729Steve Block 42068513a70bcd92384395513322f1b801e7bf9c729Steve Block GtkClipboard* clipboard = gtk_widget_get_clipboard(GTK_WIDGET(webView), GDK_SELECTION_PRIMARY); 42168513a70bcd92384395513322f1b801e7bf9c729Steve Block DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); 42268513a70bcd92384395513322f1b801e7bf9c729Steve Block WebCore::Page* corePage = core(webView); 42368513a70bcd92384395513322f1b801e7bf9c729Steve Block Frame* targetFrame = corePage->focusController()->focusedOrMainFrame(); 42468513a70bcd92384395513322f1b801e7bf9c729Steve Block 42568513a70bcd92384395513322f1b801e7bf9c729Steve Block if (!targetFrame->selection()->isRange()) 42668513a70bcd92384395513322f1b801e7bf9c729Steve Block return; 42768513a70bcd92384395513322f1b801e7bf9c729Steve Block 42868513a70bcd92384395513322f1b801e7bf9c729Steve Block dataObject->clear(); 42968513a70bcd92384395513322f1b801e7bf9c729Steve Block dataObject->setRange(targetFrame->selection()->toNormalizedRange()); 43068513a70bcd92384395513322f1b801e7bf9c729Steve Block 43168513a70bcd92384395513322f1b801e7bf9c729Steve Block viewSettingClipboard = webView; 43268513a70bcd92384395513322f1b801e7bf9c729Steve Block GClosure* callback = g_cclosure_new_object(G_CALLBACK(collapseSelection), G_OBJECT(webView)); 43368513a70bcd92384395513322f1b801e7bf9c729Steve Block g_closure_set_marshal(callback, g_cclosure_marshal_VOID__VOID); 43468513a70bcd92384395513322f1b801e7bf9c729Steve Block pasteboardHelperInstance()->writeClipboardContents(clipboard, callback); 43568513a70bcd92384395513322f1b801e7bf9c729Steve Block viewSettingClipboard = 0; 43668513a70bcd92384395513322f1b801e7bf9c729Steve Block} 43768513a70bcd92384395513322f1b801e7bf9c729Steve Block#endif 43868513a70bcd92384395513322f1b801e7bf9c729Steve Block 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::respondToChangedSelection() 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4414576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "selection-changed"); 4424576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebKitWebViewPrivate* priv = m_webView->priv; 444d0825bca7fe65beaee391d30da42e937db621564Steve Block WebCore::Page* corePage = core(m_webView); 445d0825bca7fe65beaee391d30da42e937db621564Steve Block Frame* targetFrame = corePage->focusController()->focusedOrMainFrame(); 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!targetFrame) 4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (targetFrame->editor()->ignoreCompositionSelectionChange()) 4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 453d0825bca7fe65beaee391d30da42e937db621564Steve Block#if PLATFORM(X11) 45468513a70bcd92384395513322f1b801e7bf9c729Steve Block setSelectionPrimaryClipboardIfNeeded(m_webView); 455d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!targetFrame->editor()->hasComposition()) 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned start; 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned end; 4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!targetFrame->editor()->getCompositionSelection(start, end)) { 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // gtk_im_context_reset() clears the composition for us. 46468513a70bcd92384395513322f1b801e7bf9c729Steve Block gtk_im_context_reset(priv->imContext.get()); 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project targetFrame->editor()->confirmCompositionWithoutDisturbingSelection(); 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::didEndEditing() 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4714576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "editing-ended"); 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::didWriteSelectionToPasteboard() 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::didSetSelectionTypesForPasteboard() 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid EditorClient::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand> command) 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (undoStack.size() == maximumUndoStackDepth) 4870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch undoStack.removeFirst(); 4880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!m_isInRedo) 4890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch redoStack.clear(); 4900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch undoStack.append(command); 4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid EditorClient::registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand> command) 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch redoStack.append(command); 4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::clearUndoRedoOperations() 4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch undoStack.clear(); 5010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch redoStack.clear(); 5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 50481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool EditorClient::canCopyCut(bool defaultValue) const 50581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 50681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return defaultValue; 50781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 50881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 50981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool EditorClient::canPaste(bool defaultValue) const 51081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{ 51181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return defaultValue; 51281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} 51381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::canUndo() const 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return !undoStack.isEmpty(); 5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::canRedo() const 5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return !redoStack.isEmpty(); 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::undo() 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (canUndo()) { 5270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RefPtr<WebCore::EditCommand> command(*(--undoStack.end())); 5280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch undoStack.remove(--undoStack.end()); 5290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // unapply will call us back to push this command onto the redo stack. 5300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch command->unapply(); 5310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::redo() 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (canRedo()) { 5370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch RefPtr<WebCore::EditCommand> command(*(--redoStack.end())); 5380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch redoStack.remove(--redoStack.end()); 5390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(!m_isInRedo); 5410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_isInRedo = true; 5420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // reapply will call us back to push this command onto the undo stack. 5430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch command->reapply(); 5440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_isInRedo = false; 5450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5484576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangbool EditorClient::shouldInsertNode(Node* node, Range* range, EditorInsertAction action) 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5504576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang gboolean accept = TRUE; 551cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); 552cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<WebKitDOMNode> kitNode(adoptGRef(kit(node))); 5534576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang g_signal_emit_by_name(m_webView, "should-insert-node", kitNode.get(), kitRange.get(), kit(action), &accept); 5544576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return accept; 5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::pageDestroyed() 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete this; 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::smartInsertDeleteEnabled() 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 568635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectbool EditorClient::isSelectTrailingWhitespaceEnabled() 569635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 57081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) 57181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return false; 57281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return DumpRenderTreeSupportGtk::selectTrailingWhitespaceEnabled(); 573635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 574635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::toggleContinuousSpellChecking() 5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch WebKitWebSettings* settings = webkit_web_view_get_settings(m_webView); 5780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch gboolean enabled; 5800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch g_object_get(settings, "enable-spell-checking", &enabled, NULL); 5810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch g_object_set(settings, "enable-spell-checking", !enabled, NULL); 5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::toggleGrammarChecking() 5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned CtrlKey = 1 << 0; 5900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned AltKey = 1 << 1; 5910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const unsigned ShiftKey = 1 << 2; 5920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstruct KeyDownEntry { 5940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned virtualKey; 5950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned modifiers; 5960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch const char* name; 5970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}; 5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstruct KeyPressEntry { 6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned charCode; 6010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned modifiers; 6020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch const char* name; 6030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}; 6040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const KeyDownEntry keyDownEntries[] = { 6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { 'B', CtrlKey, "ToggleBold" }, 6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { 'I', CtrlKey, "ToggleItalic" }, 6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_ESCAPE, 0, "Cancel" }, 6090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_OEM_PERIOD, CtrlKey, "Cancel" }, 6100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_TAB, 0, "InsertTab" }, 6110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_TAB, ShiftKey, "InsertBacktab" }, 6120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_RETURN, 0, "InsertNewline" }, 6130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_RETURN, CtrlKey, "InsertNewline" }, 6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_RETURN, AltKey, "InsertNewline" }, 6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, 6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}; 6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const KeyPressEntry keyPressEntries[] = { 6190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { '\t', 0, "InsertTab" }, 6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { '\t', ShiftKey, "InsertBacktab" }, 6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { '\r', 0, "InsertNewline" }, 6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { '\r', CtrlKey, "InsertNewline" }, 6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { '\r', AltKey, "InsertNewline" }, 6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch { '\r', AltKey | ShiftKey, "InsertNewline" }, 6250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}; 6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6276c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenvoid EditorClient::generateEditorCommands(const KeyboardEvent* event) 6280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 6296c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent); 6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6316c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen m_pendingEditorCommands.clear(); 6326c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6336c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // First try to interpret the command as a native GTK+ key binding. 634a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#ifdef GTK_API_VERSION_2 6356c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), event->keyEvent()->gdkEventKey()); 636a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#else 637a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch gtk_bindings_activate_event(G_OBJECT(m_nativeWidget.get()), event->keyEvent()->gdkEventKey()); 638a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif 6396c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (m_pendingEditorCommands.size() > 0) 6406c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return; 6410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6426c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen static HashMap<int, const char*> keyDownCommandsMap; 6436c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen static HashMap<int, const char*> keyPressCommandsMap; 6440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6456c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (keyDownCommandsMap.isEmpty()) { 6460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++) 6476c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); 6480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++) 6506c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); 6510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 6530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch unsigned modifiers = 0; 6546c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (event->shiftKey()) 6550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch modifiers |= ShiftKey; 6566c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (event->altKey()) 6570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch modifiers |= AltKey; 6586c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (event->ctrlKey()) 6590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch modifiers |= CtrlKey; 6600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 661cad810f21b803229eb11403f9209855525a25d57Steve Block // For keypress events, we want charCode(), but keyCode() does that. 662cad810f21b803229eb11403f9209855525a25d57Steve Block int mapKey = modifiers << 16 | event->keyCode(); 663cad810f21b803229eb11403f9209855525a25d57Steve Block if (!mapKey) 6646c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return; 665cad810f21b803229eb11403f9209855525a25d57Steve Block HashMap<int, const char*>* commandMap = event->type() == eventNames().keydownEvent ? 666cad810f21b803229eb11403f9209855525a25d57Steve Block &keyDownCommandsMap : &keyPressCommandsMap; 667cad810f21b803229eb11403f9209855525a25d57Steve Block if (const char* commandString = commandMap->get(mapKey)) 668cad810f21b803229eb11403f9209855525a25d57Steve Block m_pendingEditorCommands.append(commandString); 6696c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 6706c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6716c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenbool EditorClient::executePendingEditorCommands(Frame* frame, bool allowTextInsertion) 6726c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 6736c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen Vector<Editor::Command> commands; 6746c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen for (size_t i = 0; i < m_pendingEditorCommands.size(); i++) { 675cad810f21b803229eb11403f9209855525a25d57Steve Block const char* commandString = m_pendingEditorCommands.at(i); 676cad810f21b803229eb11403f9209855525a25d57Steve Block ASSERT(commandString); 677cad810f21b803229eb11403f9209855525a25d57Steve Block Editor::Command command = frame->editor()->command(commandString); 6786c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (command.isTextInsertion() && !allowTextInsertion) 6796c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return false; 6806c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6816c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen commands.append(command); 6826c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 6836c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6846c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen bool success = true; 6856c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen for (size_t i = 0; i < commands.size(); i++) { 6866c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!commands.at(i).execute()) { 6876c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen success = false; 6886c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen break; 6896c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 6906c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 6916c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6926c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen m_pendingEditorCommands.clear(); 6936c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6946c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // If we successfully completed all editor commands, then 6956c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // this signals a canceling of the composition. 6966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (success) 6976c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen clearPendingComposition(); 6986c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 6996c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return success; 7000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 7010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 702231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid EditorClient::handleKeyboardEvent(KeyboardEvent* event) 7030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 704231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Node* node = event->target()->toNode(); 7050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(node); 7060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Frame* frame = node->document()->frame(); 7070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(frame); 7080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 709231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block const PlatformKeyboardEvent* platformEvent = event->keyEvent(); 710231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!platformEvent) 711231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 712231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 7136c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen generateEditorCommands(event); 7146c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (m_pendingEditorCommands.size() > 0) { 715231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 7166c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // During RawKeyDown events if an editor command will insert text, defer 7176c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // the insertion until the keypress event. We want keydown to bubble up 7186c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // through the DOM first. 719231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (platformEvent->type() == PlatformKeyboardEvent::RawKeyDown) { 7206c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (executePendingEditorCommands(frame, false)) 721231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block event->setDefaultHandled(); 722231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 723231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 724dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 725dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 72606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // Only allow text insertion commands if the current node is editable. 72706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (executePendingEditorCommands(frame, frame->editor()->canEdit())) { 728231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block event->setDefaultHandled(); 729231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 7320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 73306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // Don't allow text insertion for nodes that cannot edit. 73406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (!frame->editor()->canEdit()) 73506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return; 73606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 737231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // This is just a normal text insertion, so wait to execute the insertion 738231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // until a keypress event happens. This will ensure that the insertion will not 739231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // be reflected in the contents of the field until the keyup DOM event. 740231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (event->type() == eventNames().keypressEvent) { 7410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 742dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // If we have a pending composition at this point, it happened while 743dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // filtering a keypress, so we treat it as a normal text insertion. 744dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // This will also ensure that if the keypress event handler changed the 745dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // currently focused node, the text is still inserted into the original 746dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // node (insertText() has this logic, but confirmComposition() does not). 747dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_pendingComposition) { 748dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block frame->editor()->insertText(String::fromUTF8(m_pendingComposition.get()), event); 749dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block clearPendingComposition(); 750231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block event->setDefaultHandled(); 7510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 752231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } else { 753231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Don't insert null or control characters as they can result in unexpected behaviour 754231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (event->charCode() < ' ') 755231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 756231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 757231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Don't insert anything if a modifier is pressed 758231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (platformEvent->ctrlKey() || platformEvent->altKey()) 759231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 760231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 761231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (frame->editor()->insertText(platformEvent->text(), event)) 762231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block event->setDefaultHandled(); 763231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 764231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::handleInputMethodKeydown(KeyboardEvent* event) 7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 769563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark Frame* targetFrame = core(m_webView)->focusController()->focusedOrMainFrame(); 770563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark if (!targetFrame || !targetFrame->editor()->canEdit()) 771563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark return; 7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 773563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark WebKitWebViewPrivate* priv = m_webView->priv; 774dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 775f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick m_preventNextCompositionCommit = false; 776dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 777dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Some IM contexts (e.g. 'simple') will act as if they filter every 778dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // keystroke and just issue a 'commit' signal during handling. In situations 779dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // where the 'commit' signal happens during filtering and there is no active 780dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // composition, act as if the keystroke was not filtered. The one exception to 781dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // this is when the keyval parameter of the GdkKeyEvent is 0, which is often 782dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // a key event sent by the IM context for committing the current composition. 783dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 784dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Here is a typical sequence of events for the 'simple' context: 785dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 1. GDK key press event -> webkit_web_view_key_press_event 786dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 2. Keydown event -> EditorClient::handleInputMethodKeydown 787dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // gtk_im_context_filter_keypress returns true, but there is a pending 788dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // composition so event->preventDefault is not called (below). 789dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 3. Keydown event bubbles through the DOM 790dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 4. Keydown event -> EditorClient::handleKeyboardEvent 791dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // No action taken. 792dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 4. GDK key release event -> webkit_web_view_key_release_event 793dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 5. gtk_im_context_filter_keypress is called on the release event. 794dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Simple does not filter most key releases, so the event continues. 795dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 6. Keypress event bubbles through the DOM. 796dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 7. Keypress event -> EditorClient::handleKeyboardEvent 797dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // pending composition is inserted. 798dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 8. Keyup event bubbles through the DOM. 799dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 9. Keyup event -> EditorClient::handleKeyboardEvent 800dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // No action taken. 801dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 802dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // There are two situations where we do filter the keystroke: 803dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 1. The IMContext instructed us to filter and we have no pending composition. 804dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // 2. The IMContext did not instruct us to filter, but the keystroke caused a 805dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // composition in progress to finish. It seems that sometimes SCIM will finish 806dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // a composition and not mark the keystroke as filtered. 807dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_treatContextCommitAsKeyEvent = (!targetFrame->editor()->hasComposition()) 808dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block && event->keyEvent()->gdkEventKey()->keyval; 809dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block clearPendingComposition(); 81068513a70bcd92384395513322f1b801e7bf9c729Steve Block if ((gtk_im_context_filter_keypress(priv->imContext.get(), event->keyEvent()->gdkEventKey()) && !m_pendingComposition) 811dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block || (!m_treatContextCommitAsKeyEvent && !targetFrame->editor()->hasComposition())) 812dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block event->preventDefault(); 813dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 814dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_treatContextCommitAsKeyEvent = false; 8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 817f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid EditorClient::handleInputMethodMousePress() 818f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{ 819f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick Frame* targetFrame = core(m_webView)->focusController()->focusedOrMainFrame(); 820f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 821f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (!targetFrame || !targetFrame->editor()->canEdit()) 822f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return; 823f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 824f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick WebKitWebViewPrivate* priv = m_webView->priv; 825f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 826f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // When a mouse press fires, the commit signal happens during a composition. 827f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // In this case, if the focused node is changed, the commit signal happens in a diffrent node. 828f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick // Therefore, we need to confirm the current compositon and ignore the next commit signal. 829f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick GOwnPtr<gchar> newPreedit(0); 83068513a70bcd92384395513322f1b801e7bf9c729Steve Block gtk_im_context_get_preedit_string(priv->imContext.get(), &newPreedit.outPtr(), 0, 0); 831f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 832f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (g_utf8_strlen(newPreedit.get(), -1)) { 833f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick targetFrame->editor()->confirmComposition(); 834f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick m_preventNextCompositionCommit = true; 83568513a70bcd92384395513322f1b801e7bf9c729Steve Block gtk_im_context_reset(priv->imContext.get()); 836f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick } 837f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick} 838f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick 8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectEditorClient::EditorClient(WebKitWebView* webView) 8400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_isInRedo(false) 84181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if ENABLE(SPELLCHECK) 84281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch , m_textCheckerClient(webView) 84381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#endif 8440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_webView(webView) 845f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick , m_preventNextCompositionCommit(false) 846dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_treatContextCommitAsKeyEvent(false) 8476c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen , m_nativeWidget(gtk_text_view_new()) 8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebKitWebViewPrivate* priv = m_webView->priv; 85068513a70bcd92384395513322f1b801e7bf9c729Steve Block g_signal_connect(priv->imContext.get(), "commit", G_CALLBACK(imContextCommitted), this); 85168513a70bcd92384395513322f1b801e7bf9c729Steve Block g_signal_connect(priv->imContext.get(), "preedit-changed", G_CALLBACK(imContextPreeditChanged), this); 8526c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 8536c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this); 8546c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this); 8556c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this); 8566c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "paste-clipboard", G_CALLBACK(pasteClipboardCallback), this); 8576c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "select-all", G_CALLBACK(selectAllCallback), this); 8586c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "move-cursor", G_CALLBACK(moveCursorCallback), this); 8596c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen g_signal_connect(m_nativeWidget.get(), "delete-from-cursor", G_CALLBACK(deleteFromCursorCallback), this); 86068513a70bcd92384395513322f1b801e7bf9c729Steve Block g_signal_connect(m_nativeWidget.get(), "toggle-overwrite", G_CALLBACK(toggleOverwriteCallback), this); 8616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner g_signal_connect(m_nativeWidget.get(), "popup-menu", G_CALLBACK(popupMenuCallback), this); 8626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner g_signal_connect(m_nativeWidget.get(), "show-help", G_CALLBACK(showHelpCallback), this); 8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectEditorClient::~EditorClient() 8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project WebKitWebViewPrivate* priv = m_webView->priv; 86868513a70bcd92384395513322f1b801e7bf9c729Steve Block g_signal_handlers_disconnect_by_func(priv->imContext.get(), (gpointer)imContextCommitted, this); 86968513a70bcd92384395513322f1b801e7bf9c729Steve Block g_signal_handlers_disconnect_by_func(priv->imContext.get(), (gpointer)imContextPreeditChanged, this); 8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::textFieldDidBeginEditing(Element*) 8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::textFieldDidEndEditing(Element*) 8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::textDidChangeInTextField(Element*) 8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) 8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 8878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::textWillBeDeletedInTextField(Element*) 8908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::textDidChangeInTextArea(Element*) 8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) 9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 9028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::updateSpellingUIWithMisspelledWord(const String&) 9058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid EditorClient::showSpellingUI(bool) 9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 9128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool EditorClient::spellingUIIsShowing() 9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 921