diff options
Diffstat (limited to 'WebKit/gtk/WebCoreSupport')
-rw-r--r-- | WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp | 2 | ||||
-rw-r--r-- | WebKit/gtk/WebCoreSupport/DragClientGtk.cpp | 48 | ||||
-rw-r--r-- | WebKit/gtk/WebCoreSupport/DragClientGtk.h | 7 | ||||
-rw-r--r-- | WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp | 71 | ||||
-rw-r--r-- | WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp | 142 | ||||
-rw-r--r-- | WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h | 1 | ||||
-rw-r--r-- | WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp | 1 |
7 files changed, 221 insertions, 51 deletions
diff --git a/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp b/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp index 5c1bc0b..069fb19 100644 --- a/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp @@ -62,7 +62,7 @@ static GtkWidget* inputMethodsMenuItem (WebKitWebView* webView) WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView); GtkWidget* imContextMenu = gtk_menu_new(); - gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(priv->imContext), GTK_MENU_SHELL(imContextMenu)); + gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(priv->imContext.get()), GTK_MENU_SHELL(imContextMenu)); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), imContextMenu); diff --git a/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp b/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp index b6075b6..cc75d36 100644 --- a/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp @@ -34,16 +34,30 @@ #include "RenderObject.h" #include "webkitprivate.h" #include "webkitwebview.h" +#include <gdk/gdk.h> #include <gtk/gtk.h> using namespace WebCore; namespace WebKit { +static gboolean dragIconWindowExposeEventCallback(GtkWidget* widget, GdkEventExpose* event, DragClient* client) +{ + client->dragIconWindowExposeEvent(widget, event); + return TRUE; +} + DragClient::DragClient(WebKitWebView* webView) : m_webView(webView) , m_startPos(0, 0) + , m_dragIconWindow(gtk_window_new(GTK_WINDOW_POPUP)) { + g_signal_connect(m_dragIconWindow.get(), "expose-event", G_CALLBACK(dragIconWindowExposeEventCallback), this); +} + +DragClient::~DragClient() +{ + g_signal_handlers_disconnect_by_func(m_dragIconWindow.get(), (gpointer) dragIconWindowExposeEventCallback, this); } void DragClient::willPerformDragDestinationAction(DragDestinationAction, DragData*) @@ -77,18 +91,44 @@ void DragClient::startDrag(DragImageRef image, const IntPoint& dragImageOrigin, GOwnPtr<GdkEvent> currentEvent(gtk_get_current_event()); GdkDragContext* context = gtk_drag_begin(GTK_WIDGET(m_webView), targetList.get(), dragOperationToGdkDragActions(clipboard->sourceOperation()), 1, currentEvent.get()); - webView->priv->draggingDataObjects->set(context, dataObject); + webView->priv->draggingDataObjects.set(context, dataObject); // A drag starting should prevent a double-click from happening. This might // happen if a drag is followed very quickly by another click (like in the DRT). webView->priv->previousClickTime = 0; - if (image) - gtk_drag_set_icon_pixbuf(context, image, eventPos.x() - dragImageOrigin.x(), eventPos.y() - dragImageOrigin.y()); - else + // This strategy originally comes from Chromium: + // src/chrome/browser/gtk/tab_contents_drag_source.cc + if (image) { + m_dragImage = image; + IntSize imageSize(cairo_image_surface_get_width(image), cairo_image_surface_get_height(image)); + gtk_window_resize(GTK_WINDOW(m_dragIconWindow.get()), imageSize.width(), imageSize.height()); + + if (!gtk_widget_get_realized(m_dragIconWindow.get())) { + GdkScreen* screen = gtk_widget_get_screen(m_dragIconWindow.get()); + GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen); + if (rgba) + gtk_widget_set_colormap(m_dragIconWindow.get(), rgba); + } + + IntSize origin = eventPos - dragImageOrigin; + gtk_drag_set_icon_widget(context, m_dragIconWindow.get(), + origin.width(), origin.height()); + } else gtk_drag_set_icon_default(context); } +void DragClient::dragIconWindowExposeEvent(GtkWidget* widget, GdkEventExpose* event) +{ + PlatformRefPtr<cairo_t> context = adoptPlatformRef(gdk_cairo_create(event->window)); + cairo_rectangle(context.get(), 0, 0, + cairo_image_surface_get_width(m_dragImage.get()), + cairo_image_surface_get_height(m_dragImage.get())); + cairo_set_operator(context.get(), CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(context.get(), m_dragImage.get(), 0, 0); + cairo_fill(context.get()); +} + DragImageRef DragClient::createDragImageForLink(KURL&, const String&, Frame*) { notImplemented(); diff --git a/WebKit/gtk/WebCoreSupport/DragClientGtk.h b/WebKit/gtk/WebCoreSupport/DragClientGtk.h index 514852e..2ab7e2d 100644 --- a/WebKit/gtk/WebCoreSupport/DragClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/DragClientGtk.h @@ -31,6 +31,8 @@ #define DragClientGtk_h #include "DragClient.h" +#include "GRefPtr.h" +#include "PlatformRefPtrCairo.h" typedef struct _WebKitWebView WebKitWebView; @@ -39,6 +41,7 @@ namespace WebKit { class DragClient : public WebCore::DragClient { public: DragClient(WebKitWebView*); + ~DragClient(); virtual void willPerformDragDestinationAction(WebCore::DragDestinationAction, WebCore::DragData*); virtual void willPerformDragSourceAction(WebCore::DragSourceAction, const WebCore::IntPoint&, WebCore::Clipboard*); @@ -51,9 +54,13 @@ namespace WebKit { virtual void dragControllerDestroyed(); + void dragIconWindowExposeEvent(GtkWidget*, GdkEventExpose*); + private: WebKitWebView* m_webView; WebCore::IntPoint m_startPos; + PlatformRefPtr<GtkWidget> m_dragIconWindow; + PlatformRefPtr<cairo_surface_t> m_dragImage; }; } diff --git a/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp b/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp index 8a019b4..d4e70b6 100644 --- a/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp @@ -122,6 +122,13 @@ static void pasteClipboardCallback(GtkWidget* widget, EditorClient* client) client->addPendingEditorCommand("Paste"); } +static void toggleOverwriteCallback(GtkWidget* widget, EditorClient* client) +{ + // 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"); +} + static const char* const gtkDeleteCommands[][2] = { { "DeleteBackward", "DeleteForward" }, // Characters { "DeleteWordBackward", "DeleteWordForward" }, // Word ends @@ -229,15 +236,15 @@ void EditorClient::setInputMethodState(bool active) WebKitWebViewPrivate* priv = m_webView->priv; if (active) - gtk_im_context_focus_in(priv->imContext); + gtk_im_context_focus_in(priv->imContext.get()); else - gtk_im_context_focus_out(priv->imContext); + gtk_im_context_focus_out(priv->imContext.get()); #ifdef MAEMO_CHANGES if (active) - hildon_gtk_im_context_show(priv->imContext); + hildon_gtk_im_context_show(priv->imContext.get()); else - hildon_gtk_im_context_hide(priv->imContext); + hildon_gtk_im_context_hide(priv->imContext.get()); #endif } @@ -341,6 +348,31 @@ static void collapseSelection(GtkClipboard* clipboard, WebKitWebView* webView) frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity()); } +#if PLATFORM(X11) +static void setSelectionPrimaryClipboardIfNeeded(WebKitWebView* webView) +{ + if (!gtk_widget_has_screen(GTK_WIDGET(webView))) + return; + + GtkClipboard* clipboard = gtk_widget_get_clipboard(GTK_WIDGET(webView), GDK_SELECTION_PRIMARY); + DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); + WebCore::Page* corePage = core(webView); + Frame* targetFrame = corePage->focusController()->focusedOrMainFrame(); + + if (!targetFrame->selection()->isRange()) + return; + + dataObject->clear(); + dataObject->setRange(targetFrame->selection()->toNormalizedRange()); + + viewSettingClipboard = webView; + GClosure* callback = g_cclosure_new_object(G_CALLBACK(collapseSelection), G_OBJECT(webView)); + g_closure_set_marshal(callback, g_cclosure_marshal_VOID__VOID); + pasteboardHelperInstance()->writeClipboardContents(clipboard, callback); + viewSettingClipboard = 0; +} +#endif + void EditorClient::respondToChangedSelection() { WebKitWebViewPrivate* priv = m_webView->priv; @@ -354,19 +386,7 @@ void EditorClient::respondToChangedSelection() return; #if PLATFORM(X11) - GtkClipboard* clipboard = gtk_widget_get_clipboard(GTK_WIDGET(m_webView), GDK_SELECTION_PRIMARY); - DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); - - if (targetFrame->selection()->isRange()) { - dataObject->clear(); - dataObject->setRange(targetFrame->selection()->toNormalizedRange()); - - viewSettingClipboard = m_webView; - GClosure* callback = g_cclosure_new_object(G_CALLBACK(collapseSelection), G_OBJECT(m_webView)); - g_closure_set_marshal(callback, g_cclosure_marshal_VOID__VOID); - pasteboardHelperInstance()->writeClipboardContents(clipboard, callback); - viewSettingClipboard = 0; - } + setSelectionPrimaryClipboardIfNeeded(m_webView); #endif if (!targetFrame->editor()->hasComposition()) @@ -376,7 +396,7 @@ void EditorClient::respondToChangedSelection() unsigned end; if (!targetFrame->editor()->getCompositionSelection(start, end)) { // gtk_im_context_reset() clears the composition for us. - gtk_im_context_reset(priv->imContext); + gtk_im_context_reset(priv->imContext.get()); targetFrame->editor()->confirmCompositionWithoutDisturbingSelection(); } } @@ -710,7 +730,7 @@ void EditorClient::handleInputMethodKeydown(KeyboardEvent* event) m_treatContextCommitAsKeyEvent = (!targetFrame->editor()->hasComposition()) && event->keyEvent()->gdkEventKey()->keyval; clearPendingComposition(); - if ((gtk_im_context_filter_keypress(priv->imContext, event->keyEvent()->gdkEventKey()) && !m_pendingComposition) + if ((gtk_im_context_filter_keypress(priv->imContext.get(), event->keyEvent()->gdkEventKey()) && !m_pendingComposition) || (!m_treatContextCommitAsKeyEvent && !targetFrame->editor()->hasComposition())) event->preventDefault(); @@ -730,12 +750,12 @@ void EditorClient::handleInputMethodMousePress() // In this case, if the focused node is changed, the commit signal happens in a diffrent node. // Therefore, we need to confirm the current compositon and ignore the next commit signal. GOwnPtr<gchar> newPreedit(0); - gtk_im_context_get_preedit_string(priv->imContext, &newPreedit.outPtr(), 0, 0); + gtk_im_context_get_preedit_string(priv->imContext.get(), &newPreedit.outPtr(), 0, 0); if (g_utf8_strlen(newPreedit.get(), -1)) { targetFrame->editor()->confirmComposition(); m_preventNextCompositionCommit = true; - gtk_im_context_reset(priv->imContext); + gtk_im_context_reset(priv->imContext.get()); } } @@ -747,8 +767,8 @@ EditorClient::EditorClient(WebKitWebView* webView) , m_nativeWidget(gtk_text_view_new()) { WebKitWebViewPrivate* priv = m_webView->priv; - g_signal_connect(priv->imContext, "commit", G_CALLBACK(imContextCommitted), this); - g_signal_connect(priv->imContext, "preedit-changed", G_CALLBACK(imContextPreeditChanged), this); + g_signal_connect(priv->imContext.get(), "commit", G_CALLBACK(imContextCommitted), this); + g_signal_connect(priv->imContext.get(), "preedit-changed", G_CALLBACK(imContextPreeditChanged), this); g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this); g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this); @@ -757,13 +777,14 @@ EditorClient::EditorClient(WebKitWebView* webView) 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); } EditorClient::~EditorClient() { WebKitWebViewPrivate* priv = m_webView->priv; - g_signal_handlers_disconnect_by_func(priv->imContext, (gpointer)imContextCommitted, this); - g_signal_handlers_disconnect_by_func(priv->imContext, (gpointer)imContextPreeditChanged, this); + g_signal_handlers_disconnect_by_func(priv->imContext.get(), (gpointer)imContextCommitted, this); + g_signal_handlers_disconnect_by_func(priv->imContext.get(), (gpointer)imContextPreeditChanged, this); } void EditorClient::textFieldDidBeginEditing(Element*) diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp index 4b0da3d..93b4cc2 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp @@ -49,6 +49,7 @@ #include "MIMETypeRegistry.h" #include "MouseEvent.h" #include "NotImplemented.h" +#include "Page.h" #include "PlatformString.h" #include "PluginDatabase.h" #include "RenderPart.h" @@ -93,9 +94,115 @@ FrameLoaderClient::~FrameLoaderClient() g_object_unref(m_policyDecision); } -String FrameLoaderClient::userAgent(const KURL&) +static void initializeDomainsList(HashSet<String>& googleDomains) +{ + // Google search domains. + googleDomains.add("biz"); + googleDomains.add("com"); + googleDomains.add("net"); + googleDomains.add("org"); + googleDomains.add("ae"); + googleDomains.add("ag"); + googleDomains.add("am"); + googleDomains.add("at"); + googleDomains.add("az"); + googleDomains.add("be"); + googleDomains.add("bi"); + googleDomains.add("ca"); + googleDomains.add("cc"); + googleDomains.add("cd"); + googleDomains.add("cg"); + googleDomains.add("ch"); + googleDomains.add("cl"); + googleDomains.add("com.br"); + googleDomains.add("co.uk"); + googleDomains.add("co.jp"); + googleDomains.add("de"); + googleDomains.add("dj"); + googleDomains.add("dk"); + googleDomains.add("es"); + googleDomains.add("fi"); + googleDomains.add("fm"); + googleDomains.add("fr"); + googleDomains.add("gg"); + googleDomains.add("gl"); + googleDomains.add("gm"); + googleDomains.add("gs"); + googleDomains.add("hn"); + googleDomains.add("hu"); + googleDomains.add("ie"); + googleDomains.add("it"); + googleDomains.add("je"); + googleDomains.add("kz"); + googleDomains.add("li"); + googleDomains.add("lt"); + googleDomains.add("lu"); + googleDomains.add("lv"); + googleDomains.add("ma"); + googleDomains.add("ms"); + googleDomains.add("mu"); + googleDomains.add("mw"); + googleDomains.add("nl"); + googleDomains.add("no"); + googleDomains.add("nu"); + googleDomains.add("pl"); + googleDomains.add("pn"); + googleDomains.add("pt"); + googleDomains.add("ru"); + googleDomains.add("rw"); + googleDomains.add("sh"); + googleDomains.add("sk"); + googleDomains.add("sm"); + googleDomains.add("st"); + googleDomains.add("td"); + googleDomains.add("tk"); + googleDomains.add("tp"); + googleDomains.add("tv"); + googleDomains.add("us"); + googleDomains.add("uz"); + googleDomains.add("ws"); +} + +static bool isGoogleDomain(String host) +{ + DEFINE_STATIC_LOCAL(HashSet<String>, googleDomains, ()); + DEFINE_STATIC_LOCAL(Vector<String>, otherGoogleDomains, ()); + + if (googleDomains.isEmpty()) { + otherGoogleDomains.append("gmail.com"); + otherGoogleDomains.append("youtube.com"); + otherGoogleDomains.append("gstatic.com"); + otherGoogleDomains.append("ytimg.com"); + + initializeDomainsList(googleDomains); + } + + // First check if this is one of the various google.com international domains. + int position = host.find(".google."); + if (position > 0 && googleDomains.contains(host.substring(position + sizeof(".google.")))) + return true; + + // Then we check the possibility of it being one of the other, .com-only google domains. + for (unsigned int i = 0; i < otherGoogleDomains.size(); i++) { + if (host.endsWith(otherGoogleDomains.at(i))) + return true; + } + + return false; +} + +String FrameLoaderClient::userAgent(const KURL& url) { WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame)); + + gboolean useQuirks; + g_object_get(settings, "enable-site-specific-quirks", &useQuirks, NULL); + + // For Google domains, drop the browser's custom User Agent string, and use the standard + // WebKit/Safari one, so they don't give us a broken experience. + if (useQuirks && isGoogleDomain(url.host())) + return webkitUserAgent(); + return String::fromUTF8(webkit_web_settings_get_user_agent(settings)); } @@ -138,26 +245,15 @@ void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunctio (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); } - void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length) { if (!m_pluginView) { ASSERT(loader->frame()); - // Setting the encoding on the frame loader is our way to get work done that is normally done - // when the first bit of data is received, even for the case of a document with no data (like about:blank). - String encoding = loader->overrideEncoding(); - bool userChosen = !encoding.isNull(); - if (!userChosen) - encoding = loader->response().textEncodingName(); - - FrameLoader* frameLoader = loader->frameLoader(); - frameLoader->writer()->setEncoding(encoding, userChosen); - if (data) - frameLoader->addData(data, length); + loader->commitData(data, length); Frame* coreFrame = loader->frame(); - if (coreFrame && coreFrame->document() && coreFrame->document()->isMediaDocument()) - loader->cancelMainResourceLoad(frameLoader->client()->pluginWillHandleLoadError(loader->response())); + if (coreFrame && coreFrame->document()->isMediaDocument()) + loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response())); } if (m_pluginView) { @@ -859,6 +955,12 @@ bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const return true; } +bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const +{ + notImplemented(); + return false; +} + bool FrameLoaderClient::canShowMIMEType(const String& type) const { return (MIMETypeRegistry::isSupportedImageMIMEType(type) @@ -1145,14 +1247,12 @@ static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, boo { WebKitWebView* containingWindow = getViewFromFrame(frame); WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(containingWindow); - view->setGtkAdjustments(priv->horizontalAdjustment, priv->verticalAdjustment, resetValues); + view->setGtkAdjustments(priv->horizontalAdjustment.get(), priv->verticalAdjustment.get(), resetValues); if (priv->currentMenu) { - GtkMenu* menu = priv->currentMenu; - priv->currentMenu = 0; - - gtk_menu_popdown(menu); - g_object_unref(menu); + PlatformRefPtr<GtkMenu> menu(priv->currentMenu); + priv->currentMenu.clear(); + gtk_menu_popdown(menu.get()); } // Do not allow click counting between main frame loads. diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h index 753576b..c5ffc6a 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h @@ -160,6 +160,7 @@ namespace WebKit { virtual bool canHandleRequest(const WebCore::ResourceRequest&) const; virtual bool canShowMIMEType(const WTF::String&) const; + virtual bool canShowMIMETypeAsHTML(const String& MIMEType) const; virtual bool representationExistsForURLScheme(const WTF::String&) const; virtual WTF::String generatedMIMETypeForURLScheme(const WTF::String&) const; diff --git a/WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp b/WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp index c95dcff..cf9a548 100644 --- a/WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp +++ b/WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp @@ -23,6 +23,7 @@ #include "FullscreenVideoController.h" +#include "GtkVersioning.h" #include "MediaPlayer.h" #include <gdk/gdk.h> |