diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/gtk')
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp | 2 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp | 27 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp | 19 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/WebView.cpp | 265 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/WebView.h | 11 |
5 files changed, 309 insertions, 15 deletions
diff --git a/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp index a5c708f..89a9ef7 100644 --- a/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp @@ -32,7 +32,7 @@ #include "UpdateChunk.h" #include "WebProcessProxy.h" #include "WebView.h" - +#include <WebCore/GtkVersioning.h> #include <gdk/gdk.h> using namespace WebCore; diff --git a/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp b/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp index 6a6715a..118bee1 100644 --- a/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp @@ -58,7 +58,7 @@ void TextChecker::setGrammarCheckingEnabled(bool isGrammarCheckingEnabled) notImplemented(); } -int64_t TextChecker::uniqueSpellDocumentTag() +int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy*) { notImplemented(); return 0; @@ -69,18 +69,33 @@ void TextChecker::closeSpellDocumentWithTag(int64_t) notImplemented(); } -Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, const UChar* text, int length, uint64_t checkingTypes) +void TextChecker::checkSpellingOfString(int64_t, const UChar*, uint32_t, int32_t&, int32_t&) { notImplemented(); - return Vector<WebCore::TextCheckingResult>(); } -void TextChecker::updateSpellingUIWithMisspelledWord(const String& misspelledWord) +void TextChecker::checkGrammarOfString(int64_t, const UChar*, uint32_t, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&) { notImplemented(); } -void TextChecker::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +bool TextChecker::spellingUIIsShowing() +{ + notImplemented(); + return false; +} + +void TextChecker::toggleSpellingUIIsShowing() +{ + notImplemented(); +} + +void TextChecker::updateSpellingUIWithMisspelledWord(int64_t, const String&) +{ + notImplemented(); +} + +void TextChecker::updateSpellingUIWithGrammarString(int64_t, const String&, const GrammarDetail&) { notImplemented(); } @@ -90,7 +105,7 @@ void TextChecker::getGuessesForWord(int64_t spellDocumentTag, const String& word notImplemented(); } -void TextChecker::learnWord(const String& word) +void TextChecker::learnWord(int64_t, const String&) { notImplemented(); } diff --git a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp index 838de97..8945d13 100644 --- a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp @@ -27,6 +27,10 @@ #include "config.h" #include "WebPageProxy.h" +#include "NativeWebKeyboardEvent.h" +#include "NotImplemented.h" +#include "PageClient.h" + namespace WebKit { String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent) @@ -35,4 +39,19 @@ String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent return "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.7 (KHTML, like Gecko) Version/5.0 Safari/534.7"; } +void WebPageProxy::getEditorCommandsForKeyEvent(Vector<WTF::String>& commandsList) +{ + m_pageClient->getEditorCommandsForKeyEvent(m_keyEventQueue.first(), commandsList); +} + +void WebPageProxy::saveRecentSearches(const String&, const Vector<String>&) +{ + notImplemented(); +} + +void WebPageProxy::loadRecentSearches(const String&, Vector<String>&) +{ + notImplemented(); +} + } // namespace WebKit 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 diff --git a/Source/WebKit2/UIProcess/gtk/WebView.h b/Source/WebKit2/UIProcess/gtk/WebView.h index 6c281ed..6cef14c 100644 --- a/Source/WebKit2/UIProcess/gtk/WebView.h +++ b/Source/WebKit2/UIProcess/gtk/WebView.h @@ -30,6 +30,7 @@ #include "PageClient.h" #include "WebPageProxy.h" +#include "WindowsKeyboardCodes.h" #include <WebCore/IntSize.h> #include <gdk/gdk.h> #include <glib.h> @@ -64,6 +65,8 @@ public: void handleWheelEvent(GdkEventScroll*); void handleMouseEvent(GdkEvent*, int); + void addPendingEditorCommand(const char* command) { m_pendingEditorCommands.append(WTF::String(command)); } + private: WebView(WebContext*, WebPageGroup*); @@ -85,13 +88,14 @@ private: virtual void processDidCrash(); virtual void didRelaunchProcess(); virtual void pageClosed(); - virtual void setFocus(bool focused); virtual void takeFocus(bool direction); virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void setCursor(const WebCore::Cursor&); virtual void setViewportArguments(const WebCore::ViewportArguments&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); + virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); + virtual void executeUndoRedo(WebPageProxy::UndoOrRedo); virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&); @@ -103,6 +107,9 @@ private: virtual void didChangeScrollbarsForMainFrame() const; virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects); virtual float userSpaceScaleFactor() const { return 1; } + virtual void getEditorCommandsForKeyEvent(const NativeWebKeyboardEvent&, Vector<WTF::String>&); + virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned); + virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned); #if USE(ACCELERATED_COMPOSITING) virtual void pageDidEnterAcceleratedCompositing(); @@ -118,6 +125,8 @@ private: GtkWidget* m_viewWidget; bool m_isPageActive; RefPtr<WebPageProxy> m_page; + Vector<WTF::String> m_pendingEditorCommands; + GRefPtr<GtkWidget> m_nativeWidget; }; } // namespace WebKit |