diff options
author | Ben Murdoch <benm@google.com> | 2011-05-24 11:24:40 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-02 09:53:15 +0100 |
commit | 81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch) | |
tree | 7a9e5ed86ff429fd347a25153107221543909b19 /Source/WebKit/gtk/WebCoreSupport | |
parent | 94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff) | |
download | external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2 |
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/WebKit/gtk/WebCoreSupport')
11 files changed, 470 insertions, 174 deletions
diff --git a/Source/WebKit/gtk/WebCoreSupport/AssertMatchingEnums.cpp b/Source/WebKit/gtk/WebCoreSupport/AssertMatchingEnums.cpp index 9c596f8..298f329 100644 --- a/Source/WebKit/gtk/WebCoreSupport/AssertMatchingEnums.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/AssertMatchingEnums.cpp @@ -22,15 +22,29 @@ #include "config.h" #include "DumpRenderTreeSupportGtk.h" +#include "EditingBehaviorTypes.h" #include "FindOptions.h" +#include "FrameLoaderTypes.h" +#include "webkitwebnavigationaction.h" +#include "webkitwebsettings.h" #include <wtf/Assertions.h> #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, webcore_name) \ - COMPILE_ASSERT(int(WebKit::webkit_name) == int(WebCore::webcore_name), mismatching_enums) + COMPILE_ASSERT(int(webkit_name) == int(WebCore::webcore_name), mismatching_enums) -COMPILE_ASSERT_MATCHING_ENUM(WebFindOptionsCaseInsensitive , CaseInsensitive); -COMPILE_ASSERT_MATCHING_ENUM(WebFindOptionsAtWordStarts, AtWordStarts); -COMPILE_ASSERT_MATCHING_ENUM(WebFindOptionsTreatMedialCapitalAsWordStart, TreatMedialCapitalAsWordStart); -COMPILE_ASSERT_MATCHING_ENUM(WebFindOptionsBackwards, Backwards); -COMPILE_ASSERT_MATCHING_ENUM(WebFindOptionsWrapAround, WrapAround); -COMPILE_ASSERT_MATCHING_ENUM(WebFindOptionsStartInSelection, StartInSelection); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_EDITING_BEHAVIOR_MAC, EditingMacBehavior); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_EDITING_BEHAVIOR_WINDOWS, EditingWindowsBehavior); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_EDITING_BEHAVIOR_UNIX, EditingUnixBehavior); + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED, NavigationTypeLinkClicked); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED, NavigationTypeFormSubmitted); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_WEB_NAVIGATION_REASON_BACK_FORWARD, NavigationTypeBackForward); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_WEB_NAVIGATION_REASON_RELOAD, NavigationTypeReload); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED, NavigationTypeFormResubmitted); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_WEB_NAVIGATION_REASON_OTHER, NavigationTypeOther); + +COMPILE_ASSERT_MATCHING_ENUM(WebKit::WebFindOptionsAtWordStarts, AtWordStarts); +COMPILE_ASSERT_MATCHING_ENUM(WebKit::WebFindOptionsTreatMedialCapitalAsWordStart, TreatMedialCapitalAsWordStart); +COMPILE_ASSERT_MATCHING_ENUM(WebKit::WebFindOptionsBackwards, Backwards); +COMPILE_ASSERT_MATCHING_ENUM(WebKit::WebFindOptionsWrapAround, WrapAround); +COMPILE_ASSERT_MATCHING_ENUM(WebKit::WebFindOptionsStartInSelection, StartInSelection); diff --git a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp index bbfdd72..8e828ac 100644 --- a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp @@ -72,6 +72,7 @@ namespace WebKit { ChromeClient::ChromeClient(WebKitWebView* webView) : m_webView(webView) , m_closeSoonTimer(0) + , m_pendingScrollInvalidations(false) { ASSERT(m_webView); } @@ -218,7 +219,8 @@ void ChromeClient::setScrollbarsVisible(bool visible) g_object_set(webWindowFeatures, "scrollbar-visible", visible, NULL); } -bool ChromeClient::scrollbarsVisible() { +bool ChromeClient::scrollbarsVisible() +{ WebKitWebWindowFeatures* webWindowFeatures = webkit_web_view_get_window_features(m_webView); gboolean visible; @@ -353,12 +355,13 @@ bool ChromeClient::shouldInterruptJavaScript() return false; } -bool ChromeClient::tabsToLinks() const +KeyboardUIMode ChromeClient::keyboardUIMode() { + bool tabsToLinks = true; if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) - return DumpRenderTreeSupportGtk::linksIncludedInFocusChain(); + tabsToLinks = DumpRenderTreeSupportGtk::linksIncludedInFocusChain(); - return true; + return tabsToLinks ? KeyboardAccessTabsToLinks : KeyboardAccessDefault; } IntRect ChromeClient::windowResizerRect() const @@ -367,9 +370,16 @@ IntRect ChromeClient::windowResizerRect() const return IntRect(); } -void ChromeClient::invalidateWindow(const IntRect&, bool) +void ChromeClient::invalidateWindow(const IntRect&, bool immediate) { - notImplemented(); + // If we've invalidated regions for scrolling, force GDK to process those invalidations + // now. This will also cause child windows to move right away. This prevents redraw + // artifacts with child windows (e.g. Flash plugin instances). + if (immediate && m_pendingScrollInvalidations) { + m_pendingScrollInvalidations = false; + if (GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView))) + gdk_window_process_updates(window, TRUE); + } } void ChromeClient::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate) @@ -396,6 +406,8 @@ void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, con if (!window) return; + m_pendingScrollInvalidations = true; + // We cannot use gdk_window_scroll here because it is only able to // scroll the whole window at once, and we often need to scroll // portions of the window only (think frames). @@ -433,8 +445,6 @@ void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, con gdk_window_invalidate_region(window, invalidRegion, FALSE); cairo_region_destroy(invalidRegion); #endif - - gdk_window_process_updates(window, TRUE); } // FIXME: this does not take into account the WM decorations @@ -577,11 +587,9 @@ void ChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseNam DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), defaultQuota); WebKitWebFrame* webFrame = kit(frame); - WebKitWebView* webView = getViewFromFrame(webFrame); - WebKitSecurityOrigin* origin = webkit_web_frame_get_security_origin(webFrame); WebKitWebDatabase* webDatabase = webkit_security_origin_get_web_database(origin, databaseName.utf8().data()); - g_signal_emit_by_name(webView, "database-quota-exceeded", webFrame, webDatabase); + g_signal_emit_by_name(m_webView, "database-quota-exceeded", webFrame, webDatabase); } #endif @@ -603,7 +611,7 @@ void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) RefPtr<FileChooser> chooser = prpFileChooser; GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Upload File"), - GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(platformPageClient()))), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(m_webView))), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, @@ -644,29 +652,33 @@ void ChromeClient::dispatchViewportDataDidChange(const ViewportArguments& argume webkitViewportAttributesRecompute(webkit_web_view_get_viewport_attributes(m_webView)); } -void ChromeClient::setCursor(const Cursor&) +void ChromeClient::setCursor(const Cursor& cursor) { - notImplemented(); + // [GTK] Widget::setCursor() gets called frequently + // http://bugs.webkit.org/show_bug.cgi?id=16388 + // Setting the cursor may be an expensive operation in some backends, + // so don't re-set the cursor if it's already set to the target value. + GdkWindow* window = gtk_widget_get_window(platformPageClient()); + GdkCursor* currentCursor = gdk_window_get_cursor(window); + GdkCursor* newCursor = cursor.platformCursor().get(); + if (currentCursor != newCursor) + gdk_window_set_cursor(window, newCursor); } void ChromeClient::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) { WebKitWebFrame* webFrame = kit(frame); - WebKitWebView* webView = getViewFromFrame(webFrame); - GRefPtr<WebKitGeolocationPolicyDecision> policyDecision(adoptGRef(webkit_geolocation_policy_decision_new(webFrame, geolocation))); gboolean isHandled = FALSE; - g_signal_emit_by_name(webView, "geolocation-policy-decision-requested", webFrame, policyDecision.get(), &isHandled); + g_signal_emit_by_name(m_webView, "geolocation-policy-decision-requested", webFrame, policyDecision.get(), &isHandled); if (!isHandled) webkit_geolocation_policy_deny(policyDecision.get()); } void ChromeClient::cancelGeolocationPermissionRequestForFrame(WebCore::Frame* frame, WebCore::Geolocation*) { - WebKitWebFrame* webFrame = kit(frame); - WebKitWebView* webView = getViewFromFrame(webFrame); - g_signal_emit_by_name(webView, "geolocation-policy-decision-cancelled", webFrame); + g_signal_emit_by_name(m_webView, "geolocation-policy-decision-cancelled", kit(frame)); } bool ChromeClient::selectItemWritingDirectionIsNatural() @@ -698,18 +710,12 @@ bool ChromeClient::supportsFullscreenForNode(const Node* node) void ChromeClient::enterFullscreenForNode(Node* node) { - WebCore::Frame* frame = node->document()->frame(); - WebKitWebFrame* webFrame = kit(frame); - WebKitWebView* webView = getViewFromFrame(webFrame); - webViewEnterFullscreen(webView, node); + webViewEnterFullscreen(m_webView, node); } void ChromeClient::exitFullscreenForNode(Node* node) { - WebCore::Frame* frame = node->document()->frame(); - WebKitWebFrame* webFrame = kit(frame); - WebKitWebView* webView = getViewFromFrame(webFrame); - webViewExitFullscreen(webView); + webViewExitFullscreen(m_webView); } #endif diff --git a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h index d7644eb..462ddc4 100644 --- a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h @@ -91,7 +91,7 @@ namespace WebKit { virtual bool runJavaScriptPrompt(WebCore::Frame*, const WTF::String& message, const WTF::String& defaultValue, WTF::String& result); virtual void setStatusbarText(const WTF::String&); virtual bool shouldInterruptJavaScript(); - virtual bool tabsToLinks() const; + virtual WebCore::KeyboardUIMode keyboardUIMode(); virtual WebCore::IntRect windowResizerRect() const; @@ -154,6 +154,7 @@ namespace WebKit { WebKitWebView* m_webView; WebCore::KURL m_hoveredLinkURL; unsigned int m_closeSoonTimer; + bool m_pendingScrollInvalidations; }; } diff --git a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp index 83f7c21..6db2c81 100644 --- a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp @@ -48,6 +48,7 @@ #include "RenderTreeAsText.h" #include "RenderView.h" #include "SecurityOrigin.h" +#include "Settings.h" #include "TextIterator.h" #include "WorkerThread.h" #include "webkitglobalsprivate.h" @@ -68,6 +69,7 @@ using namespace WebKit; bool DumpRenderTreeSupportGtk::s_drtRun = false; bool DumpRenderTreeSupportGtk::s_linksIncludedInTabChain = true; +bool DumpRenderTreeSupportGtk::s_selectTrailingWhitespaceEnabled = false; DumpRenderTreeSupportGtk::DumpRenderTreeSupportGtk() { @@ -101,6 +103,16 @@ void DumpRenderTreeSupportGtk::setIconDatabaseEnabled(bool enabled) WebKit::setIconDatabaseEnabled(enabled); } +void DumpRenderTreeSupportGtk::setSelectTrailingWhitespaceEnabled(bool enabled) +{ + s_selectTrailingWhitespaceEnabled = enabled; +} + +bool DumpRenderTreeSupportGtk::selectTrailingWhitespaceEnabled() +{ + return s_selectTrailingWhitespaceEnabled; +} + JSValueRef DumpRenderTreeSupportGtk::nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) { JSLock lock(SilenceAssertionsOnly); @@ -610,17 +622,23 @@ void DumpRenderTreeSupportGtk::layoutFrame(WebKitWebFrame* frame) } // For testing fast/viewport. -void DumpRenderTreeSupportGtk::dumpConfigurationForViewport(WebKitWebView* webView, gint availableWidth, gint availableHeight) +void DumpRenderTreeSupportGtk::dumpConfigurationForViewport(WebKitWebView* webView, gint deviceDPI, gint deviceWidth, gint deviceHeight, gint availableWidth, gint availableHeight) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); ViewportArguments arguments = webView->priv->corePage->mainFrame()->document()->viewportArguments(); - // desktopWidth = 980, deviceWidth = 320, deviceHeight = 480, deviceDPI = 160 - ViewportAttributes attrs = computeViewportAttributes(arguments, 980, 320, 480, 160, IntSize(availableWidth, availableHeight)); + ViewportAttributes attrs = computeViewportAttributes(arguments, /* default layout width for non-mobile pages */ 980, deviceWidth, deviceHeight, deviceDPI, IntSize(availableWidth, availableHeight)); fprintf(stdout, "viewport size %dx%d scale %f with limits [%f, %f]\n", attrs.layoutSize.width(), attrs.layoutSize.height(), attrs.initialScale, attrs.minimumScale, attrs.maximumScale); } +void DumpRenderTreeSupportGtk::clearOpener(WebKitWebFrame* frame) +{ + Frame* coreFrame = core(frame); + if (coreFrame) + coreFrame->loader()->setOpener(0); +} + unsigned int DumpRenderTreeSupportGtk::workerThreadCount() { #if ENABLE(WORKERS) @@ -642,3 +660,12 @@ bool DumpRenderTreeSupportGtk::findString(WebKitWebView* webView, const gchar* t return core(webView)->findString(String::fromUTF8(targetString), findOptions); } +double DumpRenderTreeSupportGtk::defaultMinimumTimerInterval() +{ + return Settings::defaultMinDOMTimerInterval(); +} + +void DumpRenderTreeSupportGtk::setMinimumTimerInterval(WebKitWebView* webView, double interval) +{ + core(webView)->settings()->setMinDOMTimerInterval(interval); +} diff --git a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h index 553d7bb..595d6da 100644 --- a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h @@ -54,8 +54,13 @@ public: static void setLinksIncludedInFocusChain(bool); static bool linksIncludedInFocusChain(); static void setIconDatabaseEnabled(bool); + static void setSelectTrailingWhitespaceEnabled(bool); + static bool selectTrailingWhitespaceEnabled(); + static JSValueRef nodesFromRect(JSContextRef context, JSValueRef value, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping); - static void dumpConfigurationForViewport(WebKitWebView* webView, gint availableWidth, gint availableHeight); + static void dumpConfigurationForViewport(WebKitWebView* webView, gint deviceDPI, gint deviceWidth, gint deviceHeight, gint availableWidth, gint availableHeight); + + static void clearOpener(WebKitWebFrame*); // FIXME: Move these to webkitwebframe.h once their API has been discussed. static GSList* getFrameChildren(WebKitWebFrame*); @@ -89,6 +94,8 @@ public: static void confirmComposition(WebKitWebView*, const char* text); static bool firstRectForCharacterRange(WebKitWebView*, int location, int length, GdkRectangle*); static bool selectedRange(WebKitWebView*, int* start, int* end); + static double defaultMinimumTimerInterval(); // Not really tied to WebView + static void setMinimumTimerInterval(WebKitWebView*, double); // GC static void gcCollectJavascriptObjects(); @@ -103,6 +110,7 @@ public: private: static bool s_drtRun; static bool s_linksIncludedInTabChain; + static bool s_selectTrailingWhitespaceEnabled; }; #endif diff --git a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp index ee9bf9a..33fafaa 100644 --- a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp @@ -25,9 +25,9 @@ #include "EditorClientGtk.h" #include "DataObjectGtk.h" +#include "DumpRenderTreeSupportGtk.h" #include "EditCommand.h" #include "Editor.h" -#include <enchant.h> #include "EventNames.h" #include "FocusController.h" #include "Frame.h" @@ -481,11 +481,6 @@ void EditorClient::didSetSelectionTypesForPasteboard() notImplemented(); } -bool EditorClient::isEditable() -{ - return webkit_web_view_get_editable(m_webView); -} - void EditorClient::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand> command) { if (undoStack.size() == maximumUndoStackDepth) @@ -506,6 +501,16 @@ void EditorClient::clearUndoRedoOperations() redoStack.clear(); } +bool EditorClient::canCopyCut(bool defaultValue) const +{ + return defaultValue; +} + +bool EditorClient::canPaste(bool defaultValue) const +{ + return defaultValue; +} + bool EditorClient::canUndo() const { return !undoStack.isEmpty(); @@ -562,8 +567,9 @@ bool EditorClient::smartInsertDeleteEnabled() bool EditorClient::isSelectTrailingWhitespaceEnabled() { - notImplemented(); - return false; + if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) + return false; + return DumpRenderTreeSupportGtk::selectTrailingWhitespaceEnabled(); } void EditorClient::toggleContinuousSpellChecking() @@ -832,6 +838,9 @@ void EditorClient::handleInputMethodMousePress() EditorClient::EditorClient(WebKitWebView* webView) : m_isInRedo(false) +#if ENABLE(SPELLCHECK) + , m_textCheckerClient(webView) +#endif , m_webView(webView) , m_preventNextCompositionCommit(false) , m_treatContextCommitAsKeyEvent(false) @@ -887,100 +896,6 @@ void EditorClient::textDidChangeInTextArea(Element*) notImplemented(); } -void EditorClient::ignoreWordInSpellDocument(const String& text) -{ - GSList* dicts = webkitWebViewGetEnchantDicts(m_webView); - - for (; dicts; dicts = dicts->next) { - EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); - - enchant_dict_add_to_session(dict, text.utf8().data(), -1); - } -} - -void EditorClient::learnWord(const String& text) -{ - GSList* dicts = webkitWebViewGetEnchantDicts(m_webView); - - for (; dicts; dicts = dicts->next) { - EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); - - enchant_dict_add_to_personal(dict, text.utf8().data(), -1); - } -} - -void EditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength) -{ - GSList* dicts = webkitWebViewGetEnchantDicts(m_webView); - if (!dicts) - return; - - gchar* ctext = g_utf16_to_utf8(const_cast<gunichar2*>(text), length, 0, 0, 0); - int utflen = g_utf8_strlen(ctext, -1); - - PangoLanguage* language = pango_language_get_default(); - PangoLogAttr* attrs = g_new(PangoLogAttr, utflen+1); - - // pango_get_log_attrs uses an aditional position at the end of the text. - pango_get_log_attrs(ctext, -1, -1, language, attrs, utflen+1); - - for (int i = 0; i < length+1; i++) { - // We go through each character until we find an is_word_start, - // then we get into an inner loop to find the is_word_end corresponding - // to it. - if (attrs[i].is_word_start) { - int start = i; - int end = i; - int wordLength; - - while (attrs[end].is_word_end < 1) - end++; - - wordLength = end - start; - // Set the iterator to be at the current word end, so we don't - // check characters twice. - i = end; - - for (; dicts; dicts = dicts->next) { - EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); - gchar* cstart = g_utf8_offset_to_pointer(ctext, start); - gint bytes = static_cast<gint>(g_utf8_offset_to_pointer(ctext, end) - cstart); - gchar* word = g_new0(gchar, bytes+1); - int result; - - g_utf8_strncpy(word, cstart, end - start); - - result = enchant_dict_check(dict, word, -1); - g_free(word); - if (result) { - *misspellingLocation = start; - *misspellingLength = wordLength; - } else { - // Stop checking, this word is ok in at least one dict. - *misspellingLocation = -1; - *misspellingLength = 0; - break; - } - } - } - } - - g_free(attrs); - g_free(ctext); -} - -String EditorClient::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord) -{ - // This method can be implemented using customized algorithms for the particular browser. - // Currently, it computes an empty string. - return String(); -} - -void EditorClient::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*) -{ - notImplemented(); -} - void EditorClient::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) { notImplemented(); @@ -1002,24 +917,4 @@ bool EditorClient::spellingUIIsShowing() return false; } -void EditorClient::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses) -{ - GSList* dicts = webkitWebViewGetEnchantDicts(m_webView); - guesses.clear(); - - for (; dicts; dicts = dicts->next) { - size_t numberOfSuggestions; - size_t i; - - EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); - gchar** suggestions = enchant_dict_suggest(dict, word.utf8().data(), -1, &numberOfSuggestions); - - for (i = 0; i < numberOfSuggestions && i < 10; i++) - guesses.append(String::fromUTF8(suggestions[i])); - - if (numberOfSuggestions > 0) - enchant_dict_free_suggestions(dict, suggestions); - } -} - } diff --git a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h index 214dbd6..8aafe45 100644 --- a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h @@ -32,12 +32,19 @@ #define EditorClientGtk_h #include "EditorClient.h" +#include "TextCheckerClient.h" #include <wtf/Deque.h> #include <wtf/Forward.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> +#if ENABLE(SPELLCHECK) +#include "TextCheckerClientEnchant.h" +#else +#include "EmptyClients.h" +#endif + typedef struct _WebKitWebView WebKitWebView; namespace WebCore { @@ -47,7 +54,7 @@ class KeyboardEvent; namespace WebKit { - class EditorClient : public WebCore::EditorClient { +class EditorClient : public WebCore::EditorClient { protected: bool m_isInRedo; @@ -80,8 +87,6 @@ namespace WebKit { virtual void toggleGrammarChecking(); virtual int spellCheckerDocumentTag(); - virtual bool isEditable(); - virtual bool shouldBeginEditing(WebCore::Range*); virtual bool shouldEndEditing(WebCore::Range*); virtual bool shouldInsertNode(WebCore::Node*, WebCore::Range*, WebCore::EditorInsertAction); @@ -103,6 +108,8 @@ namespace WebKit { virtual void registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand>); virtual void clearUndoRedoOperations(); + virtual bool canCopyCut(bool defaultValue) const; + virtual bool canPaste(bool defaultValue) const; virtual bool canUndo() const; virtual bool canRedo() const; @@ -120,21 +127,21 @@ namespace WebKit { virtual void textWillBeDeletedInTextField(WebCore::Element*); virtual void textDidChangeInTextArea(WebCore::Element*); - virtual void ignoreWordInSpellDocument(const WTF::String&); - virtual void learnWord(const WTF::String&); - virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); - virtual WTF::String getAutoCorrectSuggestionForMisspelledWord(const WTF::String&); - virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual WebCore::TextCheckerClient* textChecker() { return &m_textCheckerClient; } + virtual void updateSpellingUIWithGrammarString(const WTF::String&, const WebCore::GrammarDetail&); virtual void updateSpellingUIWithMisspelledWord(const WTF::String&); virtual void showSpellingUI(bool show); virtual bool spellingUIIsShowing(); - virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses); virtual void willSetInputMethodState(); virtual void setInputMethodState(bool enabled); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {} private: +#if ENABLE(SPELLCHECK) + TextCheckerClientEnchant m_textCheckerClient; +#else + WebCore::EmptyTextCheckerClient m_textCheckerClient; +#endif WebKitWebView* m_webView; bool m_preventNextCompositionCommit; bool m_treatContextCommitAsKeyEvent; diff --git a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp index 875455a..d8ea90e 100644 --- a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp @@ -25,6 +25,8 @@ #include "config.h" #include "FrameLoaderClientGtk.h" +#include "AXObjectCache.h" +#include "AccessibilityObject.h" #include "ArchiveResource.h" #include "CachedFrame.h" #include "Color.h" @@ -55,6 +57,7 @@ #include "PluginDatabase.h" #include "ProgressTracker.h" #include "RenderPart.h" +#include "RenderView.h" #include "ResourceHandle.h" #include "ResourceRequest.h" #include "ScriptController.h" @@ -222,6 +225,51 @@ String FrameLoaderClient::userAgent(const KURL& url) return String::fromUTF8(webkit_web_settings_get_user_agent(settings)); } +static void notifyAccessibilityStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) +{ + if (loadStatus != WEBKIT_LOAD_PROVISIONAL + && loadStatus != WEBKIT_LOAD_FAILED + && loadStatus != WEBKIT_LOAD_FINISHED) + return; + + WebKitWebFramePrivate* priv = frame->priv; + if (!priv->coreFrame || !priv->coreFrame->document()) + return; + + RenderView* contentRenderer = priv->coreFrame->contentRenderer(); + if (!contentRenderer) + return; + + AXObjectCache* axObjectCache = priv->coreFrame->document()->axObjectCache(); + if (!axObjectCache) + return; + + AccessibilityObject* coreAxObject = axObjectCache->getOrCreate(contentRenderer); + if (!coreAxObject) + return; + + AtkObject* axObject = coreAxObject->wrapper(); + if (!axObject || !ATK_IS_DOCUMENT(axObject)) + return; + + switch (loadStatus) { + case WEBKIT_LOAD_PROVISIONAL: + g_signal_emit_by_name(axObject, "state-change", "busy", true); + if (core(frame)->loader()->loadType() == FrameLoadTypeReload) + g_signal_emit_by_name(axObject, "reload"); + break; + case WEBKIT_LOAD_FAILED: + g_signal_emit_by_name(axObject, "load-stopped"); + g_signal_emit_by_name(axObject, "state-change", "busy", false); + break; + case WEBKIT_LOAD_FINISHED: + g_signal_emit_by_name(axObject, "load-complete"); + g_signal_emit_by_name(axObject, "state-change", "busy", false); + default: + break; + } +} + static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) { frame->priv->loadStatus = loadStatus; @@ -231,6 +279,9 @@ static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) if (frame == webkit_web_view_get_main_frame(webView)) { webView->priv->loadStatus = loadStatus; g_object_notify(G_OBJECT(webView), "load-status"); + + if (AXObjectCache::accessibilityEnabled()) + notifyAccessibilityStatus(frame, loadStatus); } } @@ -407,7 +458,7 @@ void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* load m_response = response; } -void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String& mimeType, const ResourceRequest& resourceRequest) +void FrameLoaderClient::dispatchDecidePolicyForResponse(FramePolicyFunction policyFunction, const ResourceResponse& response, const ResourceRequest& resourceRequest) { ASSERT(policyFunction); if (!policyFunction) @@ -426,6 +477,8 @@ void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction poli g_object_unref(m_policyDecision); m_policyDecision = policyDecision; + String mimeType = response.mimeType(); + gboolean isHandled = false; g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled); @@ -757,6 +810,11 @@ bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const return item != 0; } +bool FrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const +{ + return true; +} + void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const { } diff --git a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h index 2e8a2dd..3340837 100644 --- a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h @@ -94,7 +94,7 @@ namespace WebKit { virtual WebCore::Frame* dispatchCreatePage(const WebCore::NavigationAction&); virtual void dispatchShow(); - virtual void dispatchDecidePolicyForMIMEType(WebCore::FramePolicyFunction, const WTF::String& MIMEType, const WebCore::ResourceRequest&); + virtual void dispatchDecidePolicyForResponse(WebCore::FramePolicyFunction, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&); virtual void dispatchDecidePolicyForNewWindowAction(WebCore::FramePolicyFunction, const WebCore::NavigationAction&, const WebCore::ResourceRequest&, WTF::PassRefPtr<WebCore::FormState>, const WTF::String& frameName); virtual void dispatchDecidePolicyForNavigationAction(WebCore::FramePolicyFunction, const WebCore::NavigationAction&, const WebCore::ResourceRequest&, WTF::PassRefPtr<WebCore::FormState>); virtual void cancelPolicyCheck(); @@ -141,6 +141,7 @@ namespace WebKit { virtual void updateGlobalHistory(); virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const; + virtual bool shouldStopLoadingForHistoryItem(WebCore::HistoryItem*) const; virtual void dispatchDidAddBackForwardItem(WebCore::HistoryItem*) const; virtual void dispatchDidRemoveBackForwardItem(WebCore::HistoryItem*) const; virtual void dispatchDidChangeBackForwardIndex() const; diff --git a/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp new file mode 100644 index 0000000..74e8132 --- /dev/null +++ b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2009 Diego Escalante Urrelo <diegoe@gnome.org> + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010 Igalia S.L. + * Copyright (C) 2010, Martin Robinson <mrobinson@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "TextCheckerClientEnchant.h" + +#include "NotImplemented.h" +#include "webkitwebsettingsprivate.h" +#include "webkitwebviewprivate.h" +#include <enchant.h> +#include <glib.h> +#include <wtf/text/CString.h> + +using namespace WebCore; + +namespace WebKit { + +EnchantBroker* TextCheckerClientEnchant::broker = 0; + +TextCheckerClientEnchant::TextCheckerClientEnchant(WebKitWebView* webView) + : m_webView(webView) + , m_enchantDicts(0) +{ +} + +TextCheckerClientEnchant::~TextCheckerClientEnchant() +{ + g_slist_foreach(m_enchantDicts, freeSpellCheckingLanguage, 0); + g_slist_free(m_enchantDicts); +} + +void TextCheckerClientEnchant::ignoreWordInSpellDocument(const String& text) +{ + GSList* dicts = m_enchantDicts; + + for (; dicts; dicts = dicts->next) { + EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); + + enchant_dict_add_to_session(dict, text.utf8().data(), -1); + } +} + +void TextCheckerClientEnchant::learnWord(const String& text) +{ + GSList* dicts = m_enchantDicts; + + for (; dicts; dicts = dicts->next) { + EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); + + enchant_dict_add_to_personal(dict, text.utf8().data(), -1); + } +} + +void TextCheckerClientEnchant::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength) +{ + GSList* dicts = m_enchantDicts; + if (!dicts) + return; + + gchar* ctext = g_utf16_to_utf8(const_cast<gunichar2*>(text), length, 0, 0, 0); + int utflen = g_utf8_strlen(ctext, -1); + + PangoLanguage* language(pango_language_get_default()); + GOwnPtr<PangoLogAttr> attrs(g_new(PangoLogAttr, utflen+1)); + + // pango_get_log_attrs uses an aditional position at the end of the text. + pango_get_log_attrs(ctext, -1, -1, language, attrs.get(), utflen+1); + + for (int i = 0; i < length+1; i++) { + // We go through each character until we find an is_word_start, + // then we get into an inner loop to find the is_word_end corresponding + // to it. + if (attrs.get()[i].is_word_start) { + int start = i; + int end = i; + int wordLength; + + while (attrs.get()[end].is_word_end < 1) + end++; + + wordLength = end - start; + // Set the iterator to be at the current word end, so we don't + // check characters twice. + i = end; + + for (; dicts; dicts = dicts->next) { + EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); + gchar* cstart = g_utf8_offset_to_pointer(ctext, start); + gint bytes = static_cast<gint>(g_utf8_offset_to_pointer(ctext, end) - cstart); + gchar* word = g_new0(gchar, bytes+1); + int result; + + g_utf8_strncpy(word, cstart, end - start); + + result = enchant_dict_check(dict, word, -1); + g_free(word); + if (result) { + *misspellingLocation = start; + *misspellingLength = wordLength; + } else { + // Stop checking, this word is ok in at least one dict. + *misspellingLocation = -1; + *misspellingLength = 0; + break; + } + } + } + } +} + +String TextCheckerClientEnchant::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord) +{ + // This method can be implemented using customized algorithms for the particular browser. + // Currently, it computes an empty string. + return String(); +} + +void TextCheckerClientEnchant::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*) +{ + notImplemented(); +} + +void TextCheckerClientEnchant::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses) +{ + GSList* dicts = m_enchantDicts; + guesses.clear(); + + for (; dicts; dicts = dicts->next) { + size_t numberOfSuggestions; + size_t i; + + EnchantDict* dict = static_cast<EnchantDict*>(dicts->data); + gchar** suggestions = enchant_dict_suggest(dict, word.utf8().data(), -1, &numberOfSuggestions); + + for (i = 0; i < numberOfSuggestions && i < 10; i++) + guesses.append(String::fromUTF8(suggestions[i])); + + if (numberOfSuggestions > 0) + enchant_dict_free_suggestions(dict, suggestions); + } +} + +static void getAvailableDictionariesCallback(const char* const languageTag, const char* const, const char* const, const char* const, void* data) +{ + Vector<CString>* dicts = static_cast<Vector<CString>*>(data); + + dicts->append(languageTag); +} + +void TextCheckerClientEnchant::updateSpellCheckingLanguage(const char* spellCheckingLanguages) +{ + EnchantDict* dict; + GSList* spellDictionaries = 0; + + if (!broker) + broker = enchant_broker_init(); + + if (spellCheckingLanguages) { + char** langs = g_strsplit(spellCheckingLanguages, ",", -1); + for (int i = 0; langs[i]; i++) { + if (enchant_broker_dict_exists(broker, langs[i])) { + dict = enchant_broker_request_dict(broker, langs[i]); + spellDictionaries = g_slist_append(spellDictionaries, dict); + } + } + g_strfreev(langs); + } else { + const char* language = pango_language_to_string(gtk_get_default_language()); + if (enchant_broker_dict_exists(broker, language)) { + dict = enchant_broker_request_dict(broker, language); + spellDictionaries = g_slist_append(spellDictionaries, dict); + } else { + // No dictionaries selected, we get one from the list + Vector<CString> allDictionaries; + enchant_broker_list_dicts(broker, getAvailableDictionariesCallback, &allDictionaries); + if (!allDictionaries.isEmpty()) { + dict = enchant_broker_request_dict(broker, allDictionaries[0].data()); + spellDictionaries = g_slist_append(spellDictionaries, dict); + } + } + } + g_slist_foreach(m_enchantDicts, freeSpellCheckingLanguage, 0); + g_slist_free(m_enchantDicts); + m_enchantDicts = spellDictionaries; +} + +void TextCheckerClientEnchant::freeSpellCheckingLanguage(gpointer data, gpointer) +{ + if (!broker) + broker = enchant_broker_init(); + + EnchantDict* dict = static_cast<EnchantDict*>(data); + enchant_broker_free_dict(broker, dict); +} + +} diff --git a/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h new file mode 100644 index 0000000..c294a3d --- /dev/null +++ b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextCheckerClientEnchant_h +#define TextCheckerClientEnchant_h + +#include "TextCheckerClient.h" + +typedef struct _GSList GSList; +typedef struct _WebKitWebView WebKitWebView; +typedef struct str_enchant_broker EnchantBroker; + +namespace WebKit { + +class TextCheckerClientEnchant : public WebCore::TextCheckerClient { + public: + TextCheckerClientEnchant(WebKitWebView*); + ~TextCheckerClientEnchant(); + virtual void ignoreWordInSpellDocument(const WTF::String&); + virtual void learnWord(const WTF::String&); + virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); + virtual WTF::String getAutoCorrectSuggestionForMisspelledWord(const WTF::String&); + virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses); + virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {} + + void updateSpellCheckingLanguage(const char*); + static void freeSpellCheckingLanguage(gpointer, gpointer); + private: + WebKitWebView* m_webView; + GSList* m_enchantDicts; + static EnchantBroker* broker; + }; +} +#endif + |