summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/UIProcess/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/gtk')
-rw-r--r--Source/WebKit2/UIProcess/gtk/ChunkedUpdateDrawingAreaProxyGtk.cpp2
-rw-r--r--Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp27
-rw-r--r--Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp19
-rw-r--r--Source/WebKit2/UIProcess/gtk/WebView.cpp265
-rw-r--r--Source/WebKit2/UIProcess/gtk/WebView.h11
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