2010-12-08 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk>
[WebKit-https.git] / WebKit / gtk / webkit / webkitwebview.cpp
1 /*
2  *  Copyright (C) 2007, 2008 Holger Hans Peter Freyther
3  *  Copyright (C) 2007, 2008, 2009 Christian Dywan <christian@imendio.com>
4  *  Copyright (C) 2007 Xan Lopez <xan@gnome.org>
5  *  Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
6  *  Copyright (C) 2008 Jan Alonzo <jmalonzo@unpluggable.com>
7  *  Copyright (C) 2008 Gustavo Noronha Silva <gns@gnome.org>
8  *  Copyright (C) 2008 Nuanti Ltd.
9  *  Copyright (C) 2008, 2009, 2010 Collabora Ltd.
10  *  Copyright (C) 2009, 2010 Igalia S.L.
11  *  Copyright (C) 2009 Movial Creative Technologies Inc.
12  *  Copyright (C) 2009 Bobby Powers
13  *
14  *  This library is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU Lesser General Public
16  *  License as published by the Free Software Foundation; either
17  *  version 2 of the License, or (at your option) any later version.
18  *
19  *  This library is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  *  Lesser General Public License for more details.
23  *
24  *  You should have received a copy of the GNU Lesser General Public
25  *  License along with this library; if not, write to the Free Software
26  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
27  */
28
29 #include "config.h"
30 #include "webkitwebview.h"
31
32 #include "AXObjectCache.h"
33 #include "AbstractDatabase.h"
34 #include "BackForwardListImpl.h"
35 #include "Chrome.h"
36 #include "ChromeClientGtk.h"
37 #include "ClipboardUtilitiesGtk.h"
38 #include "ContextMenu.h"
39 #include "ContextMenuClientGtk.h"
40 #include "ContextMenuController.h"
41 #include "Cursor.h"
42 #include "Document.h"
43 #include "DocumentLoader.h"
44 #include "DragActions.h"
45 #include "DragClientGtk.h"
46 #include "DragController.h"
47 #include "DragData.h"
48 #include "Editor.h"
49 #include "EditorClientGtk.h"
50 #include "EventHandler.h"
51 #include "FloatQuad.h"
52 #include "FocusController.h"
53 #include "FrameLoader.h"
54 #include "FrameLoaderTypes.h"
55 #include "FrameView.h"
56 #include "GOwnPtrGtk.h"
57 #include "GraphicsContext.h"
58 #include "GtkVersioning.h"
59 #include "HTMLNames.h"
60 #include "HitTestRequest.h"
61 #include "HitTestResult.h"
62 #include "IconDatabase.h"
63 #include "InspectorClientGtk.h"
64 #include "MemoryCache.h"
65 #include "MouseEventWithHitTestResults.h"
66 #include "NotImplemented.h"
67 #include "PageCache.h"
68 #include "Pasteboard.h"
69 #include "PasteboardHelper.h"
70 #include "PasteboardHelperGtk.h"
71 #include "PlatformKeyboardEvent.h"
72 #include "PlatformWheelEvent.h"
73 #include "ProgressTracker.h"
74 #include "RenderView.h"
75 #include "ResourceHandle.h"
76 #include "ScriptValue.h"
77 #include "Scrollbar.h"
78 #include "webkit/WebKitDOMDocumentPrivate.h"
79 #include "webkitdownload.h"
80 #include "webkitenumtypes.h"
81 #include "webkitgeolocationpolicydecision.h"
82 #include "webkitmarshal.h"
83 #include "webkitnetworkrequest.h"
84 #include "webkitnetworkresponse.h"
85 #include "webkitprivate.h"
86 #include "webkitwebbackforwardlist.h"
87 #include "webkitwebhistoryitem.h"
88 #include "webkitwebinspector.h"
89 #include "webkitwebviewprivate.h"
90 #include <gdk/gdkkeysyms.h>
91 #include <glib/gi18n-lib.h>
92 #include <wtf/gobject/GOwnPtr.h>
93 #include <wtf/text/CString.h>
94
95 /**
96  * SECTION:webkitwebview
97  * @short_description: The central class of the WebKitGTK+ API
98  * @see_also: #WebKitWebSettings, #WebKitWebFrame
99  *
100  * #WebKitWebView is the central class of the WebKitGTK+ API. It is a
101  * #GtkWidget implementing the scrolling interface which means you can
102  * embed in a #GtkScrolledWindow. It is responsible for managing the
103  * drawing of the content, forwarding of events. You can load any URI
104  * into the #WebKitWebView or any kind of data string. With #WebKitWebSettings
105  * you can control various aspects of the rendering and loading of the content.
106  * Each #WebKitWebView has exactly one #WebKitWebFrame as main frame. A
107  * #WebKitWebFrame can have n children.
108  *
109  * <programlisting>
110  * /<!-- -->* Create the widgets *<!-- -->/
111  * GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
112  * GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
113  * GtkWidget *web_view = webkit_web_view_new ();
114  *
115  * /<!-- -->* Place the WebKitWebView in the GtkScrolledWindow *<!-- -->/
116  * gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
117  * gtk_container_add (GTK_CONTAINER (main_window), scrolled_window);
118  *
119  * /<!-- -->* Open a webpage *<!-- -->/
120  * webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), "http://www.gnome.org");
121  *
122  * /<!-- -->* Show the result *<!-- -->/
123  * gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);
124  * gtk_widget_show_all (main_window);
125  * </programlisting>
126  */
127
128 static const double defaultDPI = 96.0;
129 static WebKitCacheModel cacheModel = WEBKIT_CACHE_MODEL_DEFAULT;
130 static IntPoint globalPointForClientPoint(GdkWindow* window, const IntPoint& clientPoint);
131
132 using namespace WebKit;
133 using namespace WebCore;
134
135 enum {
136     /* normal signals */
137     NAVIGATION_REQUESTED,
138     NEW_WINDOW_POLICY_DECISION_REQUESTED,
139     NAVIGATION_POLICY_DECISION_REQUESTED,
140     MIME_TYPE_POLICY_DECISION_REQUESTED,
141     CREATE_WEB_VIEW,
142     WEB_VIEW_READY,
143     WINDOW_OBJECT_CLEARED,
144     LOAD_STARTED,
145     LOAD_COMMITTED,
146     LOAD_PROGRESS_CHANGED,
147     LOAD_ERROR,
148     LOAD_FINISHED,
149     TITLE_CHANGED,
150     HOVERING_OVER_LINK,
151     POPULATE_POPUP,
152     STATUS_BAR_TEXT_CHANGED,
153     ICON_LOADED,
154     SELECTION_CHANGED,
155     CONSOLE_MESSAGE,
156     SCRIPT_ALERT,
157     SCRIPT_CONFIRM,
158     SCRIPT_PROMPT,
159     SELECT_ALL,
160     COPY_CLIPBOARD,
161     PASTE_CLIPBOARD,
162     CUT_CLIPBOARD,
163     DOWNLOAD_REQUESTED,
164     MOVE_CURSOR,
165     PRINT_REQUESTED,
166     PLUGIN_WIDGET,
167     CLOSE_WEB_VIEW,
168     UNDO,
169     REDO,
170     DATABASE_QUOTA_EXCEEDED,
171     RESOURCE_REQUEST_STARTING,
172     DOCUMENT_LOAD_FINISHED,
173     GEOLOCATION_POLICY_DECISION_REQUESTED,
174     GEOLOCATION_POLICY_DECISION_CANCELLED,
175     ONLOAD_EVENT,
176     FRAME_CREATED,
177
178     SHOULD_BEGIN_EDITING,
179     SHOULD_END_EDITING,
180     SHOULD_INSERT_NODE,
181     SHOULD_INSERT_TEXT,
182     SHOULD_DELETE_RANGE,
183     SHOULD_SHOW_DELETE_INTERFACE_FOR_ELEMENT,
184     SHOULD_CHANGE_SELECTED_RANGE,
185     SHOULD_APPLY_STYLE,
186     EDITING_BEGAN,
187     USER_CHANGED_CONTENTS,
188     EDITING_ENDED,
189
190     LAST_SIGNAL
191 };
192
193 enum {
194     PROP_0,
195
196     PROP_TITLE,
197     PROP_URI,
198     PROP_COPY_TARGET_LIST,
199     PROP_PASTE_TARGET_LIST,
200     PROP_EDITABLE,
201     PROP_SETTINGS,
202     PROP_WEB_INSPECTOR,
203     PROP_WINDOW_FEATURES,
204     PROP_TRANSPARENT,
205     PROP_ZOOM_LEVEL,
206     PROP_FULL_CONTENT_ZOOM,
207     PROP_LOAD_STATUS,
208     PROP_PROGRESS,
209     PROP_ENCODING,
210     PROP_CUSTOM_ENCODING,
211     PROP_ICON_URI,
212     PROP_IM_CONTEXT,
213 #ifdef GTK_API_VERSION_2
214     PROP_VIEW_MODE
215 #else
216     PROP_VIEW_MODE,
217     PROP_HADJUSTMENT,
218     PROP_VADJUSTMENT,
219     PROP_HSCROLL_POLICY,
220     PROP_VSCROLL_POLICY
221 #endif
222 };
223
224 static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };
225
226 #ifdef GTK_API_VERSION_2
227 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
228 #else
229 G_DEFINE_TYPE_WITH_CODE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER,
230                         G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, 0))
231 #endif
232
233 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView);
234 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures);
235
236 static GtkIMContext* webkit_web_view_get_im_context(WebKitWebView*);
237
238 static void PopupMenuPositionFunc(GtkMenu* menu, gint *x, gint *y, gboolean *pushIn, gpointer userData)
239 {
240     WebKitWebView* view = WEBKIT_WEB_VIEW(userData);
241     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(view);
242     GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(view));
243     GtkRequisition menuSize;
244
245 #ifdef GTK_API_VERSION_2
246     gtk_widget_size_request(GTK_WIDGET(menu), &menuSize);
247 #else
248     gtk_widget_get_preferred_size(GTK_WIDGET(menu), &menuSize, NULL);
249 #endif
250
251     *x = priv->lastPopupXPosition;
252     if ((*x + menuSize.width) >= gdk_screen_get_width(screen))
253       *x -= menuSize.width;
254
255     *y = priv->lastPopupYPosition;
256     if ((*y + menuSize.height) >= gdk_screen_get_height(screen))
257       *y -= menuSize.height;
258
259     *pushIn = FALSE;
260 }
261
262 static Node* getFocusedNode(Frame* frame)
263 {
264     if (Document* doc = frame->document())
265         return doc->focusedNode();
266     return 0;
267 }
268
269 static void contextMenuItemActivated(GtkMenuItem* item, ContextMenuController* controller)
270 {
271     ContextMenuItem contextItem(item);
272     controller->contextMenuItemSelected(&contextItem);
273 }
274
275 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
276 {
277     Page* page = core(webView);
278     page->contextMenuController()->clearContextMenu();
279     Frame* focusedFrame;
280     Frame* mainFrame = page->mainFrame();
281     gboolean mousePressEventResult = FALSE;
282
283     if (!mainFrame->view())
284         return FALSE;
285
286     mainFrame->view()->setCursor(pointerCursor());
287     if (page->frameCount()) {
288         HitTestRequest request(HitTestRequest::Active);
289         IntPoint point = mainFrame->view()->windowToContents(event.pos());
290         MouseEventWithHitTestResults mev = mainFrame->document()->prepareMouseEvent(request, point, event);
291
292         Frame* targetFrame = EventHandler::subframeForTargetNode(mev.targetNode());
293         if (!targetFrame)
294             targetFrame = mainFrame;
295
296         focusedFrame = page->focusController()->focusedOrMainFrame();
297         if (targetFrame != focusedFrame) {
298             page->focusController()->setFocusedFrame(targetFrame);
299             focusedFrame = targetFrame;
300         }
301     } else
302         focusedFrame = mainFrame;
303
304     if (focusedFrame->view() && focusedFrame->eventHandler()->handleMousePressEvent(event))
305         mousePressEventResult = TRUE;
306
307
308     bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
309     if (!handledEvent)
310         return FALSE;
311
312     // If coreMenu is NULL, this means WebCore decided to not create
313     // the default context menu; this may happen when the page is
314     // handling the right-click for reasons other than the context menu.
315     ContextMenuController* controller = page->contextMenuController();
316     ContextMenu* coreMenu = controller->contextMenu();
317     if (!coreMenu)
318         return mousePressEventResult;
319
320     // If we reach here, it's because WebCore is going to show the
321     // default context menu. We check our setting to figure out
322     // whether we want it or not.
323     WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
324     gboolean enableDefaultContextMenu;
325     g_object_get(settings, "enable-default-context-menu", &enableDefaultContextMenu, NULL);
326
327     if (!enableDefaultContextMenu)
328         return FALSE;
329
330     GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
331     if (!menu)
332         return FALSE;
333
334     // We connect the "activate" signal here rather than in ContextMenuGtk to avoid
335     // a layering violation. ContextMenuGtk should not know about the ContextMenuController.
336     // FIXME: This should handle submenu items.
337     GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
338     GList* currentListItem = items.get();
339     while (currentListItem) {
340         GtkMenuItem* item = GTK_MENU_ITEM(currentListItem->data);
341         if (!GTK_IS_SEPARATOR_MENU_ITEM(item) && !gtk_menu_item_get_submenu(item))
342             g_signal_connect(item, "activate", G_CALLBACK(contextMenuItemActivated), controller);
343         currentListItem = currentListItem->next;
344     }
345
346     g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
347
348     // If the context menu is now empty, don't show it.
349     items.set(gtk_container_get_children(GTK_CONTAINER(menu)));
350     if (!items)
351         return FALSE;
352
353     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
354     priv->currentMenu = menu;
355     priv->lastPopupXPosition = event.globalX();
356     priv->lastPopupYPosition = event.globalY();
357
358     gtk_menu_popup(menu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
359     return TRUE;
360 }
361
362 static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
363 {
364     static const int contextMenuMargin = 1;
365
366     // The context menu event was generated from the keyboard, so show the context menu by the current selection.
367     Page* page = core(WEBKIT_WEB_VIEW(widget));
368     Frame* frame = page->focusController()->focusedOrMainFrame();
369     FrameView* view = frame->view();
370     if (!view)
371         return FALSE;    
372
373     Position start = frame->selection()->selection().start();
374     Position end = frame->selection()->selection().end();
375
376     int rightAligned = FALSE;
377     IntPoint location;
378
379     if (!start.node() || !end.node()
380         || (frame->selection()->selection().isCaret() && !frame->selection()->selection().isContentEditable())) {
381         // If there's a focused elment, use its location.
382         if (Node* focusedNode = getFocusedNode(frame)) {
383             IntRect focusedNodeRect = focusedNode->getRect();
384             location = IntPoint(rightAligned ? focusedNodeRect.right() : focusedNodeRect.x(), focusedNodeRect.bottom());
385         } else
386             location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
387     } else {
388         RenderObject* renderer = start.node()->renderer();
389         if (!renderer)
390             return FALSE;
391
392         // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:],
393         // now Frame::firstRectForRange(), which perhaps this should call).
394         int extraWidthToEndOfLine = 0;
395
396         InlineBox* startInlineBox;
397         int startCaretOffset;
398         start.getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
399         IntRect startCaretRect = renderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
400         if (startCaretRect != IntRect())
401             startCaretRect = renderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox();
402
403         InlineBox* endInlineBox;
404         int endCaretOffset;
405         end.getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
406         IntRect endCaretRect = renderer->localCaretRect(endInlineBox, endCaretOffset);
407         if (endCaretRect != IntRect())
408             endCaretRect = renderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox();
409
410         IntRect firstRect;
411         if (startCaretRect.y() == endCaretRect.y())
412             firstRect = IntRect(MIN(startCaretRect.x(), endCaretRect.x()),
413                                 startCaretRect.y(),
414                                 abs(endCaretRect.x() - startCaretRect.x()),
415                                 MAX(startCaretRect.height(), endCaretRect.height()));
416         else
417             firstRect = IntRect(startCaretRect.x(),
418                                 startCaretRect.y(),
419                                 startCaretRect.width() + extraWidthToEndOfLine,
420                                 startCaretRect.height());
421
422         location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
423     }
424
425     // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
426     // Ideally we'd have the position of a context menu event be separate from its target node.
427     location = view->contentsToWindow(location) + IntSize(0, -1);
428     if (location.y() < 0)
429         location.setY(contextMenuMargin);
430     else if (location.y() > view->height())
431         location.setY(view->height() - contextMenuMargin);
432     if (location.x() < 0)
433         location.setX(contextMenuMargin);
434     else if (location.x() > view->width())
435         location.setX(view->width() - contextMenuMargin);
436     IntPoint global(globalPointForClientPoint(gtk_widget_get_window(widget), location));
437
438     PlatformMouseEvent event(location, global, RightButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
439
440     return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
441 }
442
443 #ifndef GTK_API_VERSION_2
444 static void setHorizontalAdjustment(WebKitWebView* webView, GtkAdjustment* adjustment)
445 {
446     if (!core(webView))
447         return;
448
449     webView->priv->horizontalAdjustment = adjustment;
450     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
451     if (!view)
452         return;
453     view->setHorizontalAdjustment(adjustment);
454 }
455
456 static void setVerticalAdjustment(WebKitWebView* webView, GtkAdjustment* adjustment)
457 {
458     if (!core(webView))
459         return;
460
461     webView->priv->verticalAdjustment = adjustment;
462     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
463     if (!view)
464         return;
465     view->setVerticalAdjustment(adjustment);
466 }
467
468 static GtkAdjustment* getHorizontalAdjustment(WebKitWebView* webView)
469 {
470     return webView->priv->horizontalAdjustment.get();
471 }
472
473 static GtkAdjustment* getVerticalAdjustment(WebKitWebView* webView)
474 {
475     return webView->priv->verticalAdjustment.get();
476 }
477
478 static void setHorizontalScrollPolicy(WebKitWebView* webView, GtkScrollablePolicy policy)
479 {
480     webView->priv->horizontalScrollingPolicy = policy;
481     gtk_widget_queue_resize(GTK_WIDGET(webView));
482 }
483
484 static void setVerticalScrollPolicy(WebKitWebView* webView, GtkScrollablePolicy policy)
485 {
486     webView->priv->verticalScrollingPolicy = policy;
487     gtk_widget_queue_resize(GTK_WIDGET(webView));
488 }
489
490 static GtkScrollablePolicy getHorizontalScrollPolicy(WebKitWebView* webView)
491 {
492     return webView->priv->horizontalScrollingPolicy;
493 }
494
495 static GtkScrollablePolicy getVerticalScrollPolicy(WebKitWebView* webView)
496 {
497     return webView->priv->verticalScrollingPolicy;
498 }
499
500 #endif
501
502 static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
503 {
504     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
505
506     switch(prop_id) {
507     case PROP_TITLE:
508         g_value_set_string(value, webkit_web_view_get_title(webView));
509         break;
510     case PROP_URI:
511         g_value_set_string(value, webkit_web_view_get_uri(webView));
512         break;
513     case PROP_COPY_TARGET_LIST:
514         g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView));
515         break;
516     case PROP_PASTE_TARGET_LIST:
517         g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView));
518         break;
519     case PROP_EDITABLE:
520         g_value_set_boolean(value, webkit_web_view_get_editable(webView));
521         break;
522     case PROP_SETTINGS:
523         g_value_set_object(value, webkit_web_view_get_settings(webView));
524         break;
525     case PROP_WEB_INSPECTOR:
526         g_value_set_object(value, webkit_web_view_get_inspector(webView));
527         break;
528     case PROP_WINDOW_FEATURES:
529         g_value_set_object(value, webkit_web_view_get_window_features(webView));
530         break;
531     case PROP_TRANSPARENT:
532         g_value_set_boolean(value, webkit_web_view_get_transparent(webView));
533         break;
534     case PROP_ZOOM_LEVEL:
535         g_value_set_float(value, webkit_web_view_get_zoom_level(webView));
536         break;
537     case PROP_FULL_CONTENT_ZOOM:
538         g_value_set_boolean(value, webkit_web_view_get_full_content_zoom(webView));
539         break;
540     case PROP_ENCODING:
541         g_value_set_string(value, webkit_web_view_get_encoding(webView));
542         break;
543     case PROP_CUSTOM_ENCODING:
544         g_value_set_string(value, webkit_web_view_get_custom_encoding(webView));
545         break;
546     case PROP_LOAD_STATUS:
547         g_value_set_enum(value, webkit_web_view_get_load_status(webView));
548         break;
549     case PROP_PROGRESS:
550         g_value_set_double(value, webkit_web_view_get_progress(webView));
551         break;
552     case PROP_ICON_URI:
553         g_value_set_string(value, webkit_web_view_get_icon_uri(webView));
554         break;
555     case PROP_IM_CONTEXT:
556         g_value_set_object(value, webkit_web_view_get_im_context(webView));
557         break;
558     case PROP_VIEW_MODE:
559         g_value_set_enum(value, webkit_web_view_get_view_mode(webView));
560         break;
561 #ifndef GTK_API_VERSION_2
562     case PROP_HADJUSTMENT:
563         g_value_set_object(value, getHorizontalAdjustment(webView));
564         break;
565     case PROP_VADJUSTMENT:
566         g_value_set_object(value, getVerticalAdjustment(webView));
567         break;
568     case PROP_HSCROLL_POLICY:
569         g_value_set_enum(value, getHorizontalScrollPolicy(webView));
570         break;
571     case PROP_VSCROLL_POLICY:
572         g_value_set_enum(value, getVerticalScrollPolicy(webView));
573         break;
574 #endif
575     default:
576         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
577     }
578 }
579
580 static void webkit_web_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec)
581 {
582     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
583
584     switch(prop_id) {
585     case PROP_EDITABLE:
586         webkit_web_view_set_editable(webView, g_value_get_boolean(value));
587         break;
588     case PROP_SETTINGS:
589         webkit_web_view_set_settings(webView, WEBKIT_WEB_SETTINGS(g_value_get_object(value)));
590         break;
591     case PROP_WINDOW_FEATURES:
592         webkit_web_view_set_window_features(webView, WEBKIT_WEB_WINDOW_FEATURES(g_value_get_object(value)));
593         break;
594     case PROP_TRANSPARENT:
595         webkit_web_view_set_transparent(webView, g_value_get_boolean(value));
596         break;
597     case PROP_ZOOM_LEVEL:
598         webkit_web_view_set_zoom_level(webView, g_value_get_float(value));
599         break;
600     case PROP_FULL_CONTENT_ZOOM:
601         webkit_web_view_set_full_content_zoom(webView, g_value_get_boolean(value));
602         break;
603     case PROP_CUSTOM_ENCODING:
604         webkit_web_view_set_custom_encoding(webView, g_value_get_string(value));
605         break;
606     case PROP_VIEW_MODE:
607         webkit_web_view_set_view_mode(webView, static_cast<WebKitWebViewViewMode>(g_value_get_enum(value)));
608         break;
609 #ifndef GTK_API_VERSION_2
610     case PROP_HADJUSTMENT:
611         setHorizontalAdjustment(webView, static_cast<GtkAdjustment*>(g_value_get_object(value)));
612         break;
613     case PROP_VADJUSTMENT:
614         setVerticalAdjustment(webView, static_cast<GtkAdjustment*>(g_value_get_object(value)));
615         break;
616     case PROP_HSCROLL_POLICY:
617         setHorizontalScrollPolicy(webView, static_cast<GtkScrollablePolicy>(g_value_get_enum(value)));
618         break;
619     case PROP_VSCROLL_POLICY:
620         setVerticalScrollPolicy(webView, static_cast<GtkScrollablePolicy>(g_value_get_enum(value)));
621         break;
622 #endif
623     default:
624         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
625     }
626 }
627
628 static bool shouldCoalesce(const IntRect& rect, const Vector<IntRect>& rects)
629 {
630     const unsigned int cRectThreshold = 10;
631     const float cWastedSpaceThreshold = 0.75f;
632     bool useUnionedRect = (rects.size() <= 1) || (rects.size() > cRectThreshold);
633     if (useUnionedRect)
634         return true;
635     // Attempt to guess whether or not we should use the unioned rect or the individual rects.
636     // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
637     // is too large, then we will do individual rect painting instead.
638     float unionPixels = (rect.width() * rect.height());
639     float singlePixels = 0;
640     for (size_t i = 0; i < rects.size(); ++i)
641         singlePixels += rects[i].width() * rects[i].height();
642     float wastedSpace = 1 - (singlePixels / unionPixels);
643     if (wastedSpace <= cWastedSpaceThreshold)
644         useUnionedRect = true;
645     return useUnionedRect;
646 }
647
648 static void paintWebView(Frame* frame, gboolean transparent, GraphicsContext& context, const IntRect& clipRect, const Vector<IntRect>& rects)
649 {
650     bool coalesce = true;
651
652     if (rects.size() > 0)
653         coalesce = shouldCoalesce(clipRect, rects);
654
655     if (coalesce) {
656         context.clip(clipRect);
657         if (transparent)
658             context.clearRect(clipRect);
659         frame->view()->paint(&context, clipRect);
660     } else {
661         for (size_t i = 0; i < rects.size(); i++) {
662             IntRect rect = rects[i];
663             context.save();
664             context.clip(rect);
665             if (transparent)
666                 context.clearRect(rect);
667             frame->view()->paint(&context, rect);
668             context.restore();
669         }
670     }
671
672     context.save();
673     context.clip(clipRect);
674     frame->page()->inspectorController()->drawNodeHighlight(context);
675     context.restore();
676 }
677 #ifdef GTK_API_VERSION_2
678 static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
679 {
680     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
681     WebKitWebViewPrivate* priv = webView->priv;
682
683     Frame* frame = core(webView)->mainFrame();
684     if (frame->contentRenderer() && frame->view()) {
685         frame->view()->updateLayoutAndStyleIfNeededRecursive();
686
687         cairo_t* cr = gdk_cairo_create(event->window);
688         GraphicsContext ctx(cr);
689         cairo_destroy(cr);
690         ctx.setGdkExposeEvent(event);
691
692         int rectCount;
693         GOwnPtr<GdkRectangle> rects;
694         gdk_region_get_rectangles(event->region, &rects.outPtr(), &rectCount);
695         Vector<IntRect> paintRects;
696         for (int i = 0; i < rectCount; i++)
697             paintRects.append(IntRect(rects.get()[i]));
698
699         paintWebView(frame, priv->transparent, ctx, static_cast<IntRect>(event->area), paintRects);
700     }
701
702     return FALSE;
703 }
704 #else
705 static gboolean webkit_web_view_draw(GtkWidget* widget, cairo_t* cr)
706 {
707     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
708     WebKitWebViewPrivate* priv = webView->priv;
709     GdkRectangle clipRect;
710
711     if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
712         return FALSE;
713
714     Frame* frame = core(webView)->mainFrame();
715     if (frame->contentRenderer() && frame->view()) {
716         GraphicsContext ctx(cr);
717         IntRect rect = clipRect;
718         cairo_rectangle_list_t* rectList = cairo_copy_clip_rectangle_list(cr);
719
720         frame->view()->updateLayoutAndStyleIfNeededRecursive();
721
722         Vector<IntRect> rects;
723         if (!rectList->status && rectList->num_rectangles > 0) {
724             for (int i = 0; i < rectList->num_rectangles; i++)
725                 rects.append(enclosingIntRect(FloatRect(rectList->rectangles[i])));
726         }
727         paintWebView(frame, priv->transparent, ctx, rect, rects);
728
729         cairo_rectangle_list_destroy(rectList);
730     }
731
732     return FALSE;
733 }
734 #endif // GTK_API_VERSION_2
735
736 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event)
737 {
738     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
739
740     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
741     PlatformKeyboardEvent keyboardEvent(event);
742
743     if (!frame->view())
744         return FALSE;
745
746     if (frame->eventHandler()->keyEvent(keyboardEvent))
747         return TRUE;
748
749     /* Chain up to our parent class for binding activation */
750     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event);
751 }
752
753 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event)
754 {
755     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
756
757     // GTK+ IM contexts often require us to filter key release events, which
758     // WebCore does not do by default, so we filter the event here. We only block
759     // the event if we don't have a pending composition, because that means we
760     // are using a context like 'simple' which marks every keystroke as filtered.
761     WebKit::EditorClient* client = static_cast<WebKit::EditorClient*>(core(webView)->editorClient());
762     if (gtk_im_context_filter_keypress(webView->priv->imContext.get(), event) && !client->hasPendingComposition())
763         return TRUE;
764
765     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
766     if (!frame->view())
767         return FALSE;
768
769     PlatformKeyboardEvent keyboardEvent(event);
770     if (frame->eventHandler()->keyEvent(keyboardEvent))
771         return TRUE;
772
773     /* Chain up to our parent class for binding activation */
774     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event);
775 }
776
777 static guint32 getEventTime(GdkEvent* event)
778 {
779     guint32 time = gdk_event_get_time(event);
780     if (time)
781         return time;
782
783     // Real events always have a non-zero time, but events synthesized
784     // by the DRT do not and we must calculate a time manually. This time
785     // is not calculated in the DRT, because GTK+ does not work well with
786     // anything other than GDK_CURRENT_TIME on synthesized events.
787     GTimeVal timeValue;
788     g_get_current_time(&timeValue);
789     return (timeValue.tv_sec * 1000) + (timeValue.tv_usec / 1000);
790
791
792 static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventButton* event)
793 {
794     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
795     WebKitWebViewPrivate* priv = webView->priv;
796
797     // FIXME: need to keep track of subframe focus for key events
798     gtk_widget_grab_focus(widget);
799
800     // For double and triple clicks GDK sends both a normal button press event
801     // and a specific type (like GDK_2BUTTON_PRESS). If we detect a special press
802     // coming up, ignore this event as it certainly generated the double or triple
803     // click. The consequence of not eating this event is two DOM button press events
804     // are generated.
805     GOwnPtr<GdkEvent> nextEvent(gdk_event_peek());
806     if (nextEvent && (nextEvent->any.type == GDK_2BUTTON_PRESS || nextEvent->any.type == GDK_3BUTTON_PRESS))
807         return TRUE;
808
809     gint doubleClickDistance = 250;
810     gint doubleClickTime = 5;
811     GtkSettings* settings = gtk_settings_get_for_screen(gtk_widget_get_screen(widget));
812     g_object_get(settings, 
813         "gtk-double-click-distance", &doubleClickDistance,
814         "gtk-double-click-time", &doubleClickTime, NULL);
815
816     // GTK+ only counts up to triple clicks, but WebCore wants to know about
817     // quadruple clicks, quintuple clicks, ad infinitum. Here, we replicate the
818     // GDK logic for counting clicks.
819     guint32 eventTime = getEventTime(reinterpret_cast<GdkEvent*>(event));
820     if ((event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
821         || ((abs(event->x - priv->previousClickPoint.x()) < doubleClickDistance)
822             && (abs(event->y - priv->previousClickPoint.y()) < doubleClickDistance)
823             && (eventTime - priv->previousClickTime < static_cast<guint>(doubleClickTime))
824             && (event->button == priv->previousClickButton)))
825         priv->currentClickCount++;
826     else
827         priv->currentClickCount = 1;
828
829     PlatformMouseEvent platformEvent(event);
830     platformEvent.setClickCount(priv->currentClickCount);
831     priv->previousClickPoint = platformEvent.pos();
832     priv->previousClickButton = event->button;
833     priv->previousClickTime = eventTime;
834
835     if (event->button == 3)
836         return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
837
838     Frame* frame = core(webView)->mainFrame();
839     if (!frame->view())
840         return FALSE;
841
842     gboolean result = frame->eventHandler()->handleMousePressEvent(platformEvent);
843     // Handle the IM context when a mouse press fires
844     static_cast<WebKit::EditorClient*>(core(webView)->editorClient())->handleInputMethodMousePress();
845
846 #if PLATFORM(X11)
847     /* Copy selection to the X11 selection clipboard */
848     if (event->button == 2) {
849         bool primary = webView->priv->usePrimaryForPaste;
850         webView->priv->usePrimaryForPaste = true;
851
852         Editor* editor = webView->priv->corePage->focusController()->focusedOrMainFrame()->editor();
853         result = result || editor->canPaste() || editor->canDHTMLPaste();
854         editor->paste();
855
856         webView->priv->usePrimaryForPaste = primary;
857     }
858 #endif
859
860     return result;
861 }
862
863 static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEventButton* event)
864 {
865     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
866
867     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
868
869     if (focusedFrame && focusedFrame->editor()->canEdit()) {
870 #ifdef MAEMO_CHANGES
871         WebKitWebViewPrivate* priv = webView->priv;
872         hildon_gtk_im_context_filter_event(priv->imContext.get(), (GdkEvent*)event);
873 #endif
874     }
875
876     Frame* mainFrame = core(webView)->mainFrame();
877     if (mainFrame->view())
878         mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
879
880     /* We always return FALSE here because WebKit can, for the same click, decide
881      * to not handle press-event but handle release-event, which can totally confuse
882      * some GTK+ containers when there are no other events in between. This way we
883      * guarantee that this case never happens, and that if press-event goes through
884      * release-event also goes through.
885      */
886
887     return FALSE;
888 }
889
890 static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event)
891 {
892     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
893
894     Frame* frame = core(webView)->mainFrame();
895     if (!frame->view())
896         return FALSE;
897
898     return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
899 }
900
901 static gboolean webkit_web_view_scroll_event(GtkWidget* widget, GdkEventScroll* event)
902 {
903     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
904
905     Frame* frame = core(webView)->mainFrame();
906     if (!frame->view())
907         return FALSE;
908
909     PlatformWheelEvent wheelEvent(event);
910     return frame->eventHandler()->handleWheelEvent(wheelEvent);
911 }
912
913 #ifdef GTK_API_VERSION_2
914 static void webkit_web_view_size_request(GtkWidget* widget, GtkRequisition* requisition)
915 {
916     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
917     Frame* coreFrame = core(webkit_web_view_get_main_frame(web_view));
918     if (!coreFrame)
919         return;
920
921     FrameView* view = coreFrame->view();
922     if (!view)
923         return;
924
925     requisition->width = view->contentsWidth();
926     requisition->height = view->contentsHeight();
927 }
928 #else
929 static void webkit_web_view_get_preferred_width(GtkWidget* widget, gint* minimum, gint* natural)
930 {
931     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
932     Frame* coreFrame = core(webkit_web_view_get_main_frame(web_view));
933     if (!coreFrame)
934         return;
935
936     FrameView* view = coreFrame->view();
937     if (!view)
938         return;
939
940     *minimum = *natural = view->contentsWidth();
941 }
942
943 static void webkit_web_view_get_preferred_height(GtkWidget* widget, gint* minimum, gint* natural)
944 {
945     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
946     Frame* coreFrame = core(webkit_web_view_get_main_frame(web_view));
947     if (!coreFrame)
948         return;
949
950     FrameView* view = coreFrame->view();
951     if (!view)
952         return;
953
954     *minimum = *natural = view->contentsHeight();
955 }
956 #endif
957
958 static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
959 {
960     GTK_WIDGET_CLASS(webkit_web_view_parent_class)->size_allocate(widget,allocation);
961
962     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
963
964     Frame* frame = core(webView)->mainFrame();
965     if (!frame->view())
966         return;
967
968     frame->view()->resize(allocation->width, allocation->height);
969 }
970
971 static void webkit_web_view_grab_focus(GtkWidget* widget)
972 {
973
974     if (gtk_widget_is_sensitive(widget)) {
975         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
976         FocusController* focusController = core(webView)->focusController();
977
978         focusController->setActive(true);
979
980         if (focusController->focusedFrame())
981             focusController->setFocused(true);
982         else
983             focusController->setFocusedFrame(core(webView)->mainFrame());
984     }
985
986     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->grab_focus(widget);
987 }
988
989 static gboolean webkit_web_view_focus_in_event(GtkWidget* widget, GdkEventFocus* event)
990 {
991     // TODO: Improve focus handling as suggested in
992     // http://bugs.webkit.org/show_bug.cgi?id=16910
993     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
994     if (gtk_widget_is_toplevel(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {
995         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
996         FocusController* focusController = core(webView)->focusController();
997
998         focusController->setActive(true);
999
1000         if (focusController->focusedFrame())
1001             focusController->setFocused(true);
1002         else
1003             focusController->setFocusedFrame(core(webView)->mainFrame());
1004
1005         if (focusController->focusedFrame()->editor()->canEdit())
1006             gtk_im_context_focus_in(webView->priv->imContext.get());
1007     }
1008     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event);
1009 }
1010
1011 static gboolean webkit_web_view_focus_out_event(GtkWidget* widget, GdkEventFocus* event)
1012 {
1013     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1014
1015     // We may hit this code while destroying the widget, and we might
1016     // no longer have a page, then.
1017     Page* page = core(webView);
1018     if (page) {
1019         page->focusController()->setActive(false);
1020         page->focusController()->setFocused(false);
1021     }
1022
1023     if (webView->priv->imContext)
1024         gtk_im_context_focus_out(webView->priv->imContext.get());
1025
1026     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_out_event(widget, event);
1027 }
1028
1029 static void webkit_web_view_realize(GtkWidget* widget)
1030 {
1031     gtk_widget_set_realized(widget, TRUE);
1032
1033     GtkAllocation allocation;
1034 #if GTK_CHECK_VERSION(2, 18, 0)
1035     gtk_widget_get_allocation(widget, &allocation);
1036 #else
1037     allocation = widget->allocation;
1038 #endif
1039
1040     GdkWindowAttr attributes;
1041     attributes.window_type = GDK_WINDOW_CHILD;
1042     attributes.x = allocation.x;
1043     attributes.y = allocation.y;
1044     attributes.width = allocation.width;
1045     attributes.height = allocation.height;
1046     attributes.wclass = GDK_INPUT_OUTPUT;
1047     attributes.visual = gtk_widget_get_visual(widget);
1048 #ifdef GTK_API_VERSION_2
1049     attributes.colormap = gtk_widget_get_colormap(widget);
1050 #endif
1051     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
1052                             | GDK_EXPOSURE_MASK
1053                             | GDK_BUTTON_PRESS_MASK
1054                             | GDK_BUTTON_RELEASE_MASK
1055                             | GDK_POINTER_MOTION_MASK
1056                             | GDK_KEY_PRESS_MASK
1057                             | GDK_KEY_RELEASE_MASK
1058                             | GDK_BUTTON_MOTION_MASK
1059                             | GDK_BUTTON1_MOTION_MASK
1060                             | GDK_BUTTON2_MOTION_MASK
1061                             | GDK_BUTTON3_MOTION_MASK;
1062
1063     gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
1064 #ifdef GTK_API_VERSION_2
1065     attributes_mask |= GDK_WA_COLORMAP;
1066 #endif
1067     GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask);
1068     gtk_widget_set_window(widget, window);
1069     gdk_window_set_user_data(window, widget);
1070
1071 #if GTK_CHECK_VERSION(2, 20, 0)
1072     gtk_widget_style_attach(widget);
1073 #else
1074     widget->style = gtk_style_attach(gtk_widget_get_style(widget), window);
1075 #endif
1076     gtk_style_set_background(gtk_widget_get_style(widget), window, GTK_STATE_NORMAL);
1077
1078     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1079     WebKitWebViewPrivate* priv = webView->priv;
1080     gtk_im_context_set_client_window(priv->imContext.get(), window);
1081 }
1082
1083 #ifdef GTK_API_VERSION_2
1084 static void webkit_web_view_set_scroll_adjustments(WebKitWebView* webView, GtkAdjustment* hadj, GtkAdjustment* vadj)
1085 {
1086     if (!core(webView))
1087         return;
1088
1089     webView->priv->horizontalAdjustment = hadj;
1090     webView->priv->verticalAdjustment = vadj;
1091
1092     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
1093     if (!view)
1094         return;
1095     view->setGtkAdjustments(hadj, vadj);
1096 }
1097 #endif
1098
1099 static void webkit_web_view_container_add(GtkContainer* container, GtkWidget* widget)
1100 {
1101     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
1102     WebKitWebViewPrivate* priv = webView->priv;
1103
1104     priv->children.add(widget);
1105     gtk_widget_set_parent(widget, GTK_WIDGET(container));
1106 }
1107
1108 static void webkit_web_view_container_remove(GtkContainer* container, GtkWidget* widget)
1109 {
1110     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
1111     WebKitWebViewPrivate* priv = webView->priv;
1112
1113     if (priv->children.contains(widget)) {
1114         gtk_widget_unparent(widget);
1115         priv->children.remove(widget);
1116     }
1117 }
1118
1119 static void webkit_web_view_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
1120 {
1121     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
1122     WebKitWebViewPrivate* priv = webView->priv;
1123
1124     HashSet<GtkWidget*> children = priv->children;
1125     HashSet<GtkWidget*>::const_iterator end = children.end();
1126     for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
1127         (*callback)(*current, callbackData);
1128 }
1129
1130 static WebKitWebView* webkit_web_view_real_create_web_view(WebKitWebView*, WebKitWebFrame*)
1131 {
1132     return 0;
1133 }
1134
1135 static gboolean webkit_web_view_real_web_view_ready(WebKitWebView*)
1136 {
1137     return FALSE;
1138 }
1139
1140 static gboolean webkit_web_view_real_close_web_view(WebKitWebView*)
1141 {
1142     return FALSE;
1143 }
1144
1145 static WebKitNavigationResponse webkit_web_view_real_navigation_requested(WebKitWebView*, WebKitWebFrame*, WebKitNetworkRequest*)
1146 {
1147     return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
1148 }
1149
1150 static void webkit_web_view_real_window_object_cleared(WebKitWebView*, WebKitWebFrame*, JSGlobalContextRef context, JSObjectRef window_object)
1151 {
1152     notImplemented();
1153 }
1154
1155 static gchar* webkit_web_view_real_choose_file(WebKitWebView*, WebKitWebFrame*, const gchar* old_name)
1156 {
1157     notImplemented();
1158     return g_strdup(old_name);
1159 }
1160
1161 typedef enum {
1162     WEBKIT_SCRIPT_DIALOG_ALERT,
1163     WEBKIT_SCRIPT_DIALOG_CONFIRM,
1164     WEBKIT_SCRIPT_DIALOG_PROMPT
1165  } WebKitScriptDialogType;
1166
1167 static gboolean webkit_web_view_script_dialog(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
1168 {
1169     GtkMessageType messageType;
1170     GtkButtonsType buttons;
1171     gint defaultResponse;
1172     GtkWidget* window;
1173     GtkWidget* dialog;
1174     GtkWidget* entry = 0;
1175     gboolean didConfirm = FALSE;
1176
1177     switch (type) {
1178     case WEBKIT_SCRIPT_DIALOG_ALERT:
1179         messageType = GTK_MESSAGE_WARNING;
1180         buttons = GTK_BUTTONS_CLOSE;
1181         defaultResponse = GTK_RESPONSE_CLOSE;
1182         break;
1183     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
1184         messageType = GTK_MESSAGE_QUESTION;
1185         buttons = GTK_BUTTONS_OK_CANCEL;
1186         defaultResponse = GTK_RESPONSE_OK;
1187         break;
1188     case WEBKIT_SCRIPT_DIALOG_PROMPT:
1189         messageType = GTK_MESSAGE_QUESTION;
1190         buttons = GTK_BUTTONS_OK_CANCEL;
1191         defaultResponse = GTK_RESPONSE_OK;
1192         break;
1193     default:
1194         g_warning("Unknown value for WebKitScriptDialogType.");
1195         return FALSE;
1196     }
1197
1198     window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
1199     dialog = gtk_message_dialog_new(gtk_widget_is_toplevel(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
1200     gchar* title = g_strconcat("JavaScript - ", webkit_web_frame_get_uri(frame), NULL);
1201     gtk_window_set_title(GTK_WINDOW(dialog), title);
1202     g_free(title);
1203
1204     if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
1205         entry = gtk_entry_new();
1206         gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
1207         gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
1208         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
1209         gtk_widget_show(entry);
1210     }
1211
1212     gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
1213     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
1214
1215     switch (response) {
1216     case GTK_RESPONSE_OK:
1217         didConfirm = TRUE;
1218         if (entry)
1219             *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1220         break;
1221     case GTK_RESPONSE_CANCEL:
1222         didConfirm = FALSE;
1223         break;
1224
1225     }
1226     gtk_widget_destroy(GTK_WIDGET(dialog));
1227     return didConfirm;
1228 }
1229
1230 static gboolean webkit_web_view_real_script_alert(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message)
1231 {
1232     webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
1233     return TRUE;
1234 }
1235
1236 static gboolean webkit_web_view_real_script_confirm(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm)
1237 {
1238     *didConfirm = webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
1239     return TRUE;
1240 }
1241
1242 static gboolean webkit_web_view_real_script_prompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
1243 {
1244     if (!webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
1245         *value = NULL;
1246     return TRUE;
1247 }
1248
1249 static gboolean webkit_web_view_real_console_message(WebKitWebView* webView, const gchar* message, unsigned int line, const gchar* sourceId)
1250 {
1251     g_message("console message: %s @%d: %s\n", sourceId, line, message);
1252     return TRUE;
1253 }
1254
1255 static void webkit_web_view_real_select_all(WebKitWebView* webView)
1256 {
1257     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1258     frame->editor()->command("SelectAll").execute();
1259 }
1260
1261 static void webkit_web_view_real_cut_clipboard(WebKitWebView* webView)
1262 {
1263     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1264     frame->editor()->command("Cut").execute();
1265 }
1266
1267 static void webkit_web_view_real_copy_clipboard(WebKitWebView* webView)
1268 {
1269     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1270     frame->editor()->command("Copy").execute();
1271 }
1272
1273 static void webkit_web_view_real_undo(WebKitWebView* webView)
1274 {
1275     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1276     frame->editor()->command("Undo").execute();
1277 }
1278
1279 static void webkit_web_view_real_redo(WebKitWebView* webView)
1280 {
1281     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1282     frame->editor()->command("Redo").execute();
1283 }
1284
1285 static gboolean webkit_web_view_real_move_cursor (WebKitWebView* webView, GtkMovementStep step, gint count)
1286 {
1287     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW (webView), FALSE);
1288     g_return_val_if_fail(step == GTK_MOVEMENT_VISUAL_POSITIONS ||
1289                          step == GTK_MOVEMENT_DISPLAY_LINES ||
1290                          step == GTK_MOVEMENT_PAGES ||
1291                          step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
1292     g_return_val_if_fail(count == 1 || count == -1, FALSE);
1293
1294     ScrollDirection direction;
1295     ScrollGranularity granularity;
1296
1297     switch (step) {
1298     case GTK_MOVEMENT_DISPLAY_LINES:
1299         granularity = ScrollByLine;
1300         if (count == 1)
1301             direction = ScrollDown;
1302         else
1303             direction = ScrollUp;
1304         break;
1305     case GTK_MOVEMENT_VISUAL_POSITIONS:
1306         granularity = ScrollByLine;
1307         if (count == 1)
1308             direction = ScrollRight;
1309         else
1310             direction = ScrollLeft;
1311         break;
1312     case GTK_MOVEMENT_PAGES:
1313         granularity = ScrollByPage;
1314         if (count == 1)
1315             direction = ScrollDown;
1316         else
1317             direction = ScrollUp;
1318         break;
1319     case GTK_MOVEMENT_BUFFER_ENDS:
1320         granularity = ScrollByDocument;
1321         if (count == 1)
1322             direction = ScrollDown;
1323         else
1324             direction = ScrollUp;
1325         break;
1326     default:
1327         g_assert_not_reached();
1328         return false;
1329     }
1330
1331     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1332     if (!frame->eventHandler()->scrollOverflow(direction, granularity))
1333         frame->view()->scroll(direction, granularity);
1334
1335     return true;
1336 }
1337
1338 static void webkit_web_view_real_paste_clipboard(WebKitWebView* webView)
1339 {
1340     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1341     frame->editor()->command("Paste").execute();
1342 }
1343
1344 static gboolean webkit_web_view_real_should_allow_editing_action(WebKitWebView*)
1345 {
1346     return TRUE;
1347 }
1348
1349 static void webkit_web_view_dispose(GObject* object)
1350 {
1351     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
1352     WebKitWebViewPrivate* priv = webView->priv;
1353
1354     priv->disposing = TRUE;
1355
1356     // These smart pointers are cleared manually, because some cleanup operations are
1357     // very sensitive to their value. We may crash if these are done in the wrong order.
1358     priv->horizontalAdjustment.clear();
1359     priv->verticalAdjustment.clear();
1360     priv->backForwardList.clear();
1361
1362     if (priv->corePage) {
1363         webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object));
1364         core(priv->mainFrame)->loader()->detachFromParent();
1365         delete priv->corePage;
1366         priv->corePage = 0;
1367     }
1368
1369     if (priv->webSettings) {
1370         g_signal_handlers_disconnect_by_func(priv->webSettings.get(), (gpointer)webkit_web_view_settings_notify, webView);
1371         priv->webSettings.clear();
1372     }
1373
1374     priv->webInspector.clear();
1375     priv->webWindowFeatures.clear();
1376     priv->mainResource.clear();
1377     priv->subResources.clear();
1378
1379     HashMap<GdkDragContext*, DroppingContext*>::iterator endDroppingContexts = priv->droppingContexts.end();
1380     for (HashMap<GdkDragContext*, DroppingContext*>::iterator iter = priv->droppingContexts.begin(); iter != endDroppingContexts; ++iter)
1381         delete (iter->second);
1382     priv->droppingContexts.clear();
1383
1384     G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object);
1385 }
1386
1387 static void webkit_web_view_finalize(GObject* object)
1388 {
1389     // We need to manually call the destructor here, since this object's memory is managed
1390     // by GLib. This calls all C++ members' destructors and prevents memory leaks.
1391     WEBKIT_WEB_VIEW(object)->priv->~WebKitWebViewPrivate();
1392     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
1393 }
1394
1395 static gboolean webkit_signal_accumulator_object_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
1396 {
1397     gpointer newWebView = g_value_get_object(handlerReturn);
1398     g_value_set_object(returnAccu, newWebView);
1399
1400     // Continue if we don't have a newWebView
1401     return !newWebView;
1402 }
1403
1404 static gboolean webkit_navigation_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
1405 {
1406     WebKitNavigationResponse navigationResponse = (WebKitNavigationResponse)g_value_get_enum(handlerReturn);
1407     g_value_set_enum(returnAccu, navigationResponse);
1408
1409     if (navigationResponse != WEBKIT_NAVIGATION_RESPONSE_ACCEPT)
1410         return FALSE;
1411
1412     return TRUE;
1413 }
1414
1415 static AtkObject* webkit_web_view_get_accessible(GtkWidget* widget)
1416 {
1417     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1418     if (!core(webView))
1419         return NULL;
1420
1421     AXObjectCache::enableAccessibility();
1422
1423     Frame* coreFrame = core(webView)->mainFrame();
1424     if (!coreFrame)
1425         return NULL;
1426
1427     Document* doc = coreFrame->document();
1428     if (!doc)
1429         return NULL;
1430
1431     AccessibilityObject* coreAccessible = doc->axObjectCache()->getOrCreate(doc->renderer());
1432     if (!coreAccessible || !coreAccessible->wrapper())
1433         return NULL;
1434
1435     return coreAccessible->wrapper();
1436 }
1437
1438 static gdouble webViewGetDPI(WebKitWebView* webView)
1439 {
1440     WebKitWebViewPrivate* priv = webView->priv;
1441     WebKitWebSettings* webSettings = priv->webSettings.get();
1442     gboolean enforce96DPI;
1443     g_object_get(webSettings, "enforce-96-dpi", &enforce96DPI, NULL);
1444     if (enforce96DPI)
1445         return 96.0;
1446
1447     gdouble DPI = defaultDPI;
1448     GdkScreen* screen = gtk_widget_has_screen(GTK_WIDGET(webView)) ? gtk_widget_get_screen(GTK_WIDGET(webView)) : gdk_screen_get_default();
1449     if (screen) {
1450         DPI = gdk_screen_get_resolution(screen);
1451         // gdk_screen_get_resolution() returns -1 when no DPI is set.
1452         if (DPI == -1)
1453             DPI = defaultDPI;
1454     }
1455     ASSERT(DPI > 0);
1456     return DPI;
1457 }
1458
1459 static void webkit_web_view_screen_changed(GtkWidget* widget, GdkScreen* previousScreen)
1460 {
1461     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1462     WebKitWebViewPrivate* priv = webView->priv;
1463
1464     if (priv->disposing)
1465         return;
1466
1467     WebKitWebSettings* webSettings = priv->webSettings.get();
1468     Settings* settings = core(webView)->settings();
1469     gdouble DPI = webViewGetDPI(webView);
1470
1471     guint defaultFontSize, defaultMonospaceFontSize, minimumFontSize, minimumLogicalFontSize;
1472
1473     g_object_get(webSettings,
1474                  "default-font-size", &defaultFontSize,
1475                  "default-monospace-font-size", &defaultMonospaceFontSize,
1476                  "minimum-font-size", &minimumFontSize,
1477                  "minimum-logical-font-size", &minimumLogicalFontSize,
1478                  NULL);
1479
1480     settings->setDefaultFontSize(defaultFontSize / 72.0 * DPI);
1481     settings->setDefaultFixedFontSize(defaultMonospaceFontSize / 72.0 * DPI);
1482     settings->setMinimumFontSize(minimumFontSize / 72.0 * DPI);
1483     settings->setMinimumLogicalFontSize(minimumLogicalFontSize / 72.0 * DPI);
1484 }
1485
1486 static IntPoint globalPointForClientPoint(GdkWindow* window, const IntPoint& clientPoint)
1487 {
1488     int x, y;
1489     gdk_window_get_origin(window, &x, &y);
1490     return clientPoint + IntSize(x, y);
1491 }
1492
1493
1494 static void webkit_web_view_drag_end(GtkWidget* widget, GdkDragContext* context)
1495 {
1496     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1497     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1498
1499     // This might happen if a drag is still in progress after a WebKitWebView
1500     // is disposed and before it is finalized.
1501     if (!priv->draggingDataObjects.contains(context))
1502         return;
1503
1504     priv->draggingDataObjects.remove(context);
1505
1506     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1507     if (!frame)
1508         return;
1509
1510     GdkEvent* event = gdk_event_new(GDK_BUTTON_RELEASE);
1511     int x, y, xRoot, yRoot;
1512     GdkModifierType modifiers;
1513     GdkDisplay* display = gdk_display_get_default();
1514     gdk_display_get_pointer(display, 0, &xRoot, &yRoot, &modifiers);
1515
1516     GdkWindow* window = gdk_display_get_window_at_pointer(display, &x, &y);
1517     if (window) {
1518         g_object_ref(window);
1519         event->button.window = window;
1520     }
1521     event->button.x = x;
1522     event->button.y = y;
1523     event->button.x_root = xRoot;
1524     event->button.y_root = yRoot;
1525     event->button.state = modifiers;
1526
1527     PlatformMouseEvent platformEvent(&event->button);
1528     frame->eventHandler()->dragSourceEndedAt(platformEvent, gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
1529
1530     gdk_event_free(event);
1531 }
1532
1533 static void webkit_web_view_drag_data_get(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint)
1534 {
1535     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(widget));
1536
1537     // This might happen if a drag is still in progress after a WebKitWebView
1538     // is diposed and before it is finalized.
1539     if (!priv->draggingDataObjects.contains(context))
1540         return;
1541
1542     pasteboardHelperInstance()->fillSelectionData(selectionData, info, priv->draggingDataObjects.get(context).get());
1543 }
1544
1545 static gboolean doDragLeaveLater(DroppingContext* context)
1546 {
1547     WebKitWebView* webView = context->webView;
1548     WebKitWebViewPrivate* priv = webView->priv;
1549
1550     if (!priv->droppingContexts.contains(context->gdkContext))
1551         return FALSE;
1552
1553     // If the view doesn't know about the drag yet (there are still pending data)
1554     // requests, don't update it with information about the drag.
1555     if (context->pendingDataRequests)
1556         return FALSE;
1557
1558     // Don't call dragExited if we have just received a drag-drop signal. This
1559     // happens in the case of a successful drop onto the view.
1560     if (!context->dropHappened) {
1561         const IntPoint& position = context->lastMotionPosition;
1562         DragData dragData(context->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(GTK_WIDGET(webView)), position), DragOperationNone);
1563         core(webView)->dragController()->dragExited(&dragData);
1564     }
1565
1566     core(webView)->dragController()->dragEnded();
1567     priv->droppingContexts.remove(context->gdkContext);
1568     delete context;
1569     return FALSE;
1570 }
1571
1572 static void webkit_web_view_drag_leave(GtkWidget* widget, GdkDragContext* context, guint time)
1573 {
1574     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1575     WebKitWebViewPrivate* priv = webView->priv;
1576
1577     if (!priv->droppingContexts.contains(context))
1578         return;
1579
1580     // During a drop GTK+ will fire a drag-leave signal right before firing
1581     // the drag-drop signal. We want the actions for drag-leave to happen after
1582     // those for drag-drop, so schedule them to happen asynchronously here.
1583     g_timeout_add(0, reinterpret_cast<GSourceFunc>(doDragLeaveLater), priv->droppingContexts.get(context));
1584 }
1585
1586 static gboolean webkit_web_view_drag_motion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1587 {
1588     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1589     WebKitWebViewPrivate* priv = webView->priv;
1590
1591     DroppingContext* droppingContext = 0;
1592     IntPoint position = IntPoint(x, y);
1593     if (!priv->droppingContexts.contains(context)) {
1594         droppingContext = new DroppingContext;
1595         droppingContext->webView = webView;
1596         droppingContext->gdkContext = context;
1597         droppingContext->dataObject = WebCore::DataObjectGtk::create();
1598         droppingContext->dropHappened = false;
1599         droppingContext->lastMotionPosition = position;
1600         priv->droppingContexts.set(context, droppingContext);
1601
1602         Vector<GdkAtom> acceptableTargets(pasteboardHelperInstance()->dropAtomsForContext(widget, context));
1603         droppingContext->pendingDataRequests = acceptableTargets.size();
1604         for (size_t i = 0; i < acceptableTargets.size(); i++)
1605             gtk_drag_get_data(widget, context, acceptableTargets.at(i), time);
1606     } else {
1607         droppingContext = priv->droppingContexts.get(context);
1608         droppingContext->lastMotionPosition = position;
1609     }
1610
1611     // Don't send any drag information to WebCore until we've retrieved all
1612     // the data for this drag operation. Otherwise we'd have to block to wait
1613     // for the drag's data.
1614     ASSERT(droppingContext);
1615     if (droppingContext->pendingDataRequests > 0)
1616         return TRUE;
1617
1618     DragData dragData(droppingContext->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(widget), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
1619     DragOperation operation = core(webView)->dragController()->dragUpdated(&dragData);
1620     gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
1621
1622     return TRUE;
1623 }
1624
1625 static void webkit_web_view_drag_data_received(GtkWidget* widget, GdkDragContext* context, gint x, gint y, GtkSelectionData* selectionData, guint info, guint time)
1626 {
1627     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1628     WebKitWebViewPrivate* priv = webView->priv;
1629
1630     if (!priv->droppingContexts.contains(context))
1631         return;
1632
1633     DroppingContext* droppingContext = priv->droppingContexts.get(context);
1634     droppingContext->pendingDataRequests--;
1635     pasteboardHelperInstance()->fillDataObjectFromDropData(selectionData, info, droppingContext->dataObject.get());
1636
1637     if (droppingContext->pendingDataRequests)
1638         return;
1639
1640     // The coordinates passed to drag-data-received signal are sometimes
1641     // inaccurate in DRT, so use the coordinates of the last motion event.
1642     const IntPoint& position = droppingContext->lastMotionPosition;
1643
1644     // If there are no more pending requests, start sending dragging data to WebCore.
1645     DragData dragData(droppingContext->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(widget), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
1646     DragOperation operation = core(webView)->dragController()->dragEntered(&dragData);
1647     gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
1648 }
1649
1650 static gboolean webkit_web_view_drag_drop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
1651 {
1652     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1653     WebKitWebViewPrivate* priv = webView->priv;
1654
1655     if (!priv->droppingContexts.contains(context))
1656         return FALSE;
1657
1658     DroppingContext* droppingContext = priv->droppingContexts.get(context);
1659     droppingContext->dropHappened = true;
1660
1661     IntPoint position(x, y);
1662     DragData dragData(droppingContext->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(widget), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
1663     core(webView)->dragController()->performDrag(&dragData);
1664
1665     gtk_drag_finish(context, TRUE, FALSE, time);
1666     return TRUE;
1667 }
1668
1669 #if GTK_CHECK_VERSION(2, 12, 0)
1670 static gboolean webkit_web_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip)
1671 {
1672     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(widget);
1673
1674     if (keyboard_mode) {
1675         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
1676
1677         // Get the title of the current focused element.
1678         Frame* coreFrame = core(webView)->focusController()->focusedOrMainFrame();
1679         if (!coreFrame)
1680             return FALSE;
1681
1682         Node* node = getFocusedNode(coreFrame);
1683         if (!node)
1684             return FALSE;
1685
1686         for (Node* titleNode = node; titleNode; titleNode = titleNode->parentNode()) {
1687             if (titleNode->isElementNode()) {
1688                 String title = static_cast<Element*>(titleNode)->title();
1689                 if (!title.isEmpty()) {
1690                     if (FrameView* view = coreFrame->view()) {
1691                         GdkRectangle area = view->contentsToWindow(node->getRect());
1692                         gtk_tooltip_set_tip_area(tooltip, &area);
1693                     }
1694                     gtk_tooltip_set_text(tooltip, title.utf8().data());
1695
1696                     return TRUE;
1697                 }
1698             }
1699         }
1700
1701         return FALSE;
1702     }
1703
1704     if (priv->tooltipText.length() > 0) {
1705         if (!keyboard_mode) {
1706             if (!priv->tooltipArea.isEmpty()) {
1707                 GdkRectangle area = priv->tooltipArea;
1708                 gtk_tooltip_set_tip_area(tooltip, &area);
1709             } else
1710                 gtk_tooltip_set_tip_area(tooltip, 0);
1711         }
1712         gtk_tooltip_set_text(tooltip, priv->tooltipText.data());
1713         return TRUE;
1714     }
1715
1716     return FALSE;
1717 }
1718
1719 static gboolean webkit_web_view_show_help(GtkWidget* widget, GtkWidgetHelpType help_type)
1720 {
1721     if (help_type == GTK_WIDGET_HELP_TOOLTIP)
1722         gtk_widget_set_has_tooltip(widget, TRUE);
1723
1724     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->show_help(widget, help_type);
1725 }
1726 #endif
1727
1728 static GtkIMContext* webkit_web_view_get_im_context(WebKitWebView* webView)
1729 {
1730     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1731     return GTK_IM_CONTEXT(webView->priv->imContext.get());
1732 }
1733
1734 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
1735 {
1736     GtkBindingSet* binding_set;
1737
1738     webkit_init();
1739
1740     /*
1741      * Signals
1742      */
1743
1744     /**
1745      * WebKitWebView::create-web-view:
1746      * @webView: the object on which the signal is emitted
1747      * @frame: the #WebKitWebFrame
1748      *
1749      * Emitted when the creation of a new window is requested.
1750      * If this signal is handled the signal handler should return the
1751      * newly created #WebKitWebView.
1752      *
1753      * The new #WebKitWebView should not be displayed to the user
1754      * until the #WebKitWebView::web-view-ready signal is emitted.
1755      *
1756      * The signal handlers should not try to deal with the reference count for
1757      * the new #WebKitWebView. The widget to which the widget is added will
1758      * handle that.
1759      *
1760      * Return value: (transfer full): a newly allocated #WebKitWebView, or %NULL
1761      *
1762      * Since: 1.0.3
1763      */
1764     webkit_web_view_signals[CREATE_WEB_VIEW] = g_signal_new("create-web-view",
1765             G_TYPE_FROM_CLASS(webViewClass),
1766             (GSignalFlags)G_SIGNAL_RUN_LAST,
1767             G_STRUCT_OFFSET (WebKitWebViewClass, create_web_view),
1768             webkit_signal_accumulator_object_handled,
1769             NULL,
1770             webkit_marshal_OBJECT__OBJECT,
1771             WEBKIT_TYPE_WEB_VIEW , 1,
1772             WEBKIT_TYPE_WEB_FRAME);
1773
1774     /**
1775      * WebKitWebView::web-view-ready:
1776      * @webView: the object on which the signal is emitted
1777      *
1778      * Emitted after #WebKitWebView::create-web-view when the new #WebKitWebView
1779      * should be displayed to the user. When this signal is emitted
1780      * all the information about how the window should look, including
1781      * size, position, whether the location, status and scroll bars
1782      * should be displayed, is already set on the
1783      * #WebKitWebWindowFeatures object contained by the #WebKitWebView.
1784      *
1785      * Notice that some of that information may change during the life
1786      * time of the window, so you may want to connect to the ::notify
1787      * signal of the #WebKitWebWindowFeatures object to handle those.
1788      *
1789      * Return value: %TRUE to stop handlers from being invoked for the event or
1790      * %FALSE to propagate the event furter
1791      *
1792      * Since: 1.0.3
1793      */
1794     webkit_web_view_signals[WEB_VIEW_READY] = g_signal_new("web-view-ready",
1795             G_TYPE_FROM_CLASS(webViewClass),
1796             (GSignalFlags)G_SIGNAL_RUN_LAST,
1797             G_STRUCT_OFFSET (WebKitWebViewClass, web_view_ready),
1798             g_signal_accumulator_true_handled,
1799             NULL,
1800             webkit_marshal_BOOLEAN__VOID,
1801             G_TYPE_BOOLEAN, 0);
1802
1803     /**
1804      * WebKitWebView::close-web-view:
1805      * @webView: the object on which the signal is emitted
1806      *
1807      * Emitted when closing a #WebKitWebView is requested. This occurs when a
1808      * call is made from JavaScript's window.close function. The default
1809      * signal handler does not do anything. It is the owner's responsibility
1810      * to hide or delete the web view, if necessary.
1811      *
1812      * Return value: %TRUE to stop handlers from being invoked for the event or
1813      * %FALSE to propagate the event furter
1814      *
1815      * Since: 1.1.11
1816      */
1817     webkit_web_view_signals[CLOSE_WEB_VIEW] = g_signal_new("close-web-view",
1818             G_TYPE_FROM_CLASS(webViewClass),
1819             (GSignalFlags)G_SIGNAL_RUN_LAST,
1820             G_STRUCT_OFFSET (WebKitWebViewClass, close_web_view),
1821             g_signal_accumulator_true_handled,
1822             NULL,
1823             webkit_marshal_BOOLEAN__VOID,
1824             G_TYPE_BOOLEAN, 0);
1825
1826     /**
1827      * WebKitWebView::navigation-requested:
1828      * @webView: the object on which the signal is emitted
1829      * @frame: the #WebKitWebFrame that required the navigation
1830      * @request: a #WebKitNetworkRequest
1831      *
1832      * Emitted when @frame requests a navigation to another page.
1833      *
1834      * Return value: a #WebKitNavigationResponse
1835      *
1836      * Deprecated: Use WebKitWebView::navigation-policy-decision-requested
1837      * instead
1838      */
1839     webkit_web_view_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation-requested",
1840             G_TYPE_FROM_CLASS(webViewClass),
1841             (GSignalFlags)G_SIGNAL_RUN_LAST,
1842             G_STRUCT_OFFSET (WebKitWebViewClass, navigation_requested),
1843             webkit_navigation_request_handled,
1844             NULL,
1845             webkit_marshal_ENUM__OBJECT_OBJECT,
1846             WEBKIT_TYPE_NAVIGATION_RESPONSE, 2,
1847             WEBKIT_TYPE_WEB_FRAME,
1848             WEBKIT_TYPE_NETWORK_REQUEST);
1849
1850     /**
1851      * WebKitWebView::new-window-policy-decision-requested:
1852      * @webView: the object on which the signal is emitted
1853      * @frame: the #WebKitWebFrame that required the navigation
1854      * @request: a #WebKitNetworkRequest
1855      * @navigation_action: a #WebKitWebNavigationAction
1856      * @policy_decision: a #WebKitWebPolicyDecision
1857      *
1858      * Emitted when @frame requests opening a new window. With this
1859      * signal the browser can use the context of the request to decide
1860      * about the new window. If the request is not handled the default
1861      * behavior is to allow opening the new window to load the URI,
1862      * which will cause a create-web-view signal emission where the
1863      * browser handles the new window action but without information
1864      * of the context that caused the navigation. The following
1865      * navigation-policy-decision-requested emissions will load the
1866      * page after the creation of the new window just with the
1867      * information of this new navigation context, without any
1868      * information about the action that made this new window to be
1869      * opened.
1870      *
1871      * Notice that if you return TRUE, meaning that you handled the
1872      * signal, you are expected to have decided what to do, by calling
1873      * webkit_web_policy_decision_ignore(),
1874      * webkit_web_policy_decision_use(), or
1875      * webkit_web_policy_decision_download() on the @policy_decision
1876      * object.
1877      *
1878      * Return value: %TRUE if a decision was made, %FALSE to have the
1879      * default behavior apply
1880      *
1881      * Since: 1.1.4
1882      */
1883     webkit_web_view_signals[NEW_WINDOW_POLICY_DECISION_REQUESTED] =
1884         g_signal_new("new-window-policy-decision-requested",
1885             G_TYPE_FROM_CLASS(webViewClass),
1886             (GSignalFlags)G_SIGNAL_RUN_LAST,
1887             0,
1888             g_signal_accumulator_true_handled,
1889             NULL,
1890             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
1891             G_TYPE_BOOLEAN, 4,
1892             WEBKIT_TYPE_WEB_FRAME,
1893             WEBKIT_TYPE_NETWORK_REQUEST,
1894             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
1895             WEBKIT_TYPE_WEB_POLICY_DECISION);
1896
1897     /**
1898      * WebKitWebView::navigation-policy-decision-requested:
1899      * @webView: the object on which the signal is emitted
1900      * @frame: the #WebKitWebFrame that required the navigation
1901      * @request: a #WebKitNetworkRequest
1902      * @navigation_action: a #WebKitWebNavigationAction
1903      * @policy_decision: a #WebKitWebPolicyDecision
1904      *
1905      * Emitted when @frame requests a navigation to another page.
1906      * If this signal is not handled, the default behavior is to allow the
1907      * navigation.
1908      *
1909      * Notice that if you return TRUE, meaning that you handled the
1910      * signal, you are expected to have decided what to do, by calling
1911      * webkit_web_policy_decision_ignore(),
1912      * webkit_web_policy_decision_use(), or
1913      * webkit_web_policy_decision_download() on the @policy_decision
1914      * object.
1915      *
1916      * Return value: %TRUE if a decision was made, %FALSE to have the
1917      * default behavior apply
1918      *
1919      * Since: 1.0.3
1920      */
1921     webkit_web_view_signals[NAVIGATION_POLICY_DECISION_REQUESTED] = g_signal_new("navigation-policy-decision-requested",
1922             G_TYPE_FROM_CLASS(webViewClass),
1923             (GSignalFlags)G_SIGNAL_RUN_LAST,
1924             0,
1925             g_signal_accumulator_true_handled,
1926             NULL,
1927             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
1928             G_TYPE_BOOLEAN, 4,
1929             WEBKIT_TYPE_WEB_FRAME,
1930             WEBKIT_TYPE_NETWORK_REQUEST,
1931             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
1932             WEBKIT_TYPE_WEB_POLICY_DECISION);
1933
1934     /**
1935      * WebKitWebView::mime-type-policy-decision-requested:
1936      * @webView: the object on which the signal is emitted
1937      * @frame: the #WebKitWebFrame that required the policy decision
1938      * @request: a WebKitNetworkRequest
1939      * @mimetype: the MIME type attempted to load
1940      * @policy_decision: a #WebKitWebPolicyDecision
1941      *
1942      * Decide whether or not to display the given MIME type.  If this
1943      * signal is not handled, the default behavior is to show the
1944      * content of the requested URI if WebKit can show this MIME
1945      * type and the content disposition is not a download; if WebKit
1946      * is not able to show the MIME type nothing happens.
1947      *
1948      * Notice that if you return TRUE, meaning that you handled the
1949      * signal, you are expected to be aware of the "Content-Disposition"
1950      * header. A value of "attachment" usually indicates a download
1951      * regardless of the MIME type, see also
1952      * soup_message_headers_get_content_disposition(). And you must call
1953      * webkit_web_policy_decision_ignore(),
1954      * webkit_web_policy_decision_use(), or
1955      * webkit_web_policy_decision_download() on the @policy_decision
1956      * object.
1957      *
1958      * Return value: %TRUE if a decision was made, %FALSE to have the
1959      * default behavior apply
1960      *
1961      * Since: 1.0.3
1962      */
1963     webkit_web_view_signals[MIME_TYPE_POLICY_DECISION_REQUESTED] = g_signal_new("mime-type-policy-decision-requested",
1964             G_TYPE_FROM_CLASS(webViewClass),
1965             (GSignalFlags)G_SIGNAL_RUN_LAST,
1966             0,
1967             g_signal_accumulator_true_handled,
1968             NULL,
1969             webkit_marshal_BOOLEAN__OBJECT_OBJECT_STRING_OBJECT,
1970             G_TYPE_BOOLEAN, 4,
1971             WEBKIT_TYPE_WEB_FRAME,
1972             WEBKIT_TYPE_NETWORK_REQUEST,
1973             G_TYPE_STRING,
1974             WEBKIT_TYPE_WEB_POLICY_DECISION);
1975
1976     /**
1977      * WebKitWebView::window-object-cleared:
1978      * @webView: the object on which the signal is emitted
1979      * @frame: the #WebKitWebFrame to which @window_object belongs
1980      * @context: the #JSGlobalContextRef holding the global object and other
1981      * execution state; equivalent to the return value of
1982      * webkit_web_frame_get_global_context(@frame)
1983      * @window_object: the #JSObjectRef representing the frame's JavaScript
1984      * window object
1985      *
1986      * Emitted when the JavaScript window object in a #WebKitWebFrame has been
1987      * cleared in preparation for a new load. This is the preferred place to
1988      * set custom properties on the window object using the JavaScriptCore API.
1989      */
1990     webkit_web_view_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window-object-cleared",
1991             G_TYPE_FROM_CLASS(webViewClass),
1992             (GSignalFlags)G_SIGNAL_RUN_LAST,
1993             G_STRUCT_OFFSET (WebKitWebViewClass, window_object_cleared),
1994             NULL,
1995             NULL,
1996             webkit_marshal_VOID__OBJECT_POINTER_POINTER,
1997             G_TYPE_NONE, 3,
1998             WEBKIT_TYPE_WEB_FRAME,
1999             G_TYPE_POINTER,
2000             G_TYPE_POINTER);
2001
2002     /**
2003      * WebKitWebView::download-requested:
2004      * @webView: the object on which the signal is emitted
2005      * @download: a #WebKitDownload object that lets you control the
2006      * download process
2007      *
2008      * A new Download is being requested. By default, if the signal is
2009      * not handled, the download is cancelled. If you handle the download
2010      * and call webkit_download_set_destination_uri(), it will be
2011      * started for you. If you need to set the destination asynchronously
2012      * you are responsible for starting or cancelling it yourself.
2013      *
2014      * If you intend to handle downloads yourself rather than using
2015      * the #WebKitDownload helper object you must handle this signal,
2016      * and return %FALSE.
2017      *
2018      * Also, keep in mind that the default policy for WebKitGTK+ is to
2019      * ignore files with a MIME type that it does not know how to
2020      * handle, which means this signal won't be emitted in the default
2021      * setup. One way to trigger downloads is to connect to
2022      * WebKitWebView::mime-type-policy-decision-requested and call
2023      * webkit_web_policy_decision_download() on the
2024      * #WebKitWebPolicyDecision in the parameter list for the kind of
2025      * files you want your application to download (a common solution
2026      * is to download anything that WebKit can't handle, which you can
2027      * figure out by using webkit_web_view_can_show_mime_type()).
2028      *
2029      * Return value: TRUE if the download should be performed, %FALSE to
2030      * cancel it
2031      *
2032      * Since: 1.1.2
2033      */
2034     webkit_web_view_signals[DOWNLOAD_REQUESTED] = g_signal_new("download-requested",
2035             G_TYPE_FROM_CLASS(webViewClass),
2036             (GSignalFlags)G_SIGNAL_RUN_LAST,
2037             0,
2038             g_signal_accumulator_true_handled,
2039             NULL,
2040             webkit_marshal_BOOLEAN__OBJECT,
2041             G_TYPE_BOOLEAN, 1,
2042             G_TYPE_OBJECT);
2043
2044     /**
2045      * WebKitWebView::load-started:
2046      * @webView: the object on which the signal is emitted
2047      * @frame: the frame going to do the load
2048      *
2049      * When a #WebKitWebFrame begins to load this signal is emitted.
2050      *
2051      * Deprecated: Use the "load-status" property instead.
2052      */
2053     webkit_web_view_signals[LOAD_STARTED] = g_signal_new("load-started",
2054             G_TYPE_FROM_CLASS(webViewClass),
2055             (GSignalFlags)G_SIGNAL_RUN_LAST,
2056             0,
2057             NULL,
2058             NULL,
2059             g_cclosure_marshal_VOID__OBJECT,
2060             G_TYPE_NONE, 1,
2061             WEBKIT_TYPE_WEB_FRAME);
2062
2063     /**
2064      * WebKitWebView::load-committed:
2065      * @webView: the object on which the signal is emitted
2066      * @frame: the main frame that received the first data
2067      *
2068      * When a #WebKitWebFrame loaded the first data this signal is emitted.
2069      *
2070      * Deprecated: Use the "load-status" property instead.
2071      */
2072     webkit_web_view_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
2073             G_TYPE_FROM_CLASS(webViewClass),
2074             (GSignalFlags)G_SIGNAL_RUN_LAST,
2075             0,
2076             NULL,
2077             NULL,
2078             g_cclosure_marshal_VOID__OBJECT,
2079             G_TYPE_NONE, 1,
2080             WEBKIT_TYPE_WEB_FRAME);
2081
2082
2083     /**
2084      * WebKitWebView::load-progress-changed:
2085      * @webView: the #WebKitWebView
2086      * @progress: the global progress
2087      *
2088      * Deprecated: Use the "progress" property instead.
2089      */
2090     webkit_web_view_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load-progress-changed",
2091             G_TYPE_FROM_CLASS(webViewClass),
2092             (GSignalFlags)G_SIGNAL_RUN_LAST,
2093             0,
2094             NULL,
2095             NULL,
2096             g_cclosure_marshal_VOID__INT,
2097             G_TYPE_NONE, 1,
2098             G_TYPE_INT);
2099
2100     /**
2101      * WebKitWebView::load-error
2102      * @webView: the object on which the signal is emitted
2103      * @web_frame: the #WebKitWebFrame
2104      * @uri: the URI that triggered the error
2105      * @web_error: the #GError that was triggered
2106      *
2107      * An error occurred while loading. By default, if the signal is not
2108      * handled, the @web_view will display a stock error page. You need to
2109      * handle the signal if you want to provide your own error page.
2110      *
2111      * Since: 1.1.6
2112      *
2113      * Return value: %TRUE to stop other handlers from being invoked for the
2114      * event. %FALSE to propagate the event further.
2115      */
2116     webkit_web_view_signals[LOAD_ERROR] = g_signal_new("load-error",
2117             G_TYPE_FROM_CLASS(webViewClass),
2118             (GSignalFlags)(G_SIGNAL_RUN_LAST),
2119             0,
2120             g_signal_accumulator_true_handled,
2121             NULL,
2122             webkit_marshal_BOOLEAN__OBJECT_STRING_POINTER,
2123             G_TYPE_BOOLEAN, 3,
2124             WEBKIT_TYPE_WEB_FRAME,
2125             G_TYPE_STRING,
2126             G_TYPE_POINTER);
2127
2128     /**
2129      * WebKitWebView::load-finished:
2130      * @webView: the #WebKitWebView
2131      * @frame: the #WebKitWebFrame
2132      *
2133      * Deprecated: Use the "load-status" property instead.
2134      */
2135     webkit_web_view_signals[LOAD_FINISHED] = g_signal_new("load-finished",
2136             G_TYPE_FROM_CLASS(webViewClass),
2137             (GSignalFlags)G_SIGNAL_RUN_LAST,
2138             0,
2139             NULL,
2140             NULL,
2141             g_cclosure_marshal_VOID__OBJECT,
2142             G_TYPE_NONE, 1,
2143             WEBKIT_TYPE_WEB_FRAME);
2144
2145     /**
2146      * WebKitWebView::onload-event:
2147      * @webView: the object on which the signal is emitted
2148      * @frame: the frame
2149      *
2150      * When a #WebKitWebFrame receives an onload event this signal is emitted.
2151      */
2152     webkit_web_view_signals[ONLOAD_EVENT] = g_signal_new("onload-event",
2153             G_TYPE_FROM_CLASS(webViewClass),
2154             (GSignalFlags)G_SIGNAL_RUN_LAST,
2155             0,
2156             NULL,
2157             NULL,
2158             g_cclosure_marshal_VOID__OBJECT,
2159             G_TYPE_NONE, 1,
2160             WEBKIT_TYPE_WEB_FRAME);
2161
2162     /**
2163      * WebKitWebView::title-changed:
2164      * @webView: the object on which the signal is emitted
2165      * @frame: the main frame
2166      * @title: the new title
2167      *
2168      * When a #WebKitWebFrame changes the document title this signal is emitted.
2169      *
2170      * Deprecated: 1.1.4: Use "notify::title" instead.
2171      */
2172     webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed",
2173             G_TYPE_FROM_CLASS(webViewClass),
2174             (GSignalFlags)G_SIGNAL_RUN_LAST,
2175             0,
2176             NULL,
2177             NULL,
2178             webkit_marshal_VOID__OBJECT_STRING,
2179             G_TYPE_NONE, 2,
2180             WEBKIT_TYPE_WEB_FRAME,
2181             G_TYPE_STRING);
2182
2183     /**
2184      * WebKitWebView::hovering-over-link:
2185      * @webView: the object on which the signal is emitted
2186      * @title: the link's title
2187      * @uri: the URI the link points to
2188      *
2189      * When the cursor is over a link, this signal is emitted.
2190      */
2191     webkit_web_view_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
2192             G_TYPE_FROM_CLASS(webViewClass),
2193             (GSignalFlags)G_SIGNAL_RUN_LAST,
2194             0,
2195             NULL,
2196             NULL,
2197             webkit_marshal_VOID__STRING_STRING,
2198             G_TYPE_NONE, 2,
2199             G_TYPE_STRING,
2200             G_TYPE_STRING);
2201
2202     /**
2203      * WebKitWebView::populate-popup:
2204      * @webView: the object on which the signal is emitted
2205      * @menu: the context menu
2206      *
2207      * When a context menu is about to be displayed this signal is emitted.
2208      *
2209      * Add menu items to #menu to extend the context menu.
2210      */
2211     webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
2212             G_TYPE_FROM_CLASS(webViewClass),
2213             (GSignalFlags)G_SIGNAL_RUN_LAST,
2214             0,
2215             NULL,
2216             NULL,
2217             g_cclosure_marshal_VOID__OBJECT,
2218             G_TYPE_NONE, 1,
2219             GTK_TYPE_MENU);
2220
2221     /**
2222      * WebKitWebView::print-requested
2223      * @webView: the object in which the signal is emitted
2224      * @web_frame: the frame that is requesting to be printed
2225      *
2226      * Emitted when printing is requested by the frame, usually
2227      * because of a javascript call. When handling this signal you
2228      * should call webkit_web_frame_print_full() or
2229      * webkit_web_frame_print() to do the actual printing.
2230      *
2231      * The default handler will present a print dialog and carry a
2232      * print operation. Notice that this means that if you intend to
2233      * ignore a print request you must connect to this signal, and
2234      * return %TRUE.
2235      *
2236      * Return value: %TRUE if the print request has been handled, %FALSE if
2237      * the default handler should run
2238      *
2239      * Since: 1.1.5
2240      */
2241     webkit_web_view_signals[PRINT_REQUESTED] = g_signal_new("print-requested",
2242             G_TYPE_FROM_CLASS(webViewClass),
2243             (GSignalFlags)G_SIGNAL_RUN_LAST,
2244             0,
2245             g_signal_accumulator_true_handled,
2246             NULL,
2247             webkit_marshal_BOOLEAN__OBJECT,
2248             G_TYPE_BOOLEAN, 1,
2249             WEBKIT_TYPE_WEB_FRAME);
2250
2251     webkit_web_view_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status-bar-text-changed",
2252             G_TYPE_FROM_CLASS(webViewClass),
2253             (GSignalFlags)G_SIGNAL_RUN_LAST,
2254             0,
2255             NULL,
2256             NULL,
2257             g_cclosure_marshal_VOID__STRING,
2258             G_TYPE_NONE, 1,
2259             G_TYPE_STRING);
2260
2261     /**
2262      * WebKitWebView::icon-loaded:
2263      * @webView: the object on which the signal is emitted
2264      * @icon_uri: the URI for the icon
2265      *
2266      * This signal is emitted when the main frame has got a favicon.
2267      *
2268      * Since: 1.1.18
2269      */
2270     webkit_web_view_signals[ICON_LOADED] = g_signal_new("icon-loaded",
2271             G_TYPE_FROM_CLASS(webViewClass),
2272             (GSignalFlags)G_SIGNAL_RUN_LAST,
2273             0,
2274             NULL,
2275             NULL,
2276             g_cclosure_marshal_VOID__STRING,
2277             G_TYPE_NONE, 1,
2278             G_TYPE_STRING);
2279
2280     /**
2281      * WebKitWebView::console-message:
2282      * @webView: the object on which the signal is emitted
2283      * @message: the message text
2284      * @line: the line where the error occured
2285      * @source_id: the source id
2286      *
2287      * A JavaScript console message was created.
2288      *
2289      * Return value: %TRUE to stop other handlers from being invoked for the
2290      * event. %FALSE to propagate the event further.
2291      */
2292     webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message",
2293             G_TYPE_FROM_CLASS(webViewClass),
2294             (GSignalFlags)G_SIGNAL_RUN_LAST,
2295             G_STRUCT_OFFSET(WebKitWebViewClass, console_message),
2296             g_signal_accumulator_true_handled,
2297             NULL,
2298             webkit_marshal_BOOLEAN__STRING_INT_STRING,
2299             G_TYPE_BOOLEAN, 3,
2300             G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
2301
2302     /**
2303      * WebKitWebView::script-alert:
2304      * @webView: the object on which the signal is emitted
2305      * @frame: the relevant frame
2306      * @message: the message text
2307      *
2308      * A JavaScript alert dialog was created.
2309      *
2310      * Return value: %TRUE to stop other handlers from being invoked for the
2311      * event. %FALSE to propagate the event further.
2312      */
2313     webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
2314             G_TYPE_FROM_CLASS(webViewClass),
2315             (GSignalFlags)G_SIGNAL_RUN_LAST,
2316             G_STRUCT_OFFSET(WebKitWebViewClass, script_alert),
2317             g_signal_accumulator_true_handled,
2318             NULL,
2319             webkit_marshal_BOOLEAN__OBJECT_STRING,
2320             G_TYPE_BOOLEAN, 2,
2321             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING);
2322
2323     /**
2324      * WebKitWebView::script-confirm:
2325      * @webView: the object on which the signal is emitted
2326      * @frame: the relevant frame
2327      * @message: the message text
2328      * @confirmed: whether the dialog has been confirmed
2329      *
2330      * A JavaScript confirm dialog was created, providing Yes and No buttons.
2331      *
2332      * Return value: %TRUE to stop other handlers from being invoked for the
2333      * event. %FALSE to propagate the event further.
2334      */
2335     webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm",
2336             G_TYPE_FROM_CLASS(webViewClass),
2337             (GSignalFlags)G_SIGNAL_RUN_LAST,
2338             G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm),
2339             g_signal_accumulator_true_handled,
2340             NULL,
2341             webkit_marshal_BOOLEAN__OBJECT_STRING_POINTER,
2342             G_TYPE_BOOLEAN, 3,
2343             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_POINTER);
2344
2345     /**
2346      * WebKitWebView::script-prompt:
2347      * @webView: the object on which the signal is emitted
2348      * @frame: the relevant frame
2349      * @message: the message text
2350      * @default: the default value
2351      * @text: To be filled with the return value or NULL if the dialog was cancelled.
2352      *
2353      * A JavaScript prompt dialog was created, providing an entry to input text.
2354      *
2355      * Return value: %TRUE to stop other handlers from being invoked for the
2356      * event. %FALSE to propagate the event further.
2357      */
2358     webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt",
2359             G_TYPE_FROM_CLASS(webViewClass),
2360             (GSignalFlags)G_SIGNAL_RUN_LAST,
2361             G_STRUCT_OFFSET(WebKitWebViewClass, script_prompt),
2362             g_signal_accumulator_true_handled,
2363             NULL,
2364             webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
2365             G_TYPE_BOOLEAN, 4,
2366             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
2367
2368     /**
2369      * WebKitWebView::select-all:
2370      * @webView: the object which received the signal
2371      *
2372      * The #WebKitWebView::select-all signal is a keybinding signal which gets emitted to
2373      * select the complete contents of the text view.
2374      *
2375      * The default bindings for this signal is Ctrl-a.
2376      */
2377     webkit_web_view_signals[SELECT_ALL] = g_signal_new("select-all",
2378             G_TYPE_FROM_CLASS(webViewClass),
2379             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2380             G_STRUCT_OFFSET(WebKitWebViewClass, select_all),
2381             NULL, NULL,
2382             g_cclosure_marshal_VOID__VOID,
2383             G_TYPE_NONE, 0);
2384
2385     /**
2386      * WebKitWebView::cut-clipboard:
2387      * @webView: the object which received the signal
2388      *
2389      * The #WebKitWebView::cut-clipboard signal is a keybinding signal which gets emitted to
2390      * cut the selection to the clipboard.
2391      *
2392      * The default bindings for this signal are Ctrl-x and Shift-Delete.
2393      */
2394     webkit_web_view_signals[CUT_CLIPBOARD] = g_signal_new("cut-clipboard",
2395             G_TYPE_FROM_CLASS(webViewClass),
2396             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2397             G_STRUCT_OFFSET(WebKitWebViewClass, cut_clipboard),
2398             NULL, NULL,
2399             g_cclosure_marshal_VOID__VOID,
2400             G_TYPE_NONE, 0);
2401
2402     /**
2403      * WebKitWebView::copy-clipboard:
2404      * @webView: the object which received the signal
2405      *
2406      * The #WebKitWebView::copy-clipboard signal is a keybinding signal which gets emitted to
2407      * copy the selection to the clipboard.
2408      *
2409      * The default bindings for this signal are Ctrl-c and Ctrl-Insert.
2410      */
2411     webkit_web_view_signals[COPY_CLIPBOARD] = g_signal_new("copy-clipboard",
2412             G_TYPE_FROM_CLASS(webViewClass),
2413             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2414             G_STRUCT_OFFSET(WebKitWebViewClass, copy_clipboard),
2415             NULL, NULL,
2416             g_cclosure_marshal_VOID__VOID,
2417             G_TYPE_NONE, 0);
2418
2419     /**
2420      * WebKitWebView::paste-clipboard:
2421      * @webView: the object which received the signal
2422      *
2423      * The #WebKitWebView::paste-clipboard signal is a keybinding signal which gets emitted to
2424      * paste the contents of the clipboard into the Web view.
2425      *
2426      * The default bindings for this signal are Ctrl-v and Shift-Insert.
2427      */
2428     webkit_web_view_signals[PASTE_CLIPBOARD] = g_signal_new("paste-clipboard",
2429             G_TYPE_FROM_CLASS(webViewClass),
2430             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2431             G_STRUCT_OFFSET(WebKitWebViewClass, paste_clipboard),
2432             NULL, NULL,
2433             g_cclosure_marshal_VOID__VOID,
2434             G_TYPE_NONE, 0);
2435
2436     /**
2437      * WebKitWebView::undo
2438      * @webView: the object which received the signal
2439      *
2440      * The #WebKitWebView::undo signal is a keybinding signal which gets emitted to
2441      * undo the last editing command.
2442      *
2443      * The default binding for this signal is Ctrl-z
2444      *
2445      * Since: 1.1.14
2446      */
2447     webkit_web_view_signals[UNDO] = g_signal_new("undo",
2448             G_TYPE_FROM_CLASS(webViewClass),
2449             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2450             G_STRUCT_OFFSET(WebKitWebViewClass, undo),
2451             NULL, NULL,
2452             g_cclosure_marshal_VOID__VOID,
2453             G_TYPE_NONE, 0);
2454
2455     /**
2456      * WebKitWebView::redo
2457      * @webView: the object which received the signal
2458      *
2459      * The #WebKitWebView::redo signal is a keybinding signal which gets emitted to
2460      * redo the last editing command.
2461      *
2462      * The default binding for this signal is Ctrl-Shift-z
2463      *
2464      * Since: 1.1.14
2465      */
2466     webkit_web_view_signals[REDO] = g_signal_new("redo",
2467             G_TYPE_FROM_CLASS(webViewClass),
2468             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2469             G_STRUCT_OFFSET(WebKitWebViewClass, redo),
2470             NULL, NULL,
2471             g_cclosure_marshal_VOID__VOID,
2472             G_TYPE_NONE, 0);
2473
2474     /**
2475      * WebKitWebView::move-cursor:
2476      * @webView: the object which received the signal
2477      * @step: the type of movement, one of #GtkMovementStep
2478      * @count: an integer indicating the subtype of movement. Currently
2479      *         the permitted values are '1' = forward, '-1' = backwards.
2480      *
2481      * The #WebKitWebView::move-cursor will be emitted to apply the
2482      * cursor movement described by its parameters to the @view.
2483      *
2484      * Return value: %TRUE or %FALSE
2485      * 
2486      * Since: 1.1.4
2487      */
2488     webkit_web_view_signals[MOVE_CURSOR] = g_signal_new("move-cursor",
2489             G_TYPE_FROM_CLASS(webViewClass),
2490             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2491             G_STRUCT_OFFSET(WebKitWebViewClass, move_cursor),
2492             NULL, NULL,
2493             webkit_marshal_BOOLEAN__ENUM_INT,
2494             G_TYPE_BOOLEAN, 2,
2495             GTK_TYPE_MOVEMENT_STEP,
2496             G_TYPE_INT);
2497
2498     /**
2499      * WebKitWebView::create-plugin-widget:
2500      * @webView: the object which received the signal
2501      * @mime_type: the mimetype of the requested object
2502      * @uri: the URI to load
2503      * @param: a #GHashTable with additional attributes (strings)
2504      *
2505      * The #WebKitWebView::create-plugin-widget signal will be emitted to
2506      * create a plugin widget for embed or object HTML tags. This
2507      * allows to embed a GtkWidget as a plugin into HTML content. In
2508      * case of a textual selection of the GtkWidget WebCore will attempt
2509      * to set the property value of "webkit-widget-is-selected". This can
2510      * be used to draw a visual indicator of the selection.
2511      *
2512      * Return value: (transfer full): a new #GtkWidget, or %NULL
2513      *
2514      * Since: 1.1.8
2515      */
2516     webkit_web_view_signals[PLUGIN_WIDGET] = g_signal_new("create-plugin-widget",
2517             G_TYPE_FROM_CLASS(webViewClass),
2518             (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2519             0,
2520             webkit_signal_accumulator_object_handled,
2521             NULL,
2522             webkit_marshal_OBJECT__STRING_STRING_POINTER,
2523             GTK_TYPE_WIDGET, 3,
2524             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_HASH_TABLE);
2525
2526     /**
2527      * WebKitWebView::database-quota-exceeded
2528      * @webView: the object which received the signal
2529      * @frame: the relevant frame
2530      * @database: the #WebKitWebDatabase which exceeded the quota of its #WebKitSecurityOrigin
2531      *
2532      * The #WebKitWebView::database-quota-exceeded signal will be emitted when
2533      * a Web Database exceeds the quota of its security origin. This signal
2534      * may be used to increase the size of the quota before the originating
2535      * operation fails.
2536      *
2537      * Since: 1.1.14
2538      */
2539     webkit_web_view_signals[DATABASE_QUOTA_EXCEEDED] = g_signal_new("database-quota-exceeded",
2540             G_TYPE_FROM_CLASS(webViewClass),
2541             (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2542             0,
2543             NULL, NULL,
2544             webkit_marshal_VOID__OBJECT_OBJECT,
2545             G_TYPE_NONE, 2,
2546             G_TYPE_OBJECT, G_TYPE_OBJECT);
2547
2548     /**
2549      * WebKitWebView::resource-request-starting:
2550      * @webView: the object which received the signal
2551      * @web_frame: the #WebKitWebFrame whose load dispatched this request
2552      * @web_resource: an empty #WebKitWebResource object
2553      * @request: the #WebKitNetworkRequest that will be dispatched
2554      * @response: the #WebKitNetworkResponse representing the redirect
2555      * response, if any
2556      *
2557      * Emitted when a request is about to be sent. You can modify the
2558      * request while handling this signal. You can set the URI in the
2559      * #WebKitNetworkRequest object itself, and add/remove/replace
2560      * headers using the #SoupMessage object it carries, if it is
2561      * present. See webkit_network_request_get_message(). Setting the
2562      * request URI to "about:blank" will effectively cause the request
2563      * to load nothing, and can be used to disable the loading of
2564      * specific resources.
2565      *
2566      * Notice that information about an eventual redirect is available
2567      * in @response's #SoupMessage, not in the #SoupMessage carried by
2568      * the @request. If @response is %NULL, then this is not a
2569      * redirected request.
2570      *
2571      * The #WebKitWebResource object will be the same throughout all
2572      * the lifetime of the resource, but the contents may change from
2573      * inbetween signal emissions.
2574      *
2575      * Since: 1.1.14
2576      */
2577     webkit_web_view_signals[RESOURCE_REQUEST_STARTING] = g_signal_new("resource-request-starting",
2578             G_TYPE_FROM_CLASS(webViewClass),
2579             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2580             0,
2581             NULL, NULL,
2582             webkit_marshal_VOID__OBJECT_OBJECT_OBJECT_OBJECT,
2583             G_TYPE_NONE, 4,
2584             WEBKIT_TYPE_WEB_FRAME,
2585             WEBKIT_TYPE_WEB_RESOURCE,
2586             WEBKIT_TYPE_NETWORK_REQUEST,
2587             WEBKIT_TYPE_NETWORK_RESPONSE);
2588
2589     /**
2590      * WebKitWebView::geolocation-policy-decision-requested:
2591      * @webView: the object on which the signal is emitted
2592      * @frame: the frame that requests permission
2593      * @policy_decision: a WebKitGeolocationPolicyDecision
2594      *
2595      * This signal is emitted when a @frame wants to obtain the user's
2596      * location. The decision can be made asynchronously, but you must
2597      * call g_object_ref() the @policy_decision, and return %TRUE if
2598      * you are going to handle the request. To actually make the
2599      * decision you need to call webkit_geolocation_policy_allow() or
2600      * webkit_geolocation_policy_deny() on @policy_decision.
2601      *
2602      * Since: 1.1.23
2603      */
2604     webkit_web_view_signals[GEOLOCATION_POLICY_DECISION_REQUESTED] = g_signal_new("geolocation-policy-decision-requested",
2605             G_TYPE_FROM_CLASS(webViewClass),
2606             (GSignalFlags)(G_SIGNAL_RUN_LAST),
2607             0,
2608             NULL, NULL,
2609             webkit_marshal_BOOLEAN__OBJECT_OBJECT,
2610             G_TYPE_BOOLEAN, 2,
2611             WEBKIT_TYPE_WEB_FRAME,
2612             WEBKIT_TYPE_GEOLOCATION_POLICY_DECISION);
2613
2614     /**
2615      * WebKitWebView::geolocation-policy-decision-cancelled:
2616      * @webView: the object on which the signal is emitted
2617      * @frame: the frame that cancels geolocation request.
2618      *
2619      * When a @frame wants to cancel geolocation permission it had requested
2620      * before.
2621      *
2622      * Since: 1.1.23
2623      */
2624     webkit_web_view_signals[GEOLOCATION_POLICY_DECISION_CANCELLED] = g_signal_new("geolocation-policy-decision-cancelled",
2625             G_TYPE_FROM_CLASS(webViewClass),
2626             (GSignalFlags)(G_SIGNAL_RUN_LAST),
2627             0,
2628             NULL, NULL,
2629             g_cclosure_marshal_VOID__OBJECT,
2630             G_TYPE_NONE, 1,
2631             WEBKIT_TYPE_WEB_FRAME);
2632
2633     /*
2634      * DOM-related signals. These signals are experimental, for now,
2635      * and may change API and ABI. Their comments lack one * on
2636      * purpose, to make them not be catched by gtk-doc.
2637      */
2638
2639     /*
2640      * WebKitWebView::document-load-finished
2641      * @webView: the object which received the signal
2642      * @web_frame: the #WebKitWebFrame whose load dispatched this request
2643      *
2644      * Emitted when the DOM document object load is finished for the
2645      * given frame.
2646      */
2647     webkit_web_view_signals[DOCUMENT_LOAD_FINISHED] = g_signal_new("document-load-finished",
2648             G_TYPE_FROM_CLASS(webViewClass),
2649             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2650             0,
2651             NULL, NULL,
2652             g_cclosure_marshal_VOID__OBJECT,
2653             G_TYPE_NONE, 1,
2654             WEBKIT_TYPE_WEB_FRAME);
2655
2656     /*
2657      * WebKitWebView::frame-created
2658      * @webView: the object which received the signal
2659      * @web_frame: the #WebKitWebFrame which was just created.
2660      *
2661      * Emitted when a WebKitWebView has created a new frame. This signal will
2662      * be emitted for all sub-frames created during page load. It will not be
2663      * emitted for the main frame, which originates in the WebKitWebView constructor
2664      * and may be accessed at any time using webkit_web_view_get_main_frame.
2665      *
2666      * Since: 1.3.4
2667      */
2668     webkit_web_view_signals[FRAME_CREATED] = g_signal_new("frame-created",
2669             G_TYPE_FROM_CLASS(webViewClass),
2670             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2671             0,
2672             NULL, NULL,
2673             g_cclosure_marshal_VOID__OBJECT,
2674             G_TYPE_NONE, 1,
2675             WEBKIT_TYPE_WEB_FRAME);
2676
2677     webkit_web_view_signals[SHOULD_BEGIN_EDITING] = g_signal_new("should-begin-editing",
2678         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2679         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2680         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_RANGE);
2681
2682     webkit_web_view_signals[SHOULD_END_EDITING] = g_signal_new("should-end-editing", G_TYPE_FROM_CLASS(webViewClass),
2683         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2684         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2685         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_RANGE);
2686
2687     webkit_web_view_signals[SHOULD_INSERT_NODE] = g_signal_new("should-insert-node", G_TYPE_FROM_CLASS(webViewClass), 
2688         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2689         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2690         webkit_marshal_BOOLEAN__OBJECT_OBJECT_ENUM, G_TYPE_BOOLEAN,
2691         3, WEBKIT_TYPE_DOM_NODE, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_INSERT_ACTION);
2692
2693     webkit_web_view_signals[SHOULD_INSERT_TEXT] = g_signal_new("should-insert-text", G_TYPE_FROM_CLASS(webViewClass),
2694         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2695         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2696         webkit_marshal_BOOLEAN__STRING_OBJECT_ENUM, G_TYPE_BOOLEAN,
2697         3, G_TYPE_STRING, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_INSERT_ACTION);
2698
2699     webkit_web_view_signals[SHOULD_DELETE_RANGE] = g_signal_new("should-delete-range", G_TYPE_FROM_CLASS(webViewClass),
2700         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2701         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2702         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_RANGE);
2703
2704     webkit_web_view_signals[SHOULD_SHOW_DELETE_INTERFACE_FOR_ELEMENT] = g_signal_new("should-show-delete-interface-for-element",
2705         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2706         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2707         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_HTML_ELEMENT);
2708
2709     webkit_web_view_signals[SHOULD_CHANGE_SELECTED_RANGE] = g_signal_new("should-change-selected-range",
2710         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2711         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2712         webkit_marshal_BOOLEAN__OBJECT_OBJECT_ENUM_BOOLEAN, G_TYPE_BOOLEAN,
2713          4, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_SELECTION_AFFINITY, G_TYPE_BOOLEAN);
2714
2715     webkit_web_view_signals[SHOULD_APPLY_STYLE] = g_signal_new("should-apply-style",
2716         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2717         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
2718         webkit_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN,
2719          2, WEBKIT_TYPE_DOM_CSS_STYLE_DECLARATION, WEBKIT_TYPE_DOM_RANGE);
2720
2721     webkit_web_view_signals[EDITING_BEGAN] = g_signal_new("editing-began",
2722         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
2723         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2724
2725     webkit_web_view_signals[USER_CHANGED_CONTENTS] = g_signal_new("user-changed-contents",
2726         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
2727         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2728
2729     webkit_web_view_signals[EDITING_ENDED] = g_signal_new("editing-ended",
2730         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
2731         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2732
2733     webkit_web_view_signals[SELECTION_CHANGED] = g_signal_new("selection-changed",
2734         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
2735         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2736
2737     /*
2738      * implementations of virtual methods
2739      */
2740     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
2741     webViewClass->web_view_ready = webkit_web_view_real_web_view_ready;
2742     webViewClass->close_web_view = webkit_web_view_real_close_web_view;
2743     webViewClass->navigation_requested = webkit_web_view_real_navigation_requested;
2744     webViewClass->window_object_cleared = webkit_web_view_real_window_object_cleared;
2745     webViewClass->choose_file = webkit_web_view_real_choose_file;
2746     webViewClass->script_alert = webkit_web_view_real_script_alert;
2747     webViewClass->script_confirm = webkit_web_view_real_script_confirm;
2748     webViewClass->script_prompt = webkit_web_view_real_script_prompt;
2749     webViewClass->console_message = webkit_web_view_real_console_message;
2750     webViewClass->select_all = webkit_web_view_real_select_all;
2751     webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard;
2752     webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard;
2753     webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard;
2754     webViewClass->undo = webkit_web_view_real_undo;
2755     webViewClass->redo = webkit_web_view_real_redo;
2756     webViewClass->move_cursor = webkit_web_view_real_move_cursor;
2757     webViewClass->should_allow_editing_action = webkit_web_view_real_should_allow_editing_action;
2758
2759     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
2760     objectClass->dispose = webkit_web_view_dispose;
2761     objectClass->finalize = webkit_web_view_finalize;
2762     objectClass->get_property = webkit_web_view_get_property;
2763     objectClass->set_property = webkit_web_view_set_property;
2764
2765     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webViewClass);
2766     widgetClass->realize = webkit_web_view_realize;
2767 #ifdef GTK_API_VERSION_2
2768     widgetClass->expose_event = webkit_web_view_expose_event;
2769 #else
2770     widgetClass->draw = webkit_web_view_draw;
2771 #endif
2772     widgetClass->key_press_event = webkit_web_view_key_press_event;
2773     widgetClass->key_release_event = webkit_web_view_key_release_event;
2774     widgetClass->button_press_event = webkit_web_view_button_press_event;
2775     widgetClass->button_release_event = webkit_web_view_button_release_event;
2776     widgetClass->motion_notify_event = webkit_web_view_motion_event;
2777     widgetClass->scroll_event = webkit_web_view_scroll_event;
2778     widgetClass->size_allocate = webkit_web_view_size_allocate;
2779 #ifdef GTK_API_VERSION_2
2780     widgetClass->size_request = webkit_web_view_size_request;
2781 #else
2782     widgetClass->get_preferred_width = webkit_web_view_get_preferred_width;
2783     widgetClass->get_preferred_height = webkit_web_view_get_preferred_height;
2784 #endif
2785     widgetClass->popup_menu = webkit_web_view_popup_menu_handler;
2786     widgetClass->grab_focus = webkit_web_view_grab_focus;
2787     widgetClass->focus_in_event = webkit_web_view_focus_in_event;
2788     widgetClass->focus_out_event = webkit_web_view_focus_out_event;
2789     widgetClass->get_accessible = webkit_web_view_get_accessible;
2790     widgetClass->screen_changed = webkit_web_view_screen_changed;
2791     widgetClass->drag_end = webkit_web_view_drag_end;
2792     widgetClass->drag_data_get = webkit_web_view_drag_data_get;
2793     widgetClass->drag_motion = webkit_web_view_drag_motion;
2794     widgetClass->drag_leave = webkit_web_view_drag_leave;
2795     widgetClass->drag_drop = webkit_web_view_drag_drop;
2796     widgetClass->drag_data_received = webkit_web_view_drag_data_received;
2797 #if GTK_CHECK_VERSION(2, 12, 0)
2798     widgetClass->query_tooltip = webkit_web_view_query_tooltip;
2799     widgetClass->show_help = webkit_web_view_show_help;
2800 #endif
2801
2802     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
2803     containerClass->add = webkit_web_view_container_add;
2804     containerClass->remove = webkit_web_view_container_remove;
2805     containerClass->forall = webkit_web_view_container_forall;
2806
2807     /*
2808      * make us scrollable (e.g. addable to a GtkScrolledWindow)
2809      */
2810 #ifdef GTK_API_VERSION_2
2811     webViewClass->set_scroll_adjustments = webkit_web_view_set_scroll_adjustments;
2812     GTK_WIDGET_CLASS(webViewClass)->set_scroll_adjustments_signal = g_signal_new("set-scroll-adjustments",
2813             G_TYPE_FROM_CLASS(webViewClass),
2814             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
2815             G_STRUCT_OFFSET(WebKitWebViewClass, set_scroll_adjustments),
2816             NULL, NULL,
2817             webkit_marshal_VOID__OBJECT_OBJECT,
2818             G_TYPE_NONE, 2,
2819             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
2820 #else
2821     g_object_class_override_property(objectClass, PROP_HADJUSTMENT, "hadjustment");
2822     g_object_class_override_property(objectClass, PROP_VADJUSTMENT, "vadjustment");
2823     g_object_class_override_property(objectClass, PROP_HSCROLL_POLICY, "hscroll-policy");
2824     g_object_class_override_property(objectClass, PROP_VSCROLL_POLICY, "vscroll-policy");
2825 #endif
2826
2827     /*
2828      * Key bindings
2829      */
2830
2831     binding_set = gtk_binding_set_by_class(webViewClass);
2832
2833     gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
2834                                  "select_all", 0);
2835
2836     /* Cut/copy/paste */
2837
2838     gtk_binding_entry_add_signal(binding_set, GDK_x, GDK_CONTROL_MASK,
2839                                  "cut_clipboard", 0);
2840     gtk_binding_entry_add_signal(binding_set, GDK_c, GDK_CONTROL_MASK,
2841                                  "copy_clipboard", 0);
2842     gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK,
2843                                  "paste_clipboard", 0);
2844     gtk_binding_entry_add_signal(binding_set, GDK_z, GDK_CONTROL_MASK,
2845                                  "undo", 0);
2846     gtk_binding_entry_add_signal(binding_set, GDK_z, static_cast<GdkModifierType>(GDK_CONTROL_MASK | GDK_SHIFT_MASK),
2847                                  "redo", 0);
2848
2849     gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_SHIFT_MASK,
2850                                  "cut_clipboard", 0);
2851     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_CONTROL_MASK,
2852                                  "copy_clipboard", 0);
2853     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_SHIFT_MASK,
2854                                  "paste_clipboard", 0);
2855
2856     /* Movement */
2857     
2858     gtk_binding_entry_add_signal(binding_set, GDK_Down, static_cast<GdkModifierType>(0),
2859                                  "move-cursor", 2,
2860                                  G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINES,
2861                                  G_TYPE_INT, 1);
2862     gtk_binding_entry_add_signal(binding_set, GDK_Up, static_cast<GdkModifierType>(0),
2863                                  "move-cursor", 2,
2864                                  G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINES,
2865                                  G_TYPE_INT, -1);
2866     gtk_binding_entry_add_signal(binding_set, GDK_Right, static_cast<GdkModifierType>(0),
2867                                  "move-cursor", 2,
2868                                  G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
2869                                  G_TYPE_INT, 1);
2870     gtk_binding_entry_add_signal(binding_set, GDK_Left, static_cast<GdkModifierType>(0),
2871                                  "move-cursor", 2,
2872                                  G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
2873                                  G_TYPE_INT, -1);
2874     gtk_binding_entry_add_signal(binding_set, GDK_space, static_cast<GdkModifierType>(0),
2875                                  "move-cursor", 2,
2876                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
2877                                  G_TYPE_INT, 1);
2878     gtk_binding_entry_add_signal(binding_set, GDK_space, GDK_SHIFT_MASK,
2879                                  "move-cursor", 2,
2880                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
2881                                  G_TYPE_INT, -1);
2882     gtk_binding_entry_add_signal(binding_set, GDK_Page_Down, static_cast<GdkModifierType>(0),
2883                                  "move-cursor", 2,
2884                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
2885                                  G_TYPE_INT, 1);
2886     gtk_binding_entry_add_signal(binding_set, GDK_Page_Up, static_cast<GdkModifierType>(0),
2887                                  "move-cursor", 2,
2888                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
2889                                  G_TYPE_INT, -1);
2890     gtk_binding_entry_add_signal(binding_set, GDK_End, static_cast<GdkModifierType>(0),
2891                                  "move-cursor", 2,
2892                                  G_TYPE_ENUM, GTK_MOVEMENT_BUFFER_ENDS,
2893                                  G_TYPE_INT, 1);
2894     gtk_binding_entry_add_signal(binding_set, GDK_Home, static_cast<GdkModifierType>(0),
2895                                  "move-cursor", 2,
2896                                  G_TYPE_ENUM, GTK_MOVEMENT_BUFFER_ENDS,
2897                                  G_TYPE_INT, -1);
2898
2899     /*
2900      * properties
2901      */
2902
2903     /**
2904     * WebKitWebView:title:
2905     *
2906     * Returns the @web_view's document title.
2907     *
2908     * Since: 1.1.4
2909     */
2910     g_object_class_install_property(objectClass, PROP_TITLE,
2911                                     g_param_spec_string("title",
2912                                                         _("Title"),
2913                                                         _("Returns the @web_view's document title"),
2914                                                         NULL,
2915                                                         WEBKIT_PARAM_READABLE));
2916
2917     /**
2918     * WebKitWebView:uri:
2919     *
2920     * Returns the current URI of the contents displayed by the @web_view.
2921     *
2922     * Since: 1.1.4
2923     */
2924     g_object_class_install_property(objectClass, PROP_URI,
2925                                     g_param_spec_string("uri",
2926                                                         _("URI"),
2927                                                         _("Returns the current URI of the contents displayed by the @web_view"),
2928                                                         NULL,
2929                                                         WEBKIT_PARAM_READABLE));
2930
2931     /**
2932     * WebKitWebView:copy-target-list:
2933     *
2934     * The list of targets this web view supports for clipboard copying.
2935     *
2936     * Since: 1.0.2
2937     */
2938     g_object_class_install_property(objectClass, PROP_COPY_TARGET_LIST,
2939                                     g_param_spec_boxed("copy-target-list",
2940                                                        _("Copy target list"),
2941                                                        _("The list of targets this web view supports for clipboard copying"),
2942                                                        GTK_TYPE_TARGET_LIST,
2943                                                        WEBKIT_PARAM_READABLE));
2944
2945     /**
2946     * WebKitWebView:paste-target-list:
2947     *
2948     * The list of targets this web view supports for clipboard pasting.
2949     *
2950     * Since: 1.0.2
2951     */
2952     g_object_class_install_property(objectClass, PROP_PASTE_TARGET_LIST,
2953                                     g_param_spec_boxed("paste-target-list",
2954                                                        _("Paste target list"),
2955                                                        _("The list of targets this web view supports for clipboard pasting"),
2956                                                        GTK_TYPE_TARGET_LIST,
2957                                                        WEBKIT_PARAM_READABLE));
2958
2959     g_object_class_install_property(objectClass, PROP_SETTINGS,
2960                                     g_param_spec_object("settings",
2961                                                         _("Settings"),
2962                                                         _("An associated WebKitWebSettings instance"),
2963                                                         WEBKIT_TYPE_WEB_SETTINGS,
2964                                                         WEBKIT_PARAM_READWRITE));
2965
2966     /**
2967     * WebKitWebView:web-inspector:
2968     *
2969     * The associated WebKitWebInspector instance.
2970     *
2971     * Since: 1.0.3
2972     */
2973     g_object_class_install_property(objectClass, PROP_WEB_INSPECTOR,
2974                                     g_param_spec_object("web-inspector",
2975                                                         _("Web Inspector"),
2976                                                         _("The associated WebKitWebInspector instance"),
2977                                                         WEBKIT_TYPE_WEB_INSPECTOR,
2978                                                         WEBKIT_PARAM_READABLE));
2979
2980     /**
2981     * WebKitWebView:window-features:
2982     *
2983     * An associated WebKitWebWindowFeatures instance.
2984     *
2985     * Since: 1.0.3
2986     */
2987     g_object_class_install_property(objectClass, PROP_WINDOW_FEATURES,
2988                                     g_param_spec_object("window-features",
2989                                                         "Window Features",
2990                                                         "An associated WebKitWebWindowFeatures instance",
2991                                                         WEBKIT_TYPE_WEB_WINDOW_FEATURES,
2992                                                         WEBKIT_PARAM_READWRITE));
2993
2994     g_object_class_install_property(objectClass, PROP_EDITABLE,
2995                                     g_param_spec_boolean("editable",
2996                                                          _("Editable"),
2997                                                          _("Whether content can be modified by the user"),
2998                                                          FALSE,
2999                                                          WEBKIT_PARAM_READWRITE));
3000
3001     g_object_class_install_property(objectClass, PROP_TRANSPARENT,
3002                                     g_param_spec_boolean("transparent",
3003                                                          _("Transparent"),
3004                                                          _("Whether content has a transparent background"),
3005                                                          FALSE,
3006                                                          WEBKIT_PARAM_READWRITE));
3007
3008     /**
3009     * WebKitWebView:zoom-level:
3010     *
3011     * The level of zoom of the content.
3012     *
3013     * Since: 1.0.1
3014     */
3015     g_object_class_install_property(objectClass, PROP_ZOOM_LEVEL,
3016                                     g_param_spec_float("zoom-level",
3017                                                        _("Zoom level"),
3018                                                        _("The level of zoom of the content"),
3019                                                        G_MINFLOAT,
3020                                                        G_MAXFLOAT,
3021                                                        1.0f,
3022                                                        WEBKIT_PARAM_READWRITE));
3023
3024     /**
3025     * WebKitWebView:full-content-zoom:
3026     *
3027     * Whether the full content is scaled when zooming.
3028     *
3029     * Since: 1.0.1
3030     */
3031     g_object_class_install_property(objectClass, PROP_FULL_CONTENT_ZOOM,
3032                                     g_param_spec_boolean("full-content-zoom",
3033                                                          _("Full content zoom"),
3034                                                          _("Whether the full content is scaled when zooming"),
3035                                                          FALSE,
3036                                                          WEBKIT_PARAM_READWRITE));
3037
3038     /**
3039      * WebKitWebView:encoding:
3040      *
3041      * The default encoding of the web view.
3042      *
3043      * Since: 1.1.2
3044      */
3045     g_object_class_install_property(objectClass, PROP_ENCODING,
3046                                     g_param_spec_string("encoding",
3047                                                         _("Encoding"),
3048                                                         _("The default encoding of the web view"),
3049                                                         NULL,
3050                                                         WEBKIT_PARAM_READABLE));
3051
3052     /**
3053      * WebKitWebView:custom-encoding:
3054      *
3055      * The custom encoding of the web view.
3056      *
3057      * Since: 1.1.2
3058      */
3059     g_object_class_install_property(objectClass, PROP_CUSTOM_ENCODING,
3060                                     g_param_spec_string("custom-encoding",
3061                                                         _("Custom Encoding"),
3062                                                         _("The custom encoding of the web view"),
3063                                                         NULL,
3064                                                         WEBKIT_PARAM_READWRITE));
3065
3066     /**
3067     * WebKitWebView:load-status:
3068     *
3069     * Determines the current status of the load.
3070     *
3071     * Connect to "notify::load-status" to monitor loading.
3072     *
3073     * Some versions of WebKitGTK+ emitted this signal for the default
3074     * error page, while loading it. This behavior was considered bad,
3075     * because it was essentially exposing an implementation
3076     * detail. From 1.1.19 onwards this signal is no longer emitted for
3077     * the default error pages, but keep in mind that if you override
3078     * the error pages by using webkit_web_frame_load_alternate_string()
3079     * the signals will be emitted.
3080     *
3081     * Since: 1.1.7
3082     */
3083     g_object_class_install_property(objectClass, PROP_LOAD_STATUS,
3084                                     g_param_spec_enum("load-status",
3085                                                       "Load Status",
3086                                                       "Determines the current status of the load",
3087                                                       WEBKIT_TYPE_LOAD_STATUS,
3088                                                       WEBKIT_LOAD_FINISHED,
3089                                                       WEBKIT_PARAM_READABLE));
3090
3091     /**
3092     * WebKitWebView:progress:
3093     *
3094     * Determines the current progress of the load.
3095     *
3096     * Since: 1.1.7
3097     */
3098     g_object_class_install_property(objectClass, PROP_PROGRESS,
3099                                     g_param_spec_double("progress",
3100                                                         "Progress",
3101                                                         "Determines the current progress of the load",
3102                                                         0.0, 1.0, 1.0,
3103                                                         WEBKIT_PARAM_READABLE));
3104
3105     /**
3106      * WebKitWebView:icon-uri:
3107      *
3108      * The URI for the favicon for the #WebKitWebView.
3109      *
3110      * Since: 1.1.18
3111      */
3112     g_object_class_install_property(objectClass, PROP_ICON_URI,
3113                                     g_param_spec_string("icon-uri",
3114                                                         _("Icon URI"),
3115                                                         _("The URI for the favicon for the #WebKitWebView."),
3116                                                         NULL,
3117                                                         WEBKIT_PARAM_READABLE));
3118     /**
3119     * WebKitWebView:im-context:
3120     *
3121     * The GtkIMMulticontext for the #WebKitWebView.
3122     *
3123     * This is the input method context used for all text entry widgets inside
3124     * the #WebKitWebView. It can be used to generate context menu items for
3125     * controlling the active input method.
3126     *
3127     * Since: 1.1.20
3128     */
3129     g_object_class_install_property(objectClass, PROP_IM_CONTEXT,
3130                                     g_param_spec_object("im-context",
3131                                                         "IM Context",
3132                                                         "The GtkIMMultiContext for the #WebKitWebView.",
3133                                                         GTK_TYPE_IM_CONTEXT,
3134                                                         WEBKIT_PARAM_READABLE));
3135
3136     /**
3137     * WebKitWebView:view-mode:
3138     *
3139     * The "view-mode" media feature for the #WebKitWebView.
3140     *
3141     * The "view-mode" media feature is additional information for web
3142     * applications about how the application is running, when it comes
3143     * to user experience. Whether the application is running inside a
3144     * regular browser window, in a dedicated window, fullscreen, for
3145     * instance.
3146     *
3147     * This property stores a %WebKitWebViewViewMode value that matches
3148     * the "view-mode" media feature the web application will see.
3149     *
3150     * See http://www.w3.org/TR/view-mode/ for more information.
3151     *
3152     * Since: 1.3.4
3153     */
3154     g_object_class_install_property(objectClass, PROP_VIEW_MODE,
3155                                     g_param_spec_enum("view-mode",
3156                                                       "View Mode",
3157                                                       "The view-mode media feature for the #WebKitWebView.",
3158                                                       WEBKIT_TYPE_WEB_VIEW_VIEW_MODE,
3159                                                       WEBKIT_WEB_VIEW_VIEW_MODE_WINDOWED,
3160                                                       WEBKIT_PARAM_READWRITE));
3161
3162     g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
3163 }
3164
3165 static void webkit_web_view_update_settings(WebKitWebView* webView)
3166 {
3167     WebKitWebViewPrivate* priv = webView->priv;
3168     WebKitWebSettings* webSettings = priv->webSettings.get();
3169     Settings* settings = core(webView)->settings();
3170
3171     gchar* defaultEncoding, *cursiveFontFamily, *defaultFontFamily, *fantasyFontFamily, *monospaceFontFamily, *sansSerifFontFamily, *serifFontFamily, *userStylesheetUri;
3172     gboolean autoLoadImages, autoShrinkImages, printBackgrounds,
3173         enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas,
3174         enablePrivateBrowsing, enableCaretBrowsing, enableHTML5Database, enableHTML5LocalStorage,
3175         enableXSSAuditor, enableSpatialNavigation, enableFrameFlattening, javascriptCanOpenWindows,
3176         javaScriptCanAccessClipboard, enableOfflineWebAppCache,
3177         enableUniversalAccessFromFileURI, enableFileAccessFromFileURI,
3178         enableDOMPaste, tabKeyCyclesThroughElements,
3179         enableSiteSpecificQuirks, usePageCache, enableJavaApplet, enableHyperlinkAuditing;
3180
3181     WebKitEditingBehavior editingBehavior;
3182
3183     g_object_get(webSettings,
3184                  "default-encoding", &defaultEncoding,
3185                  "cursive-font-family", &cursiveFontFamily,
3186                  "default-font-family", &defaultFontFamily,
3187                  "fantasy-font-family", &fantasyFontFamily,
3188                  "monospace-font-family", &monospaceFontFamily,
3189                  "sans-serif-font-family", &sansSerifFontFamily,
3190                  "serif-font-family", &serifFontFamily,
3191                  "auto-load-images", &autoLoadImages,
3192                  "auto-shrink-images", &autoShrinkImages,
3193                  "print-backgrounds", &printBackgrounds,
3194                  "enable-scripts", &enableScripts,
3195                  "enable-plugins", &enablePlugins,
3196                  "resizable-text-areas", &resizableTextAreas,
3197                  "user-stylesheet-uri", &userStylesheetUri,
3198                  "enable-developer-extras", &enableDeveloperExtras,
3199                  "enable-private-browsing", &enablePrivateBrowsing,
3200                  "enable-caret-browsing", &enableCaretBrowsing,
3201                  "enable-html5-database", &enableHTML5Database,
3202                  "enable-html5-local-storage", &enableHTML5LocalStorage,
3203                  "enable-xss-auditor", &enableXSSAuditor,
3204                  "enable-spatial-navigation", &enableSpatialNavigation,
3205                  "enable-frame-flattening", &enableFrameFlattening,
3206                  "javascript-can-open-windows-automatically", &javascriptCanOpenWindows,
3207                  "javascript-can-access-clipboard", &javaScriptCanAccessClipboard,
3208                  "enable-offline-web-application-cache", &enableOfflineWebAppCache,
3209                  "editing-behavior", &editingBehavior,
3210                  "enable-universal-access-from-file-uris", &enableUniversalAccessFromFileURI,
3211                  "enable-file-access-from-file-uris", &enableFileAccessFromFileURI,
3212                  "enable-dom-paste", &enableDOMPaste,
3213                  "tab-key-cycles-through-elements", &tabKeyCyclesThroughElements,
3214                  "enable-site-specific-quirks", &enableSiteSpecificQuirks,
3215                  "enable-page-cache", &usePageCache,
3216                  "enable-java-applet", &enableJavaApplet,
3217                  "enable-hyperlink-auditing", &enableHyperlinkAuditing,
3218                  NULL);
3219
3220     settings->setDefaultTextEncodingName(defaultEncoding);
3221     settings->setCursiveFontFamily(cursiveFontFamily);
3222     settings->setStandardFontFamily(defaultFontFamily);
3223     settings->setFantasyFontFamily(fantasyFontFamily);
3224     settings->setFixedFontFamily(monospaceFontFamily);
3225     settings->setSansSerifFontFamily(sansSerifFontFamily);
3226     settings->setSerifFontFamily(serifFontFamily);
3227     settings->setLoadsImagesAutomatically(autoLoadImages);
3228     settings->setShrinksStandaloneImagesToFit(autoShrinkImages);
3229     settings->setShouldPrintBackgrounds(printBackgrounds);
3230     settings->setJavaScriptEnabled(enableScripts);
3231     settings->setPluginsEnabled(enablePlugins);
3232     settings->setTextAreasAreResizable(resizableTextAreas);
3233     settings->setUserStyleSheetLocation(KURL(KURL(), userStylesheetUri));
3234     settings->setDeveloperExtrasEnabled(enableDeveloperExtras);
3235     settings->setPrivateBrowsingEnabled(enablePrivateBrowsing);
3236     settings->setCaretBrowsingEnabled(enableCaretBrowsing);
3237 #if ENABLE(DATABASE)
3238     AbstractDatabase::setIsAvailable(enableHTML5Database);
3239 #endif
3240     settings->setLocalStorageEnabled(enableHTML5LocalStorage);
3241     settings->setXSSAuditorEnabled(enableXSSAuditor);
3242     settings->setSpatialNavigationEnabled(enableSpatialNavigation);
3243     settings->setFrameFlatteningEnabled(enableFrameFlattening);
3244     settings->setJavaScriptCanOpenWindowsAutomatically(javascriptCanOpenWindows);
3245     settings->setJavaScriptCanAccessClipboard(javaScriptCanAccessClipboard);
3246     settings->setOfflineWebApplicationCacheEnabled(enableOfflineWebAppCache);
3247     settings->setEditingBehaviorType(core(editingBehavior));
3248     settings->setAllowUniversalAccessFromFileURLs(enableUniversalAccessFromFileURI);
3249     settings->setAllowFileAccessFromFileURLs(enableFileAccessFromFileURI);
3250     settings->setDOMPasteAllowed(enableDOMPaste);
3251     settings->setNeedsSiteSpecificQuirks(enableSiteSpecificQuirks);
3252     settings->setUsesPageCache(usePageCache);
3253     settings->setJavaEnabled(enableJavaApplet);
3254     settings->setHyperlinkAuditingEnabled(enableHyperlinkAuditing);
3255
3256     Page* page = core(webView);
3257     if (page)
3258         page->setTabKeyCyclesThroughElements(tabKeyCyclesThroughElements);
3259
3260     g_free(defaultEncoding);
3261     g_free(cursiveFontFamily);
3262     g_free(defaultFontFamily);
3263     g_free(fantasyFontFamily);
3264     g_free(monospaceFontFamily);
3265     g_free(sansSerifFontFamily);
3266     g_free(serifFontFamily);
3267     g_free(userStylesheetUri);
3268
3269     webkit_web_view_screen_changed(GTK_WIDGET(webView), NULL);
3270 }
3271
3272 static inline gint pixelsFromSize(WebKitWebView* webView, gint size)
3273 {
3274     gdouble DPI = webViewGetDPI(webView);
3275     return size / 72.0 * DPI;
3276 }
3277
3278 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView)
3279 {
3280     Settings* settings = core(webView)->settings();
3281
3282     const gchar* name = g_intern_string(pspec->name);
3283     GValue value = { 0, { { 0 } } };
3284     g_value_init(&value, pspec->value_type);
3285     g_object_get_property(G_OBJECT(webSettings), name, &value);
3286
3287     if (name == g_intern_string("default-encoding"))
3288         settings->setDefaultTextEncodingName(g_value_get_string(&value));
3289     else if (name == g_intern_string("cursive-font-family"))
3290         settings->setCursiveFontFamily(g_value_get_string(&value));
3291     else if (name == g_intern_string("default-font-family"))
3292         settings->setStandardFontFamily(g_value_get_string(&value));
3293     else if (name == g_intern_string("fantasy-font-family"))
3294         settings->setFantasyFontFamily(g_value_get_string(&value));
3295     else if (name == g_intern_string("monospace-font-family"))
3296         settings->setFixedFontFamily(g_value_get_string(&value));
3297     else if (name == g_intern_string("sans-serif-font-family"))
3298         settings->setSansSerifFontFamily(g_value_get_string(&value));
3299     else if (name == g_intern_string("serif-font-family"))
3300         settings->setSerifFontFamily(g_value_get_string(&value));
3301     else if (name == g_intern_string("default-font-size"))
3302         settings->setDefaultFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
3303     else if (name == g_intern_string("default-monospace-font-size"))
3304         settings->setDefaultFixedFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
3305     else if (name == g_intern_string("minimum-font-size"))
3306         settings->setMinimumFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
3307     else if (name == g_intern_string("minimum-logical-font-size"))
3308         settings->setMinimumLogicalFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
3309     else if (name == g_intern_string("enforce-96-dpi"))
3310         webkit_web_view_screen_changed(GTK_WIDGET(webView), NULL);
3311     else if (name == g_intern_string("auto-load-images"))
3312         settings->setLoadsImagesAutomatically(g_value_get_boolean(&value));
3313     else if (name == g_intern_string("auto-shrink-images"))
3314         settings->setShrinksStandaloneImagesToFit(g_value_get_boolean(&value));
3315     else if (name == g_intern_string("print-backgrounds"))
3316         settings->setShouldPrintBackgrounds(g_value_get_boolean(&value));
3317     else if (name == g_intern_string("enable-scripts"))
3318         settings->setJavaScriptEnabled(g_value_get_boolean(&value));
3319     else if (name == g_intern_string("enable-plugins"))
3320         settings->setPluginsEnabled(g_value_get_boolean(&value));
3321     else if (name == g_intern_string("resizable-text-areas"))
3322         settings->setTextAreasAreResizable(g_value_get_boolean(&value));
3323     else if (name == g_intern_string("user-stylesheet-uri"))
3324         settings->setUserStyleSheetLocation(KURL(KURL(), g_value_get_string(&value)));
3325     else if (name == g_intern_string("enable-developer-extras"))
3326         settings->setDeveloperExtrasEnabled(g_value_get_boolean(&value));
3327     else if (name == g_intern_string("enable-private-browsing"))
3328         settings->setPrivateBrowsingEnabled(g_value_get_boolean(&value));
3329     else if (name == g_intern_string("enable-caret-browsing"))
3330         settings->setCaretBrowsingEnabled(g_value_get_boolean(&value));
3331 #if ENABLE(DATABASE)
3332     else if (name == g_intern_string("enable-html5-database")) {
3333         AbstractDatabase::setIsAvailable(g_value_get_boolean(&value));
3334     }
3335 #endif
3336     else if (name == g_intern_string("enable-html5-local-storage"))
3337         settings->setLocalStorageEnabled(g_value_get_boolean(&value));
3338     else if (name == g_intern_string("enable-xss-auditor"))
3339         settings->setXSSAuditorEnabled(g_value_get_boolean(&value));
3340     else if (name == g_intern_string("enable-spatial-navigation"))
3341         settings->setSpatialNavigationEnabled(g_value_get_boolean(&value));
3342     else if (name == g_intern_string("enable-frame-flattening"))
3343         settings->setFrameFlatteningEnabled(g_value_get_boolean(&value));
3344     else if (name == g_intern_string("javascript-can-open-windows-automatically"))
3345         settings->setJavaScriptCanOpenWindowsAutomatically(g_value_get_boolean(&value));
3346     else if (name == g_intern_string("javascript-can-access-clipboard"))