summaryrefslogtreecommitdiffstats
path: root/WebKit/gtk/WebCoreSupport
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/gtk/WebCoreSupport')
-rw-r--r--WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp2
-rw-r--r--WebKit/gtk/WebCoreSupport/DragClientGtk.cpp48
-rw-r--r--WebKit/gtk/WebCoreSupport/DragClientGtk.h7
-rw-r--r--WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp71
-rw-r--r--WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp142
-rw-r--r--WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h1
-rw-r--r--WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp1
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>