diff options
author | Ben Murdoch <benm@google.com> | 2011-06-02 12:07:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-10 10:47:21 +0100 |
commit | 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch) | |
tree | e4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebKit2/UIProcess/gtk/WebView.cpp | |
parent | 87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff) | |
download | external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2 |
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebKit2/UIProcess/gtk/WebView.cpp')
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/WebView.cpp | 265 |
1 files changed, 258 insertions, 7 deletions
diff --git a/Source/WebKit2/UIProcess/gtk/WebView.cpp b/Source/WebKit2/UIProcess/gtk/WebView.cpp index 2ff67cd..aa45c62 100644 --- a/Source/WebKit2/UIProcess/gtk/WebView.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebView.cpp @@ -30,6 +30,7 @@ #include "ChunkedUpdateDrawingAreaProxy.h" #include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" #include "NotImplemented.h" #include "WebContext.h" #include "WebContextMenuProxy.h" @@ -38,11 +39,12 @@ #include "WebPageProxy.h" #include <wtf/text/WTFString.h> +typedef HashMap<int, const char*> IntConstCharHashMap; + using namespace WebCore; namespace WebKit { - void WebView::handleFocusInEvent(GtkWidget* widget) { if (!(m_isPageActive)) { @@ -59,8 +61,185 @@ void WebView::handleFocusOutEvent(GtkWidget* widget) m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive); } + +static void backspaceCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "backspace"); + client->addPendingEditorCommand("DeleteBackward"); +} + +static void selectAllCallback(GtkWidget* widget, gboolean select, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "select-all"); + client->addPendingEditorCommand(select ? "SelectAll" : "Unselect"); +} + +static void cutClipboardCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "cut-clipboard"); + client->addPendingEditorCommand("Cut"); +} + +static void copyClipboardCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "copy-clipboard"); + client->addPendingEditorCommand("Copy"); +} + +static void pasteClipboardCallback(GtkWidget* widget, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "paste-clipboard"); + client->addPendingEditorCommand("Paste"); +} + +static void toggleOverwriteCallback(GtkWidget* widget, EditorClient*) +{ + // We don't support toggling the overwrite mode, but the default callback expects + // the GtkTextView to have a layout, so we handle this signal just to stop it. + g_signal_stop_emission_by_name(widget, "toggle-overwrite"); +} + +// GTK+ will still send these signals to the web view. So we can safely stop signal +// emission without breaking accessibility. +static void popupMenuCallback(GtkWidget* widget, EditorClient*) +{ + g_signal_stop_emission_by_name(widget, "popup-menu"); +} + +static void showHelpCallback(GtkWidget* widget, EditorClient*) +{ + g_signal_stop_emission_by_name(widget, "show-help"); +} + +static const char* const gtkDeleteCommands[][2] = { + { "DeleteBackward", "DeleteForward" }, // Characters + { "DeleteWordBackward", "DeleteWordForward" }, // Word ends + { "DeleteWordBackward", "DeleteWordForward" }, // Words + { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Lines + { "DeleteToBeginningOfLine", "DeleteToEndOfLine" }, // Line ends + { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraph ends + { "DeleteToBeginningOfParagraph", "DeleteToEndOfParagraph" }, // Paragraphs + { 0, 0 } // Whitespace (M-\ in Emacs) +}; + +static void deleteFromCursorCallback(GtkWidget* widget, GtkDeleteType deleteType, gint count, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "delete-from-cursor"); + int direction = count > 0 ? 1 : 0; + + // Ensuring that deleteType <= G_N_ELEMENTS here results in a compiler warning + // that the condition is always true. + + if (deleteType == GTK_DELETE_WORDS) { + if (!direction) { + client->addPendingEditorCommand("MoveWordForward"); + client->addPendingEditorCommand("MoveWordBackward"); + } else { + client->addPendingEditorCommand("MoveWordBackward"); + client->addPendingEditorCommand("MoveWordForward"); + } + } else if (deleteType == GTK_DELETE_DISPLAY_LINES) { + if (!direction) + client->addPendingEditorCommand("MoveToBeginningOfLine"); + else + client->addPendingEditorCommand("MoveToEndOfLine"); + } else if (deleteType == GTK_DELETE_PARAGRAPHS) { + if (!direction) + client->addPendingEditorCommand("MoveToBeginningOfParagraph"); + else + client->addPendingEditorCommand("MoveToEndOfParagraph"); + } + + const char* rawCommand = gtkDeleteCommands[deleteType][direction]; + if (!rawCommand) + return; + + for (int i = 0; i < abs(count); i++) + client->addPendingEditorCommand(rawCommand); +} + +static const char* const gtkMoveCommands[][4] = { + { "MoveBackward", "MoveForward", + "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Forward/backward grapheme + { "MoveLeft", "MoveRight", + "MoveBackwardAndModifySelection", "MoveForwardAndModifySelection" }, // Left/right grapheme + { "MoveWordBackward", "MoveWordForward", + "MoveWordBackwardAndModifySelection", "MoveWordForwardAndModifySelection" }, // Forward/backward word + { "MoveUp", "MoveDown", + "MoveUpAndModifySelection", "MoveDownAndModifySelection" }, // Up/down line + { "MoveToBeginningOfLine", "MoveToEndOfLine", + "MoveToBeginningOfLineAndModifySelection", "MoveToEndOfLineAndModifySelection" }, // Up/down line ends + { "MoveParagraphForward", "MoveParagraphBackward", + "MoveParagraphForwardAndModifySelection", "MoveParagraphBackwardAndModifySelection" }, // Up/down paragraphs + { "MoveToBeginningOfParagraph", "MoveToEndOfParagraph", + "MoveToBeginningOfParagraphAndModifySelection", "MoveToEndOfParagraphAndModifySelection" }, // Up/down paragraph ends. + { "MovePageUp", "MovePageDown", + "MovePageUpAndModifySelection", "MovePageDownAndModifySelection" }, // Up/down page + { "MoveToBeginningOfDocument", "MoveToEndOfDocument", + "MoveToBeginningOfDocumentAndModifySelection", "MoveToEndOfDocumentAndModifySelection" }, // Begin/end of buffer + { 0, 0, + 0, 0 } // Horizontal page movement +}; + +static void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint count, gboolean extendSelection, WebView* client) +{ + g_signal_stop_emission_by_name(widget, "move-cursor"); + int direction = count > 0 ? 1 : 0; + if (extendSelection) + direction += 2; + + if (static_cast<unsigned>(step) >= G_N_ELEMENTS(gtkMoveCommands)) + return; + + const char* rawCommand = gtkMoveCommands[step][direction]; + if (!rawCommand) + return; + + for (int i = 0; i < abs(count); i++) + client->addPendingEditorCommand(rawCommand); +} + +static const unsigned CtrlKey = 1 << 0; +static const unsigned AltKey = 1 << 1; +static const unsigned ShiftKey = 1 << 2; + +struct KeyDownEntry { + unsigned virtualKey; + unsigned modifiers; + const char* name; +}; + +struct KeyPressEntry { + unsigned charCode; + unsigned modifiers; + const char* name; +}; + +static const KeyDownEntry keyDownEntries[] = { + { 'B', CtrlKey, "ToggleBold" }, + { 'I', CtrlKey, "ToggleItalic" }, + { VK_ESCAPE, 0, "Cancel" }, + { VK_OEM_PERIOD, CtrlKey, "Cancel" }, + { VK_TAB, 0, "InsertTab" }, + { VK_TAB, ShiftKey, "InsertBacktab" }, + { VK_RETURN, 0, "InsertNewline" }, + { VK_RETURN, CtrlKey, "InsertNewline" }, + { VK_RETURN, AltKey, "InsertNewline" }, + { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, +}; + +static const KeyPressEntry keyPressEntries[] = { + { '\t', 0, "InsertTab" }, + { '\t', ShiftKey, "InsertBacktab" }, + { '\r', 0, "InsertNewline" }, + { '\r', CtrlKey, "InsertNewline" }, + { '\r', AltKey, "InsertNewline" }, + { '\r', AltKey | ShiftKey, "InsertNewline" }, +}; + WebView::WebView(WebContext* context, WebPageGroup* pageGroup) : m_isPageActive(true) + , m_nativeWidget(gtk_text_view_new()) { m_page = context->createWebPage(this, pageGroup); @@ -71,6 +250,17 @@ WebView::WebView(WebContext* context, WebPageGroup* pageGroup) WebViewWidget* webViewWidget = WEB_VIEW_WIDGET(m_viewWidget); webViewWidgetSetWebViewInstance(webViewWidget, this); + + g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this); + g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this); + g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this); + g_signal_connect(m_nativeWidget.get(), "paste-clipboard", G_CALLBACK(pasteClipboardCallback), this); + g_signal_connect(m_nativeWidget.get(), "select-all", G_CALLBACK(selectAllCallback), this); + g_signal_connect(m_nativeWidget.get(), "move-cursor", G_CALLBACK(moveCursorCallback), this); + g_signal_connect(m_nativeWidget.get(), "delete-from-cursor", G_CALLBACK(deleteFromCursorCallback), this); + g_signal_connect(m_nativeWidget.get(), "toggle-overwrite", G_CALLBACK(toggleOverwriteCallback), this); + g_signal_connect(m_nativeWidget.get(), "popup-menu", G_CALLBACK(popupMenuCallback), this); + g_signal_connect(m_nativeWidget.get(), "show-help", G_CALLBACK(showHelpCallback), this); } WebView::~WebView() @@ -99,7 +289,7 @@ void WebView::handleKeyboardEvent(GdkEventKey* event) void WebView::handleMouseEvent(GdkEvent* event, int currentClickCount) { - m_page->handleMouseEvent(WebEventFactory::createWebMouseEvent(event, currentClickCount)); + m_page->handleMouseEvent(NativeWebMouseEvent(event, currentClickCount)); } void WebView::handleWheelEvent(GdkEventScroll* event) @@ -107,6 +297,52 @@ void WebView::handleWheelEvent(GdkEventScroll* event) m_page->handleWheelEvent(WebEventFactory::createWebWheelEvent(event)); } +void WebView::getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent& event, Vector<WTF::String>& commandList) +{ + m_pendingEditorCommands.clear(); + +#ifdef GTK_API_VERSION_2 + gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key)); +#else + gtk_bindings_activate_event(G_OBJECT(m_nativeWidget.get()), const_cast<GdkEventKey*>(&event.nativeEvent()->key)); +#endif + + if (m_pendingEditorCommands.isEmpty()) { + commandList.append(m_pendingEditorCommands); + return; + } + + DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyDownCommandsMap, ()); + DEFINE_STATIC_LOCAL(IntConstCharHashMap, keyPressCommandsMap, ()); + + if (keyDownCommandsMap.isEmpty()) { + for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++) + keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); + + for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++) + keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); + } + + unsigned modifiers = 0; + if (event.shiftKey()) + modifiers |= ShiftKey; + if (event.altKey()) + modifiers |= AltKey; + if (event.controlKey()) + modifiers |= CtrlKey; + + // For keypress events, we want charCode(), but keyCode() does that. + int mapKey = modifiers << 16 | event.nativeVirtualKeyCode(); + if (mapKey) { + HashMap<int, const char*>* commandMap = event.type() == WebEvent::KeyDown ? + &keyDownCommandsMap : &keyPressCommandsMap; + if (const char* commandString = commandMap->get(mapKey)) + m_pendingEditorCommands.append(commandString); + } + + commandList.append(m_pendingEditorCommands); +} + bool WebView::isActive() { return m_isPageActive; @@ -179,11 +415,6 @@ void WebView::didRelaunchProcess() notImplemented(); } -void WebView::setFocus(bool) -{ - notImplemented(); -} - void WebView::takeFocus(bool) { notImplemented(); @@ -222,6 +453,17 @@ void WebView::clearAllEditCommands() notImplemented(); } +bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo) +{ + notImplemented(); + return false; +} + +void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo) +{ + notImplemented(); +} + FloatRect WebView::convertToDeviceSpace(const FloatRect& viewRect) { notImplemented(); @@ -312,5 +554,14 @@ void WebView::flashBackingStoreUpdates(const Vector<IntRect>&) notImplemented(); } +void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned) +{ + notImplemented(); +} + +void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned) +{ + notImplemented(); +} } // namespace WebKit |