Allow retrieving the Soup session and modify the code to take
[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 Collabora Ltd.
10  *  Copyright (C) 2009 Igalia S.L.
11  *
12  *  This library is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public
14  *  License as published by the Free Software Foundation; either
15  *  version 2 of the License, or (at your option) any later version.
16  *
17  *  This library is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  *  Lesser General Public License for more details.
21  *
22  *  You should have received a copy of the GNU Lesser General Public
23  *  License along with this library; if not, write to the Free Software
24  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25  */
26
27 #include "config.h"
28
29 #include "webkitwebview.h"
30 #include "webkitenumtypes.h"
31 #include "webkitmarshal.h"
32 #include "webkitprivate.h"
33 #include "webkitwebinspector.h"
34 #include "webkitwebbackforwardlist.h"
35 #include "webkitwebhistoryitem.h"
36
37 #include "AXObjectCache.h"
38 #include "NotImplemented.h"
39 #include "BackForwardList.h"
40 #include "CString.h"
41 #include "ChromeClientGtk.h"
42 #include "ContextMenu.h"
43 #include "ContextMenuClientGtk.h"
44 #include "ContextMenuController.h"
45 #include "Cursor.h"
46 #include "Document.h"
47 #include "DragClientGtk.h"
48 #include "Editor.h"
49 #include "EditorClientGtk.h"
50 #include "EventHandler.h"
51 #include "FloatQuad.h"
52 #include "FocusController.h"
53 #include "FrameLoaderTypes.h"
54 #include "HitTestRequest.h"
55 #include "HitTestResult.h"
56 #include "GraphicsContext.h"
57 #include "InspectorClientGtk.h"
58 #include "FrameLoader.h"
59 #include "FrameView.h"
60 #include "PasteboardHelper.h"
61 #include "PlatformKeyboardEvent.h"
62 #include "PlatformWheelEvent.h"
63 #include "ResourceHandle.h"
64 #include "ScriptValue.h"
65 #include "Scrollbar.h"
66 #include <wtf/GOwnPtr.h>
67
68 #include <gdk/gdkkeysyms.h>
69
70 /**
71  * SECTION:webkitwebview
72  * @short_description: The central class of the WebKit/Gtk+ API
73  * @see_also: #WebKitWebSettings, #WebKitWebFrame
74  *
75  * #WebKitWebView is the central class of the WebKit/Gtk+ API. It is a
76  * #GtkWidget implementing the scrolling interface which means you can
77  * embed in a #GtkScrolledWindow. It is responsible for managing the
78  * drawing of the content, forwarding of events. You can load any URI
79  * into the #WebKitWebView or any kind of data string. With #WebKitWebSettings
80  * you can control various aspects of the rendering and loading of the content.
81  * Each #WebKitWebView has exactly one #WebKitWebFrame as main frame. A
82  * #WebKitWebFrame can have n children.
83  *
84  * <programlisting>
85  * /<!-- -->* Create the widgets *<!-- -->/
86  * GtkWidget *main_window = gtk_window_new (GTK_WIDGET_TOPLEVEL);
87  * GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
88  * GtkWidget *web_view = webkit_web_view_new ();
89  *
90  * /<!-- -->* Place the WebKitWebView in the GtkScrolledWindow *<!-- -->/
91  * gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
92  * gtk_container_add (GTK_CONTAINER (main_window), scrolled_window);
93  *
94  * /<!-- -->* Open a webpage *<!-- -->/
95  * webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), "http://www.gnome.org");
96  *
97  * /<!-- -->* Show the result *<!-- -->/
98  * gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);
99  * gtk_widget_show_all (main_window);
100  * </programlisting>
101  */
102
103 static const double defaultDPI = 96.0;
104
105 using namespace WebKit;
106 using namespace WebCore;
107
108 extern "C" {
109
110 enum {
111     /* normal signals */
112     NAVIGATION_REQUESTED,
113     NAVIGATION_POLICY_DECISION_REQUESTED,
114     MIME_TYPE_POLICY_DECISION_REQUESTED,
115     CREATE_WEB_VIEW,
116     WEB_VIEW_READY,
117     WINDOW_OBJECT_CLEARED,
118     LOAD_STARTED,
119     LOAD_COMMITTED,
120     LOAD_PROGRESS_CHANGED,
121     LOAD_FINISHED,
122     TITLE_CHANGED,
123     HOVERING_OVER_LINK,
124     POPULATE_POPUP,
125     STATUS_BAR_TEXT_CHANGED,
126     ICOND_LOADED,
127     SELECTION_CHANGED,
128     CONSOLE_MESSAGE,
129     SCRIPT_ALERT,
130     SCRIPT_CONFIRM,
131     SCRIPT_PROMPT,
132     SELECT_ALL,
133     COPY_CLIPBOARD,
134     PASTE_CLIPBOARD,
135     CUT_CLIPBOARD,
136     LAST_SIGNAL
137 };
138
139 enum {
140     PROP_0,
141
142     PROP_COPY_TARGET_LIST,
143     PROP_PASTE_TARGET_LIST,
144     PROP_EDITABLE,
145     PROP_SETTINGS,
146     PROP_WEB_INSPECTOR,
147     PROP_WINDOW_FEATURES,
148     PROP_TRANSPARENT,
149     PROP_ZOOM_LEVEL,
150     PROP_FULL_CONTENT_ZOOM
151 };
152
153 static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };
154
155 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
156
157 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView);
158 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures);
159
160 static void webkit_web_view_context_menu_position_func(GtkMenu*, gint* x, gint* y, gboolean* pushIn, WebKitWebViewPrivate* data)
161 {
162     *pushIn = FALSE;
163     *x = data->lastPopupXPosition;
164     *y = data->lastPopupYPosition;
165 }
166
167 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
168 {
169     Page* page = core(webView);
170     page->contextMenuController()->clearContextMenu();
171     Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
172
173     if (!focusedFrame->view())
174         return FALSE;
175
176     focusedFrame->view()->setCursor(pointerCursor());
177     bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
178     if (!handledEvent)
179         return FALSE;
180
181     ContextMenu* coreMenu = page->contextMenuController()->contextMenu();
182     if (!coreMenu)
183         return FALSE;
184
185     GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
186     if (!menu)
187         return FALSE;
188
189     g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
190
191     GList* items = gtk_container_get_children(GTK_CONTAINER(menu));
192     bool empty = !g_list_nth(items, 0);
193     g_list_free(items);
194     if (empty)
195         return FALSE;
196
197     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
198     priv->lastPopupXPosition = event.globalX();
199     priv->lastPopupYPosition = event.globalY();
200     gtk_menu_popup(menu, NULL, NULL,
201                    reinterpret_cast<GtkMenuPositionFunc>(webkit_web_view_context_menu_position_func),
202                    priv, event.button() + 1, gtk_get_current_event_time());
203     return TRUE;
204 }
205
206 static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
207 {
208     static const int contextMenuMargin = 1;
209
210     // The context menu event was generated from the keyboard, so show the context menu by the current selection.
211     Page* page = core(WEBKIT_WEB_VIEW(widget));
212     FrameView* view = page->mainFrame()->view();
213     if (!view)
214         return FALSE;    
215
216     Position start = page->mainFrame()->selection()->selection().start();
217     Position end = page->mainFrame()->selection()->selection().end();
218
219     int rightAligned = FALSE;
220     IntPoint location;
221
222     if (!start.node() || !end.node())
223         location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
224     else {
225         RenderObject* renderer = start.node()->renderer();
226         if (!renderer)
227             return FALSE;
228
229         // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:],
230         // now Frame::firstRectForRange(), which perhaps this should call).
231         int extraWidthToEndOfLine = 0;
232
233         InlineBox* startInlineBox;
234         int startCaretOffset;
235         start.getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
236         IntRect startCaretRect = renderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
237         if (startCaretRect != IntRect())
238             startCaretRect = renderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox();
239
240         InlineBox* endInlineBox;
241         int endCaretOffset;
242         end.getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
243         IntRect endCaretRect = renderer->localCaretRect(endInlineBox, endCaretOffset);
244         if (endCaretRect != IntRect())
245             endCaretRect = renderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox();
246
247         IntRect firstRect;
248         if (startCaretRect.y() == endCaretRect.y())
249             firstRect = IntRect(MIN(startCaretRect.x(), endCaretRect.x()),
250                                 startCaretRect.y(),
251                                 abs(endCaretRect.x() - startCaretRect.x()),
252                                 MAX(startCaretRect.height(), endCaretRect.height()));
253         else
254             firstRect = IntRect(startCaretRect.x(),
255                                 startCaretRect.y(),
256                                 startCaretRect.width() + extraWidthToEndOfLine,
257                                 startCaretRect.height());
258
259         location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
260     }
261
262     int x, y;
263     gdk_window_get_origin(GTK_WIDGET(view->hostWindow()->platformWindow())->window, &x, &y);
264
265     // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
266     // Ideally we'd have the position of a context menu event be separate from its target node.
267     location = view->contentsToWindow(location) + IntSize(0, -1);
268     IntPoint global = location + IntSize(x, y);
269     PlatformMouseEvent event(location, global, NoButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
270
271     return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
272 }
273
274 static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
275 {
276     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
277
278     switch(prop_id) {
279 #if GTK_CHECK_VERSION(2,10,0)
280     case PROP_COPY_TARGET_LIST:
281         g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView));
282         break;
283     case PROP_PASTE_TARGET_LIST:
284         g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView));
285         break;
286 #endif
287     case PROP_EDITABLE:
288         g_value_set_boolean(value, webkit_web_view_get_editable(webView));
289         break;
290     case PROP_SETTINGS:
291         g_value_set_object(value, webkit_web_view_get_settings(webView));
292         break;
293     case PROP_WEB_INSPECTOR:
294         g_value_set_object(value, webkit_web_view_get_inspector(webView));
295         break;
296     case PROP_WINDOW_FEATURES:
297         g_value_set_object(value, webkit_web_view_get_window_features(webView));
298         break;
299     case PROP_TRANSPARENT:
300         g_value_set_boolean(value, webkit_web_view_get_transparent(webView));
301         break;
302     case PROP_ZOOM_LEVEL:
303         g_value_set_float(value, webkit_web_view_get_zoom_level(webView));
304         break;
305     case PROP_FULL_CONTENT_ZOOM:
306         g_value_set_boolean(value, webkit_web_view_get_full_content_zoom(webView));
307         break;
308     default:
309         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
310     }
311 }
312
313 static void webkit_web_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec)
314 {
315     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
316
317     switch(prop_id) {
318     case PROP_EDITABLE:
319         webkit_web_view_set_editable(webView, g_value_get_boolean(value));
320         break;
321     case PROP_SETTINGS:
322         webkit_web_view_set_settings(webView, WEBKIT_WEB_SETTINGS(g_value_get_object(value)));
323         break;
324     case PROP_WINDOW_FEATURES:
325         webkit_web_view_set_window_features(webView, WEBKIT_WEB_WINDOW_FEATURES(g_value_get_object(value)));
326         break;
327     case PROP_TRANSPARENT:
328         webkit_web_view_set_transparent(webView, g_value_get_boolean(value));
329         break;
330     case PROP_ZOOM_LEVEL:
331         webkit_web_view_set_zoom_level(webView, g_value_get_float(value));
332         break;
333     case PROP_FULL_CONTENT_ZOOM:
334         webkit_web_view_set_full_content_zoom(webView, g_value_get_boolean(value));
335         break;
336     default:
337         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
338     }
339 }
340
341 static bool shouldCoalesce(GdkRectangle rect, GdkRectangle* rects, int count)
342 {
343     const int cRectThreshold = 10;
344     const float cWastedSpaceThreshold = 0.75f;
345     bool useUnionedRect = (count <= 1) || (count > cRectThreshold);
346     if (!useUnionedRect) {
347         // Attempt to guess whether or not we should use the unioned rect or the individual rects.
348         // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
349         // is too large, then we will do individual rect painting instead.
350         float unionPixels = (rect.width * rect.height);
351         float singlePixels = 0;
352         for (int i = 0; i < count; ++i)
353             singlePixels += rects[i].width * rects[i].height;
354         float wastedSpace = 1 - (singlePixels / unionPixels);
355         if (wastedSpace <= cWastedSpaceThreshold)
356             useUnionedRect = true;
357     }
358     return useUnionedRect;
359 }
360
361 static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
362 {
363     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
364     WebKitWebViewPrivate* priv = webView->priv;
365
366     Frame* frame = core(webView)->mainFrame();
367     if (frame->contentRenderer() && frame->view()) {
368         frame->view()->layoutIfNeededRecursive();
369
370         cairo_t* cr = gdk_cairo_create(event->window);
371         GraphicsContext ctx(cr);
372         cairo_destroy(cr);
373         ctx.setGdkExposeEvent(event);
374
375         GOwnPtr<GdkRectangle> rects;
376         int rectCount;
377         gdk_region_get_rectangles(event->region, &rects.outPtr(), &rectCount);
378
379         // Avoid recursing into the render tree excessively
380         bool coalesce = shouldCoalesce(event->area, rects.get(), rectCount);
381
382         if (coalesce) {
383             IntRect rect = event->area;
384             ctx.clip(rect);
385             if (priv->transparent)
386                 ctx.clearRect(rect);
387             frame->view()->paint(&ctx, rect);
388         } else {
389             for (int i = 0; i < rectCount; i++) {
390                 IntRect rect = rects.get()[i];
391                 ctx.save();
392                 ctx.clip(rect);
393                 if (priv->transparent)
394                     ctx.clearRect(rect);
395                 frame->view()->paint(&ctx, rect);
396                 ctx.restore();
397             }
398         }
399     }
400
401     return FALSE;
402 }
403
404 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event)
405 {
406     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
407
408     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
409     PlatformKeyboardEvent keyboardEvent(event);
410
411     if (!frame->view())
412         return FALSE;
413
414     if (frame->eventHandler()->keyEvent(keyboardEvent))
415         return TRUE;
416
417     FrameView* view = frame->view();
418     SelectionController::EAlteration alteration;
419     if (event->state & GDK_SHIFT_MASK)
420         alteration = SelectionController::EXTEND;
421     else
422         alteration = SelectionController::MOVE;
423
424     // TODO: We probably want to use GTK+ key bindings here and perhaps take an
425     // approach more like the Win and Mac ports for key handling.
426     switch (event->keyval) {
427     case GDK_Down:
428         view->scrollBy(IntSize(0, cScrollbarPixelsPerLineStep));
429         return TRUE;
430     case GDK_Up:
431         view->scrollBy(IntSize(0, -cScrollbarPixelsPerLineStep));
432         return TRUE;
433     case GDK_Right:
434         view->scrollBy(IntSize(cScrollbarPixelsPerLineStep, 0));
435         return TRUE;
436     case GDK_Left:
437         view->scrollBy(IntSize(-cScrollbarPixelsPerLineStep, 0));
438         return TRUE;
439     case GDK_Home:
440         frame->selection()->modify(alteration, SelectionController::BACKWARD, DocumentBoundary, true);
441         return TRUE;
442     case GDK_End:
443         frame->selection()->modify(alteration, SelectionController::FORWARD, DocumentBoundary, true);
444         return TRUE;
445     }
446
447     /* Chain up to our parent class for binding activation */
448     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event);
449 }
450
451 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event)
452 {
453     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
454
455     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
456     if (!frame->view())
457         return FALSE;
458
459     PlatformKeyboardEvent keyboardEvent(event);
460
461     if (frame->eventHandler()->keyEvent(keyboardEvent))
462         return TRUE;
463
464     /* Chain up to our parent class for binding activation */
465     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event);
466 }
467
468 static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventButton* event)
469 {
470     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
471
472     // FIXME: need to keep track of subframe focus for key events
473     gtk_widget_grab_focus(widget);
474
475     if (event->button == 3)
476         return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
477
478     Frame* frame = core(webView)->mainFrame();
479     if (!frame->view())
480         return FALSE;
481
482     return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
483 }
484
485 static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEventButton* event)
486 {
487     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
488
489     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
490
491     if (focusedFrame && focusedFrame->editor()->canEdit()) {
492 #ifdef MAEMO_CHANGES
493         WebKitWebViewPrivate* priv = webView->priv;
494         hildon_gtk_im_context_filter_event(priv->imContext, (GdkEvent*)event);
495 #endif
496     }
497
498     Frame* mainFrame = core(webView)->mainFrame();
499     if (!mainFrame->view())
500         return FALSE;
501
502     return mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
503 }
504
505 static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event)
506 {
507     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
508
509     Frame* frame = core(webView)->mainFrame();
510     if (!frame->view())
511         return FALSE;
512
513     return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
514 }
515
516 static gboolean webkit_web_view_scroll_event(GtkWidget* widget, GdkEventScroll* event)
517 {
518     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
519
520     Frame* frame = core(webView)->mainFrame();
521     if (!frame->view())
522         return FALSE;
523
524     PlatformWheelEvent wheelEvent(event);
525     return frame->eventHandler()->handleWheelEvent(wheelEvent);
526 }
527
528 static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
529 {
530     GTK_WIDGET_CLASS(webkit_web_view_parent_class)->size_allocate(widget,allocation);
531
532     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
533
534     Frame* frame = core(webView)->mainFrame();
535     if (!frame->view())
536         return;
537
538     frame->view()->resize(allocation->width, allocation->height);
539     frame->view()->forceLayout();
540     frame->view()->adjustViewSize();
541 }
542
543 static gboolean webkit_web_view_focus_in_event(GtkWidget* widget, GdkEventFocus* event)
544 {
545     // TODO: Improve focus handling as suggested in
546     // http://bugs.webkit.org/show_bug.cgi?id=16910
547     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
548     if (GTK_WIDGET_TOPLEVEL(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {
549         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
550
551         Frame* frame = core(webView)->mainFrame();
552         core(webView)->focusController()->setActive(frame);
553     }
554     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event);
555 }
556
557 static gboolean webkit_web_view_focus_out_event(GtkWidget* widget, GdkEventFocus* event)
558 {
559     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
560
561     core(webView)->focusController()->setActive(false);
562
563     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_out_event(widget, event);
564 }
565
566 static void webkit_web_view_realize(GtkWidget* widget)
567 {
568     GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
569
570     GdkWindowAttr attributes;
571     attributes.window_type = GDK_WINDOW_CHILD;
572     attributes.x = widget->allocation.x;
573     attributes.y = widget->allocation.y;
574     attributes.width = widget->allocation.width;
575     attributes.height = widget->allocation.height;
576     attributes.wclass = GDK_INPUT_OUTPUT;
577     attributes.visual = gtk_widget_get_visual (widget);
578     attributes.colormap = gtk_widget_get_colormap (widget);
579     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
580                             | GDK_EXPOSURE_MASK
581                             | GDK_BUTTON_PRESS_MASK
582                             | GDK_BUTTON_RELEASE_MASK
583                             | GDK_POINTER_MOTION_MASK
584                             | GDK_KEY_PRESS_MASK
585                             | GDK_KEY_RELEASE_MASK
586                             | GDK_BUTTON_MOTION_MASK
587                             | GDK_BUTTON1_MOTION_MASK
588                             | GDK_BUTTON2_MOTION_MASK
589                             | GDK_BUTTON3_MOTION_MASK;
590
591     gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
592     widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
593     gdk_window_set_user_data(widget->window, widget);
594
595     widget->style = gtk_style_attach(widget->style, widget->window);
596     gdk_window_set_background(widget->window, &widget->style->base[GTK_WIDGET_STATE(widget)]);
597
598     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
599     WebKitWebViewPrivate* priv = webView->priv;
600     gtk_im_context_set_client_window(priv->imContext, widget->window);
601 }
602
603 static void webkit_web_view_set_scroll_adjustments(WebKitWebView* webView, GtkAdjustment* hadj, GtkAdjustment* vadj)
604 {
605     if (!core(webView))
606         return;
607
608     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
609
610     if (hadj)
611         g_object_ref(hadj);
612     if (vadj)
613         g_object_ref(vadj);
614
615     WebKitWebViewPrivate* priv = webView->priv;
616
617     if (priv->horizontalAdjustment)
618         g_object_unref(priv->horizontalAdjustment);
619     if (priv->verticalAdjustment)
620         g_object_unref(priv->verticalAdjustment);
621
622     priv->horizontalAdjustment = hadj;
623     priv->verticalAdjustment = vadj;
624
625     if (!view)
626         return;
627
628     view->setGtkAdjustments(hadj, vadj);
629 }
630
631 static void webkit_web_view_container_add(GtkContainer* container, GtkWidget* widget)
632 {
633     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
634     WebKitWebViewPrivate* priv = webView->priv;
635
636     priv->children.add(widget);
637     if (GTK_WIDGET_REALIZED(container))
638         gtk_widget_set_parent_window(widget, GTK_WIDGET(webView)->window);
639     gtk_widget_set_parent(widget, GTK_WIDGET(container));
640 }
641
642 static void webkit_web_view_container_remove(GtkContainer* container, GtkWidget* widget)
643 {
644     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
645     WebKitWebViewPrivate* priv = webView->priv;
646
647     if (priv->children.contains(widget)) {
648         gtk_widget_unparent(widget);
649         priv->children.remove(widget);
650     }
651 }
652
653 static void webkit_web_view_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
654 {
655     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
656     WebKitWebViewPrivate* priv = webView->priv;
657
658     HashSet<GtkWidget*> children = priv->children;
659     HashSet<GtkWidget*>::const_iterator end = children.end();
660     for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
661         (*callback)(*current, callbackData);
662 }
663
664 static WebKitWebView* webkit_web_view_real_create_web_view(WebKitWebView*, WebKitWebFrame*)
665 {
666     return 0;
667 }
668
669 static gboolean webkit_web_view_real_web_view_ready(WebKitWebView*)
670 {
671     return FALSE;
672 }
673
674 static WebKitNavigationResponse webkit_web_view_real_navigation_requested(WebKitWebView*, WebKitWebFrame*, WebKitNetworkRequest*)
675 {
676     return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
677 }
678
679 static void webkit_web_view_real_window_object_cleared(WebKitWebView*, WebKitWebFrame*, JSGlobalContextRef context, JSObjectRef window_object)
680 {
681     notImplemented();
682 }
683
684 static gchar* webkit_web_view_real_choose_file(WebKitWebView*, WebKitWebFrame*, const gchar* old_name)
685 {
686     notImplemented();
687     return g_strdup(old_name);
688 }
689
690 typedef enum {
691     WEBKIT_SCRIPT_DIALOG_ALERT,
692     WEBKIT_SCRIPT_DIALOG_CONFIRM,
693     WEBKIT_SCRIPT_DIALOG_PROMPT
694  } WebKitScriptDialogType;
695
696 static gboolean webkit_web_view_script_dialog(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
697 {
698     GtkMessageType messageType;
699     GtkButtonsType buttons;
700     gint defaultResponse;
701     GtkWidget* window;
702     GtkWidget* dialog;
703     GtkWidget* entry = 0;
704     gboolean didConfirm = FALSE;
705
706     switch (type) {
707     case WEBKIT_SCRIPT_DIALOG_ALERT:
708         messageType = GTK_MESSAGE_WARNING;
709         buttons = GTK_BUTTONS_CLOSE;
710         defaultResponse = GTK_RESPONSE_CLOSE;
711         break;
712     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
713         messageType = GTK_MESSAGE_QUESTION;
714         buttons = GTK_BUTTONS_YES_NO;
715         defaultResponse = GTK_RESPONSE_YES;
716         break;
717     case WEBKIT_SCRIPT_DIALOG_PROMPT:
718         messageType = GTK_MESSAGE_QUESTION;
719         buttons = GTK_BUTTONS_OK_CANCEL;
720         defaultResponse = GTK_RESPONSE_OK;
721         break;
722     default:
723         g_warning("Unknown value for WebKitScriptDialogType.");
724         return FALSE;
725     }
726
727     window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
728     dialog = gtk_message_dialog_new(GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
729     gchar* title = g_strconcat("JavaScript - ", webkit_web_frame_get_uri(frame), NULL);
730     gtk_window_set_title(GTK_WINDOW(dialog), title);
731     g_free(title);
732
733     if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
734         entry = gtk_entry_new();
735         gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
736         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
737         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
738         gtk_widget_show(entry);
739     }
740
741     gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
742     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
743
744     switch (response) {
745     case GTK_RESPONSE_YES:
746         didConfirm = TRUE;
747         break;
748     case GTK_RESPONSE_OK:
749         didConfirm = TRUE;
750         if (entry)
751             *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
752         else
753             *value = 0;
754         break;
755     case GTK_RESPONSE_NO:
756     case GTK_RESPONSE_CANCEL:
757         didConfirm = FALSE;
758         break;
759
760     }
761     gtk_widget_destroy(GTK_WIDGET(dialog));
762     return didConfirm;
763 }
764
765 static gboolean webkit_web_view_real_script_alert(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message)
766 {
767     webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
768     return TRUE;
769 }
770
771 static gboolean webkit_web_view_real_script_confirm(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm)
772 {
773     *didConfirm = webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
774     return TRUE;
775 }
776
777 static gboolean webkit_web_view_real_script_prompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
778 {
779     if (!webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
780         *value = NULL;
781     return TRUE;
782 }
783
784 static gboolean webkit_web_view_real_console_message(WebKitWebView* webView, const gchar* message, unsigned int line, const gchar* sourceId)
785 {
786     g_print("console message: %s @%d: %s\n", sourceId, line, message);
787     return TRUE;
788 }
789
790 static void webkit_web_view_real_select_all(WebKitWebView* webView)
791 {
792     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
793     frame->editor()->command("SelectAll").execute();
794 }
795
796 static void webkit_web_view_real_cut_clipboard(WebKitWebView* webView)
797 {
798     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
799     frame->editor()->command("Cut").execute();
800 }
801
802 static void webkit_web_view_real_copy_clipboard(WebKitWebView* webView)
803 {
804     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
805     frame->editor()->command("Copy").execute();
806 }
807
808 static void webkit_web_view_real_paste_clipboard(WebKitWebView* webView)
809 {
810     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
811     frame->editor()->command("Paste").execute();
812 }
813
814 static void webkit_web_view_dispose(GObject* object)
815 {
816     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
817     WebKitWebViewPrivate* priv = webView->priv;
818
819     if (priv->corePage) {
820         webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object));
821
822         core(priv->mainFrame)->loader()->detachChildren();
823         delete priv->corePage;
824         priv->corePage = NULL;
825     }
826
827     if (priv->horizontalAdjustment) {
828         g_object_unref(priv->horizontalAdjustment);
829         priv->horizontalAdjustment = NULL;
830     }
831
832     if (priv->verticalAdjustment) {
833         g_object_unref(priv->verticalAdjustment);
834         priv->verticalAdjustment = NULL;
835     }
836
837     if (priv->backForwardList) {
838         g_object_unref(priv->backForwardList);
839         priv->backForwardList = NULL;
840
841         g_signal_handlers_disconnect_by_func(priv->webSettings, (gpointer)webkit_web_view_settings_notify, webView);
842         g_object_unref(priv->webSettings);
843         priv->webSettings = NULL;
844
845         g_object_unref(priv->webInspector);
846         priv->webInspector = NULL;
847
848         g_object_unref(priv->webWindowFeatures);
849         priv->webWindowFeatures = NULL;
850
851         g_object_unref(priv->imContext);
852         priv->imContext = NULL;
853
854         gtk_target_list_unref(priv->copy_target_list);
855         priv->copy_target_list = NULL;
856
857         gtk_target_list_unref(priv->paste_target_list);
858         priv->paste_target_list = NULL;
859
860         delete priv->userAgent;
861         priv->userAgent = NULL;
862     }
863
864     G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object);
865 }
866
867 static gboolean webkit_create_web_view_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
868 {
869     gpointer newWebView = g_value_get_object(handlerReturn);
870     g_value_set_object(returnAccu, newWebView);
871
872     // Continue if we don't have a newWebView
873     return !newWebView;
874 }
875
876 static gboolean webkit_navigation_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
877 {
878     WebKitNavigationResponse navigationResponse = (WebKitNavigationResponse)g_value_get_enum(handlerReturn);
879     g_value_set_enum(returnAccu, navigationResponse);
880
881     if (navigationResponse != WEBKIT_NAVIGATION_RESPONSE_ACCEPT)
882         return FALSE;
883
884     return TRUE;
885 }
886
887 static AtkObject* webkit_web_view_get_accessible(GtkWidget* widget)
888 {
889     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
890     if (!core(webView))
891         return NULL;
892
893     AXObjectCache::enableAccessibility();
894
895     Frame* coreFrame = core(webView)->mainFrame();
896     if (!coreFrame)
897         return NULL;
898
899     Document* doc = coreFrame->document();
900     if (!doc)
901         return NULL;
902
903     AccessibilityObject* coreAccessible = doc->axObjectCache()->get(doc->renderer());
904     if (!coreAccessible || !coreAccessible->wrapper())
905         return NULL;
906
907     return coreAccessible->wrapper();
908 }
909
910 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
911 {
912     GtkBindingSet* binding_set;
913
914     webkit_init();
915
916     /*
917      * Signals
918      */
919
920     /**
921      * WebKitWebView::create-web-view:
922      * @web_view: the object on which the signal is emitted
923      * @frame: the #WebKitWebFrame
924      * @return: a newly allocated #WebKitWebView or %NULL
925      *
926      * Emitted when the creation of a new window is requested.
927      * If this signal is handled the signal handler should return the
928      * newly created #WebKitWebView.
929      *
930      * The new #WebKitWebView should not be displayed to the user
931      * until the #WebKitWebView::web-view-ready signal is emitted.
932      *
933      * The signal handlers should not try to deal with the reference
934      * count for the new #WebKitWebView. The widget to which the
935      * widget is added will handle that.
936      *
937      * Since 1.0.3
938      */
939     webkit_web_view_signals[CREATE_WEB_VIEW] = g_signal_new("create-web-view",
940             G_TYPE_FROM_CLASS(webViewClass),
941             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
942             G_STRUCT_OFFSET (WebKitWebViewClass, create_web_view),
943             webkit_create_web_view_request_handled,
944             NULL,
945             webkit_marshal_OBJECT__OBJECT,
946             WEBKIT_TYPE_WEB_VIEW , 1,
947             WEBKIT_TYPE_WEB_FRAME);
948
949     /**
950      * WebKitWebView::web-view-ready:
951      * @web_view: the object on which the signal is emitted
952      * @return: %TRUE to stop other handlers from being invoked for
953      * the event, %FALSE to propagate the event further
954      *
955      * Emitted after #WebKitWebView::create-web-view when the new #WebKitWebView
956      * should be displayed to the user. When this signal is emitted
957      * all the information about how the window should look, including
958      * size, position, whether the location, status and scroll bars
959      * should be displayed, is already set on the
960      * #WebKitWebWindowFeatures object contained by the #WebKitWebView.
961      *
962      * Notice that some of that information may change during the life
963      * time of the window, so you may want to connect to the ::notify
964      * signal of the #WebKitWebWindowFeatures object to handle those.
965      *
966      * Since 1.0.3
967      */
968     webkit_web_view_signals[WEB_VIEW_READY] = g_signal_new("web-view-ready",
969             G_TYPE_FROM_CLASS(webViewClass),
970             (GSignalFlags)(G_SIGNAL_RUN_LAST),
971             G_STRUCT_OFFSET (WebKitWebViewClass, web_view_ready),
972             g_signal_accumulator_true_handled,
973             NULL,
974             webkit_marshal_BOOLEAN__VOID,
975             G_TYPE_BOOLEAN, 0);
976
977     /**
978      * WebKitWebView::navigation-requested:
979      * @web_view: the object on which the signal is emitted
980      * @frame: the #WebKitWebFrame that required the navigation
981      * @request: a #WebKitNetworkRequest
982      * @return: a WebKitNavigationResponse
983      *
984      * Emitted when @frame requests a navigation to another page.
985      *
986      * Deprecated: Use WebKitWebView::navigation-policy-decision-requested
987      * instead
988      */
989     webkit_web_view_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation-requested",
990             G_TYPE_FROM_CLASS(webViewClass),
991             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
992             G_STRUCT_OFFSET (WebKitWebViewClass, navigation_requested),
993             webkit_navigation_request_handled,
994             NULL,
995             webkit_marshal_ENUM__OBJECT_OBJECT,
996             WEBKIT_TYPE_NAVIGATION_RESPONSE, 2,
997             WEBKIT_TYPE_WEB_FRAME,
998             WEBKIT_TYPE_NETWORK_REQUEST);
999
1000     /**
1001      * WebKitWebView::navigation-policy-decision-requested:
1002      * @web_view: the object on which the signal is emitted
1003      * @frame: the #WebKitWebFrame that required the navigation
1004      * @request: a #WebKitNetworkRequest
1005      * @navigation_action: a #WebKitWebNavigation
1006      * @policy_decision: a #WebKitWebPolicyDecision
1007      * @return: TRUE if the signal will be handled, FALSE to have the
1008      *          default behavior apply
1009      *
1010      * Emitted when @frame requests a navigation to another page.
1011      * If this signal is not handled, the default behavior is to allow the
1012      * navigation.
1013      *
1014      * Since: 1.0.3
1015      */
1016     webkit_web_view_signals[NAVIGATION_POLICY_DECISION_REQUESTED] = g_signal_new("navigation-policy-decision-requested",
1017             G_TYPE_FROM_CLASS(webViewClass),
1018             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1019             0,
1020             g_signal_accumulator_true_handled,
1021             NULL,
1022             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
1023             G_TYPE_BOOLEAN, 4,
1024             WEBKIT_TYPE_WEB_FRAME,
1025             WEBKIT_TYPE_NETWORK_REQUEST,
1026             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
1027             WEBKIT_TYPE_WEB_POLICY_DECISION);
1028
1029     /**
1030      * WebKitWebView::mime-type-policy-decision-requested:
1031      * @web_view: the object on which the signal is emitted
1032      * @frame: the #WebKitWebFrame that required the policy decision
1033      * @request: a WebKitNetworkRequest
1034      * @mimetype: the MIME type attempted to load
1035      * @policy_decision: a #WebKitWebPolicyDecision
1036      * @return: TRUE if the signal will be handled, FALSE to have the
1037      *          default behavior apply
1038      *
1039      * Decide whether or not to display the given MIME type.  If this
1040      * signal is not handled, the default behavior is to show the
1041      * content of the requested URI if WebKit can show this MIME
1042      * type; if WebKit is not able to show the MIME type nothing
1043      * happens.
1044      *
1045      * Since: 1.0.3
1046      */
1047     webkit_web_view_signals[MIME_TYPE_POLICY_DECISION_REQUESTED] = g_signal_new("mime-type-policy-decision-requested",
1048             G_TYPE_FROM_CLASS(webViewClass),
1049             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1050             0,
1051             g_signal_accumulator_true_handled,
1052             NULL,
1053             webkit_marshal_BOOLEAN__OBJECT_OBJECT_STRING_OBJECT,
1054             G_TYPE_BOOLEAN, 4,
1055             WEBKIT_TYPE_WEB_FRAME,
1056             WEBKIT_TYPE_NETWORK_REQUEST,
1057             G_TYPE_STRING,
1058             WEBKIT_TYPE_WEB_POLICY_DECISION);
1059
1060     /**
1061      * WebKitWebView::window-object-cleared:
1062      * @web_view: the object on which the signal is emitted
1063      * @frame: the #WebKitWebFrame to which @window_object belongs
1064      * @context: the #JSGlobalContextRef holding the global object and other
1065      * execution state; equivalent to the return value of
1066      * webkit_web_frame_get_global_context(@frame)
1067      *
1068      * @window_object: the #JSObjectRef representing the frame's JavaScript
1069      * window object
1070      *
1071      * Emitted when the JavaScript window object in a #WebKitWebFrame has been
1072      * cleared in preparation for a new load. This is the preferred place to
1073      * set custom properties on the window object using the JavaScriptCore API.
1074      */
1075     webkit_web_view_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window-object-cleared",
1076             G_TYPE_FROM_CLASS(webViewClass),
1077             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1078             G_STRUCT_OFFSET (WebKitWebViewClass, window_object_cleared),
1079             NULL,
1080             NULL,
1081             webkit_marshal_VOID__OBJECT_POINTER_POINTER,
1082             G_TYPE_NONE, 3,
1083             WEBKIT_TYPE_WEB_FRAME,
1084             G_TYPE_POINTER,
1085             G_TYPE_POINTER);
1086
1087     /**
1088      * WebKitWebView::load-started:
1089      * @web_view: the object on which the signal is emitted
1090      * @frame: the frame going to do the load
1091      *
1092      * When a #WebKitWebFrame begins to load this signal is emitted.
1093      */
1094     webkit_web_view_signals[LOAD_STARTED] = g_signal_new("load-started",
1095             G_TYPE_FROM_CLASS(webViewClass),
1096             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1097             0,
1098             NULL,
1099             NULL,
1100             g_cclosure_marshal_VOID__OBJECT,
1101             G_TYPE_NONE, 1,
1102             WEBKIT_TYPE_WEB_FRAME);
1103
1104     /**
1105      * WebKitWebView::load-committed:
1106      * @web_view: the object on which the signal is emitted
1107      * @frame: the main frame that received the first data
1108      *
1109      * When a #WebKitWebFrame loaded the first data this signal is emitted.
1110      */
1111     webkit_web_view_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
1112             G_TYPE_FROM_CLASS(webViewClass),
1113             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1114             0,
1115             NULL,
1116             NULL,
1117             g_cclosure_marshal_VOID__OBJECT,
1118             G_TYPE_NONE, 1,
1119             WEBKIT_TYPE_WEB_FRAME);
1120
1121
1122     /**
1123      * WebKitWebView::load-progress-changed:
1124      * @web_view: the #WebKitWebView
1125      * @progress: the global progress
1126      */
1127     webkit_web_view_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load-progress-changed",
1128             G_TYPE_FROM_CLASS(webViewClass),
1129             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1130             0,
1131             NULL,
1132             NULL,
1133             g_cclosure_marshal_VOID__INT,
1134             G_TYPE_NONE, 1,
1135             G_TYPE_INT);
1136
1137     webkit_web_view_signals[LOAD_FINISHED] = g_signal_new("load-finished",
1138             G_TYPE_FROM_CLASS(webViewClass),
1139             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1140             0,
1141             NULL,
1142             NULL,
1143             g_cclosure_marshal_VOID__OBJECT,
1144             G_TYPE_NONE, 1,
1145             WEBKIT_TYPE_WEB_FRAME);
1146
1147     /**
1148      * WebKitWebView::title-changed:
1149      * @web_view: the object on which the signal is emitted
1150      * @frame: the main frame
1151      * @title: the new title
1152      *
1153      * When a #WebKitWebFrame changes the document title this signal is emitted.
1154      */
1155     webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed",
1156             G_TYPE_FROM_CLASS(webViewClass),
1157             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1158             0,
1159             NULL,
1160             NULL,
1161             webkit_marshal_VOID__OBJECT_STRING,
1162             G_TYPE_NONE, 2,
1163             WEBKIT_TYPE_WEB_FRAME,
1164             G_TYPE_STRING);
1165
1166     /**
1167      * WebKitWebView::hovering-over-link:
1168      * @web_view: the object on which the signal is emitted
1169      * @title: the link's title
1170      * @uri: the URI the link points to
1171      *
1172      * When the cursor is over a link, this signal is emitted.
1173      */
1174     webkit_web_view_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
1175             G_TYPE_FROM_CLASS(webViewClass),
1176             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1177             0,
1178             NULL,
1179             NULL,
1180             webkit_marshal_VOID__STRING_STRING,
1181             G_TYPE_NONE, 2,
1182             G_TYPE_STRING,
1183             G_TYPE_STRING);
1184
1185     /**
1186      * WebKitWebView::populate-popup:
1187      * @web_view: the object on which the signal is emitted
1188      * @menu: the context menu
1189      *
1190      * When a context menu is about to be displayed this signal is emitted.
1191      *
1192      * Add menu items to #menu to extend the context menu.
1193      */
1194     webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
1195             G_TYPE_FROM_CLASS(webViewClass),
1196             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1197             0,
1198             NULL,
1199             NULL,
1200             g_cclosure_marshal_VOID__OBJECT,
1201             G_TYPE_NONE, 1,
1202             GTK_TYPE_MENU);
1203
1204     webkit_web_view_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status-bar-text-changed",
1205             G_TYPE_FROM_CLASS(webViewClass),
1206             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1207             0,
1208             NULL,
1209             NULL,
1210             g_cclosure_marshal_VOID__STRING,
1211             G_TYPE_NONE, 1,
1212             G_TYPE_STRING);
1213
1214     webkit_web_view_signals[ICOND_LOADED] = g_signal_new("icon-loaded",
1215             G_TYPE_FROM_CLASS(webViewClass),
1216             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1217             0,
1218             NULL,
1219             NULL,
1220             g_cclosure_marshal_VOID__VOID,
1221             G_TYPE_NONE, 0);
1222
1223     webkit_web_view_signals[SELECTION_CHANGED] = g_signal_new("selection-changed",
1224             G_TYPE_FROM_CLASS(webViewClass),
1225             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1226             0,
1227             NULL,
1228             NULL,
1229             g_cclosure_marshal_VOID__VOID,
1230             G_TYPE_NONE, 0);
1231
1232     /**
1233      * WebKitWebView::console-message:
1234      * @web_view: the object on which the signal is emitted
1235      * @message: the message text
1236      * @line: the line where the error occured
1237      * @source_id: the source id
1238      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1239      *
1240      * A JavaScript console message was created.
1241      */
1242     webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message",
1243             G_TYPE_FROM_CLASS(webViewClass),
1244             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1245             G_STRUCT_OFFSET(WebKitWebViewClass, console_message),
1246             g_signal_accumulator_true_handled,
1247             NULL,
1248             webkit_marshal_BOOLEAN__STRING_INT_STRING,
1249             G_TYPE_BOOLEAN, 3,
1250             G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
1251
1252     /**
1253      * WebKitWebView::script-alert:
1254      * @web_view: the object on which the signal is emitted
1255      * @frame: the relevant frame
1256      * @message: the message text
1257      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1258      *
1259      * A JavaScript alert dialog was created.
1260      */
1261     webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
1262             G_TYPE_FROM_CLASS(webViewClass),
1263             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1264             G_STRUCT_OFFSET(WebKitWebViewClass, script_alert),
1265             g_signal_accumulator_true_handled,
1266             NULL,
1267             webkit_marshal_BOOLEAN__OBJECT_STRING,
1268             G_TYPE_BOOLEAN, 2,
1269             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING);
1270
1271     /**
1272      * WebKitWebView::script-confirm:
1273      * @web_view: the object on which the signal is emitted
1274      * @frame: the relevant frame
1275      * @message: the message text
1276      * @confirmed: whether the dialog has been confirmed
1277      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1278      *
1279      * A JavaScript confirm dialog was created, providing Yes and No buttons.
1280      */
1281     webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm",
1282             G_TYPE_FROM_CLASS(webViewClass),
1283             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1284             G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm),
1285             g_signal_accumulator_true_handled,
1286             NULL,
1287             webkit_marshal_BOOLEAN__OBJECT_STRING_BOOLEAN,
1288             G_TYPE_BOOLEAN, 3,
1289             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_BOOLEAN);
1290
1291     /**
1292      * WebKitWebView::script-prompt:
1293      * @web_view: the object on which the signal is emitted
1294      * @frame: the relevant frame
1295      * @message: the message text
1296      * @default: the default value
1297      * @text: To be filled with the return value or NULL if the dialog was cancelled.
1298      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
1299      *
1300      * A JavaScript prompt dialog was created, providing an entry to input text.
1301      */
1302     webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt",
1303             G_TYPE_FROM_CLASS(webViewClass),
1304             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1305             G_STRUCT_OFFSET(WebKitWebViewClass, script_prompt),
1306             g_signal_accumulator_true_handled,
1307             NULL,
1308             webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
1309             G_TYPE_BOOLEAN, 4,
1310             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
1311
1312     /**
1313      * WebKitWebView::select-all:
1314      * @web_view: the object which received the signal
1315      *
1316      * The #WebKitWebView::select-all signal is a keybinding signal which gets emitted to
1317      * select the complete contents of the text view.
1318      *
1319      * The default bindings for this signal is Ctrl-a.
1320      */
1321     webkit_web_view_signals[SELECT_ALL] = g_signal_new("select-all",
1322             G_TYPE_FROM_CLASS(webViewClass),
1323             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1324             G_STRUCT_OFFSET(WebKitWebViewClass, select_all),
1325             NULL, NULL,
1326             g_cclosure_marshal_VOID__VOID,
1327             G_TYPE_NONE, 0);
1328
1329     /**
1330      * WebKitWebView::cut-clipboard:
1331      * @web_view: the object which received the signal
1332      *
1333      * The #WebKitWebView::cut-clipboard signal is a keybinding signal which gets emitted to
1334      * cut the selection to the clipboard.
1335      *
1336      * The default bindings for this signal are Ctrl-x and Shift-Delete.
1337      */
1338     webkit_web_view_signals[CUT_CLIPBOARD] = g_signal_new("cut-clipboard",
1339             G_TYPE_FROM_CLASS(webViewClass),
1340             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1341             G_STRUCT_OFFSET(WebKitWebViewClass, cut_clipboard),
1342             NULL, NULL,
1343             g_cclosure_marshal_VOID__VOID,
1344             G_TYPE_NONE, 0);
1345
1346     /**
1347      * WebKitWebView::copy-clipboard:
1348      * @web_view: the object which received the signal
1349      *
1350      * The #WebKitWebView::copy-clipboard signal is a keybinding signal which gets emitted to
1351      * copy the selection to the clipboard.
1352      *
1353      * The default bindings for this signal are Ctrl-c and Ctrl-Insert.
1354      */
1355     webkit_web_view_signals[COPY_CLIPBOARD] = g_signal_new("copy-clipboard",
1356             G_TYPE_FROM_CLASS(webViewClass),
1357             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1358             G_STRUCT_OFFSET(WebKitWebViewClass, copy_clipboard),
1359             NULL, NULL,
1360             g_cclosure_marshal_VOID__VOID,
1361             G_TYPE_NONE, 0);
1362
1363     /**
1364      * WebKitWebView::paste-clipboard:
1365      * @web_view: the object which received the signal
1366      *
1367      * The #WebKitWebView::paste-clipboard signal is a keybinding signal which gets emitted to
1368      * paste the contents of the clipboard into the Web view.
1369      *
1370      * The default bindings for this signal are Ctrl-v and Shift-Insert.
1371      */
1372     webkit_web_view_signals[PASTE_CLIPBOARD] = g_signal_new("paste-clipboard",
1373             G_TYPE_FROM_CLASS(webViewClass),
1374             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1375             G_STRUCT_OFFSET(WebKitWebViewClass, paste_clipboard),
1376             NULL, NULL,
1377             g_cclosure_marshal_VOID__VOID,
1378             G_TYPE_NONE, 0);
1379
1380     /*
1381      * implementations of virtual methods
1382      */
1383     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
1384     webViewClass->web_view_ready = webkit_web_view_real_web_view_ready;
1385     webViewClass->navigation_requested = webkit_web_view_real_navigation_requested;
1386     webViewClass->window_object_cleared = webkit_web_view_real_window_object_cleared;
1387     webViewClass->choose_file = webkit_web_view_real_choose_file;
1388     webViewClass->script_alert = webkit_web_view_real_script_alert;
1389     webViewClass->script_confirm = webkit_web_view_real_script_confirm;
1390     webViewClass->script_prompt = webkit_web_view_real_script_prompt;
1391     webViewClass->console_message = webkit_web_view_real_console_message;
1392     webViewClass->select_all = webkit_web_view_real_select_all;
1393     webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard;
1394     webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard;
1395     webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard;
1396
1397     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
1398     objectClass->dispose = webkit_web_view_dispose;
1399     objectClass->get_property = webkit_web_view_get_property;
1400     objectClass->set_property = webkit_web_view_set_property;
1401
1402     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webViewClass);
1403     widgetClass->realize = webkit_web_view_realize;
1404     widgetClass->expose_event = webkit_web_view_expose_event;
1405     widgetClass->key_press_event = webkit_web_view_key_press_event;
1406     widgetClass->key_release_event = webkit_web_view_key_release_event;
1407     widgetClass->button_press_event = webkit_web_view_button_press_event;
1408     widgetClass->button_release_event = webkit_web_view_button_release_event;
1409     widgetClass->motion_notify_event = webkit_web_view_motion_event;
1410     widgetClass->scroll_event = webkit_web_view_scroll_event;
1411     widgetClass->size_allocate = webkit_web_view_size_allocate;
1412     widgetClass->popup_menu = webkit_web_view_popup_menu_handler;
1413     widgetClass->focus_in_event = webkit_web_view_focus_in_event;
1414     widgetClass->focus_out_event = webkit_web_view_focus_out_event;
1415     widgetClass->get_accessible = webkit_web_view_get_accessible;
1416
1417     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
1418     containerClass->add = webkit_web_view_container_add;
1419     containerClass->remove = webkit_web_view_container_remove;
1420     containerClass->forall = webkit_web_view_container_forall;
1421
1422     /*
1423      * make us scrollable (e.g. addable to a GtkScrolledWindow)
1424      */
1425     webViewClass->set_scroll_adjustments = webkit_web_view_set_scroll_adjustments;
1426     GTK_WIDGET_CLASS(webViewClass)->set_scroll_adjustments_signal = g_signal_new("set-scroll-adjustments",
1427             G_TYPE_FROM_CLASS(webViewClass),
1428             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1429             G_STRUCT_OFFSET(WebKitWebViewClass, set_scroll_adjustments),
1430             NULL, NULL,
1431             webkit_marshal_VOID__OBJECT_OBJECT,
1432             G_TYPE_NONE, 2,
1433             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1434
1435     /*
1436      * Key bindings
1437      */
1438
1439     binding_set = gtk_binding_set_by_class(webViewClass);
1440
1441     gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
1442                                  "select_all", 0);
1443
1444     /* Cut/copy/paste */
1445
1446     gtk_binding_entry_add_signal(binding_set, GDK_x, GDK_CONTROL_MASK,
1447                                  "cut_clipboard", 0);
1448     gtk_binding_entry_add_signal(binding_set, GDK_c, GDK_CONTROL_MASK,
1449                                  "copy_clipboard", 0);
1450     gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK,
1451                                  "paste_clipboard", 0);
1452
1453     gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_SHIFT_MASK,
1454                                  "cut_clipboard", 0);
1455     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_CONTROL_MASK,
1456                                  "copy_clipboard", 0);
1457     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_SHIFT_MASK,
1458                                  "paste_clipboard", 0);
1459
1460     /*
1461      * properties
1462      */
1463
1464 #if GTK_CHECK_VERSION(2,10,0)
1465     /**
1466     * WebKitWebView:copy-target-list:
1467     *
1468     * The list of targets this web view supports for clipboard copying.
1469     *
1470     * Since: 1.0.2
1471     */
1472     g_object_class_install_property(objectClass, PROP_COPY_TARGET_LIST,
1473                                     g_param_spec_boxed("copy-target-list",
1474                                                        "Copy target list",
1475                                                        "The list of targets this web view supports for clipboard copying",
1476                                                        GTK_TYPE_TARGET_LIST,
1477                                                        WEBKIT_PARAM_READABLE));
1478
1479     /**
1480     * WebKitWebView:paste-target-list:
1481     *
1482     * The list of targets this web view supports for clipboard pasting.
1483     *
1484     * Since: 1.0.2
1485     */
1486     g_object_class_install_property(objectClass, PROP_PASTE_TARGET_LIST,
1487                                     g_param_spec_boxed("paste-target-list",
1488                                                        "Paste target list",
1489                                                        "The list of targets this web view supports for clipboard pasting",
1490                                                        GTK_TYPE_TARGET_LIST,
1491                                                        WEBKIT_PARAM_READABLE));
1492 #endif
1493
1494     g_object_class_install_property(objectClass, PROP_SETTINGS,
1495                                     g_param_spec_object("settings",
1496                                                         "Settings",
1497                                                         "An associated WebKitWebSettings instance",
1498                                                         WEBKIT_TYPE_WEB_SETTINGS,
1499                                                         WEBKIT_PARAM_READWRITE));
1500
1501     /**
1502     * WebKitWebView:web-inspector:
1503     *
1504     * The associated WebKitWebInspector instance.
1505     *
1506     * Since: 1.0.3
1507     */
1508     g_object_class_install_property(objectClass, PROP_WEB_INSPECTOR,
1509                                     g_param_spec_object("web-inspector",
1510                                                         "Web Inspector",
1511                                                         "The associated WebKitWebInspector instance",
1512                                                         WEBKIT_TYPE_WEB_INSPECTOR,
1513                                                         WEBKIT_PARAM_READABLE));
1514
1515     /**
1516     * WebKitWebView:window-features:
1517     *
1518     * An associated WebKitWebWindowFeatures instance.
1519     *
1520     * Since: 1.0.3
1521     */
1522     g_object_class_install_property(objectClass, PROP_WINDOW_FEATURES,
1523                                     g_param_spec_object("window-features",
1524                                                         "Window Features",
1525                                                         "An associated WebKitWebWindowFeatures instance",
1526                                                         WEBKIT_TYPE_WEB_WINDOW_FEATURES,
1527                                                         WEBKIT_PARAM_READWRITE));
1528
1529     g_object_class_install_property(objectClass, PROP_EDITABLE,
1530                                     g_param_spec_boolean("editable",
1531                                                          "Editable",
1532                                                          "Whether content can be modified by the user",
1533                                                          FALSE,
1534                                                          WEBKIT_PARAM_READWRITE));
1535
1536     g_object_class_install_property(objectClass, PROP_TRANSPARENT,
1537                                     g_param_spec_boolean("transparent",
1538                                                          "Transparent",
1539                                                          "Whether content has a transparent background",
1540                                                          FALSE,
1541                                                          WEBKIT_PARAM_READWRITE));
1542
1543     /**
1544     * WebKitWebView:zoom-level:
1545     *
1546     * The level of zoom of the content.
1547     *
1548     * Since: 1.0.1
1549     */
1550     g_object_class_install_property(objectClass, PROP_ZOOM_LEVEL,
1551                                     g_param_spec_float("zoom-level",
1552                                                        "Zoom level",
1553                                                        "The level of zoom of the content",
1554                                                        G_MINFLOAT,
1555                                                        G_MAXFLOAT,
1556                                                        1.0f,
1557                                                        WEBKIT_PARAM_READWRITE));
1558
1559     /**
1560     * WebKitWebView:full-content-zoom:
1561     *
1562     * Whether the full content is scaled when zooming.
1563     *
1564     * Since: 1.0.1
1565     */
1566     g_object_class_install_property(objectClass, PROP_FULL_CONTENT_ZOOM,
1567                                     g_param_spec_boolean("full-content-zoom",
1568                                                          "Full content zoom",
1569                                                          "Whether the full content is scaled when zooming",
1570                                                          FALSE,
1571                                                          WEBKIT_PARAM_READWRITE));
1572
1573     g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
1574 }
1575
1576 static gdouble webViewGetDPI(WebKitWebView* webView)
1577 {
1578     WebKitWebViewPrivate* priv = webView->priv;
1579     WebKitWebSettings* webSettings = priv->webSettings;
1580     gboolean enforce96DPI;
1581     g_object_get(webSettings, "enforce-96-dpi", &enforce96DPI, NULL);
1582     if (enforce96DPI)
1583         return 96.0;
1584
1585     gdouble DPI = defaultDPI;
1586 #if GTK_CHECK_VERSION(2,10,0)
1587     GdkScreen* screen = gtk_widget_has_screen(GTK_WIDGET(webView)) ? gtk_widget_get_screen(GTK_WIDGET(webView)) : gdk_screen_get_default();
1588     if (screen) {
1589         DPI = gdk_screen_get_resolution(screen);
1590         // gdk_screen_get_resolution() returns -1 when no DPI is set.
1591         if (DPI == -1)
1592             DPI = defaultDPI;
1593     }
1594 #endif
1595     ASSERT(DPI > 0);
1596     return DPI;
1597 }
1598
1599 static void webkit_web_view_screen_changed(WebKitWebView* webView, GdkScreen* previousScreen, gpointer userdata)
1600 {
1601     WebKitWebViewPrivate* priv = webView->priv;
1602     WebKitWebSettings* webSettings = priv->webSettings;
1603     Settings* settings = core(webView)->settings();
1604     gdouble DPI = webViewGetDPI(webView);
1605
1606     guint defaultFontSize, defaultMonospaceFontSize, minimumFontSize, minimumLogicalFontSize;
1607
1608     g_object_get(webSettings,
1609                  "default-font-size", &defaultFontSize,
1610                  "default-monospace-font-size", &defaultMonospaceFontSize,
1611                  "minimum-font-size", &minimumFontSize,
1612                  "minimum-logical-font-size", &minimumLogicalFontSize,
1613                  NULL);
1614
1615     settings->setDefaultFontSize(defaultFontSize / 72.0 * DPI);
1616     settings->setDefaultFixedFontSize(defaultMonospaceFontSize / 72.0 * DPI);
1617     settings->setMinimumFontSize(minimumFontSize / 72.0 * DPI);
1618     settings->setMinimumLogicalFontSize(minimumLogicalFontSize / 72.0 * DPI);
1619 }
1620
1621 static void webkit_web_view_update_settings(WebKitWebView* webView)
1622 {
1623     WebKitWebViewPrivate* priv = webView->priv;
1624     WebKitWebSettings* webSettings = priv->webSettings;
1625     Settings* settings = core(webView)->settings();
1626
1627     gchar* defaultEncoding, *cursiveFontFamily, *defaultFontFamily, *fantasyFontFamily, *monospaceFontFamily, *sansSerifFontFamily, *serifFontFamily, *userStylesheetUri;
1628     gboolean autoLoadImages, autoShrinkImages, printBackgrounds, enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas;
1629
1630     g_object_get(webSettings,
1631                  "default-encoding", &defaultEncoding,
1632                  "cursive-font-family", &cursiveFontFamily,
1633                  "default-font-family", &defaultFontFamily,
1634                  "fantasy-font-family", &fantasyFontFamily,
1635                  "monospace-font-family", &monospaceFontFamily,
1636                  "sans-serif-font-family", &sansSerifFontFamily,
1637                  "serif-font-family", &serifFontFamily,
1638                  "auto-load-images", &autoLoadImages,
1639                  "auto-shrink-images", &autoShrinkImages,
1640                  "print-backgrounds", &printBackgrounds,
1641                  "enable-scripts", &enableScripts,
1642                  "enable-plugins", &enablePlugins,
1643                  "resizable-text-areas", &resizableTextAreas,
1644                  "user-stylesheet-uri", &userStylesheetUri,
1645                  "enable-developer-extras", &enableDeveloperExtras,
1646                  NULL);
1647
1648     settings->setDefaultTextEncodingName(defaultEncoding);
1649     settings->setCursiveFontFamily(cursiveFontFamily);
1650     settings->setStandardFontFamily(defaultFontFamily);
1651     settings->setFantasyFontFamily(fantasyFontFamily);
1652     settings->setFixedFontFamily(monospaceFontFamily);
1653     settings->setSansSerifFontFamily(sansSerifFontFamily);
1654     settings->setSerifFontFamily(serifFontFamily);
1655     settings->setLoadsImagesAutomatically(autoLoadImages);
1656     settings->setShrinksStandaloneImagesToFit(autoShrinkImages);
1657     settings->setShouldPrintBackgrounds(printBackgrounds);
1658     settings->setJavaScriptEnabled(enableScripts);
1659     settings->setPluginsEnabled(enablePlugins);
1660     settings->setTextAreasAreResizable(resizableTextAreas);
1661     settings->setUserStyleSheetLocation(KURL(KURL(), userStylesheetUri));
1662     settings->setDeveloperExtrasEnabled(enableDeveloperExtras);
1663
1664     g_free(defaultEncoding);
1665     g_free(cursiveFontFamily);
1666     g_free(defaultFontFamily);
1667     g_free(fantasyFontFamily);
1668     g_free(monospaceFontFamily);
1669     g_free(sansSerifFontFamily);
1670     g_free(serifFontFamily);
1671     g_free(userStylesheetUri);
1672
1673     webkit_web_view_screen_changed(webView, NULL, NULL);
1674 }
1675
1676 static inline gint pixelsFromSize(WebKitWebView* webView, gint size)
1677 {
1678     gdouble DPI = webViewGetDPI(webView);
1679     return size / 72.0 * DPI;
1680 }
1681
1682 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView)
1683 {
1684     Settings* settings = core(webView)->settings();
1685
1686     const gchar* name = g_intern_string(pspec->name);
1687     GValue value = { 0, { { 0 } } };
1688     g_value_init(&value, pspec->value_type);
1689     g_object_get_property(G_OBJECT(webSettings), name, &value);
1690
1691     if (name == g_intern_string("default-encoding"))
1692         settings->setDefaultTextEncodingName(g_value_get_string(&value));
1693     else if (name == g_intern_string("cursive-font-family"))
1694         settings->setCursiveFontFamily(g_value_get_string(&value));
1695     else if (name == g_intern_string("default-font-family"))
1696         settings->setStandardFontFamily(g_value_get_string(&value));
1697     else if (name == g_intern_string("fantasy-font-family"))
1698         settings->setFantasyFontFamily(g_value_get_string(&value));
1699     else if (name == g_intern_string("monospace-font-family"))
1700         settings->setFixedFontFamily(g_value_get_string(&value));
1701     else if (name == g_intern_string("sans-serif-font-family"))
1702         settings->setSansSerifFontFamily(g_value_get_string(&value));
1703     else if (name == g_intern_string("serif-font-family"))
1704         settings->setSerifFontFamily(g_value_get_string(&value));
1705     else if (name == g_intern_string("default-font-size"))
1706         settings->setDefaultFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1707     else if (name == g_intern_string("default-monospace-font-size"))
1708         settings->setDefaultFixedFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1709     else if (name == g_intern_string("minimum-font-size"))
1710         settings->setMinimumFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1711     else if (name == g_intern_string("minimum-logical-font-size"))
1712         settings->setMinimumLogicalFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
1713     else if (name == g_intern_string("enforce-96-dpi"))
1714         webkit_web_view_screen_changed(webView, NULL, NULL);
1715     else if (name == g_intern_string("auto-load-images"))
1716         settings->setLoadsImagesAutomatically(g_value_get_boolean(&value));
1717     else if (name == g_intern_string("auto-shrink-images"))
1718         settings->setShrinksStandaloneImagesToFit(g_value_get_boolean(&value));
1719     else if (name == g_intern_string("print-backgrounds"))
1720         settings->setShouldPrintBackgrounds(g_value_get_boolean(&value));
1721     else if (name == g_intern_string("enable-scripts"))
1722         settings->setJavaScriptEnabled(g_value_get_boolean(&value));
1723     else if (name == g_intern_string("enable-plugins"))
1724         settings->setPluginsEnabled(g_value_get_boolean(&value));
1725     else if (name == g_intern_string("resizable-text-areas"))
1726         settings->setTextAreasAreResizable(g_value_get_boolean(&value));
1727     else if (name == g_intern_string("user-stylesheet-uri"))
1728         settings->setUserStyleSheetLocation(KURL(KURL(), g_value_get_string(&value)));
1729     else if (name == g_intern_string("enable-developer-extras"))
1730         settings->setDeveloperExtrasEnabled(g_value_get_boolean(&value));
1731     else if (!g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), name))
1732         g_warning("Unexpected setting '%s'", name);
1733     g_value_unset(&value);
1734 }
1735
1736 static void webkit_web_view_init(WebKitWebView* webView)
1737 {
1738     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1739     webView->priv = priv;
1740
1741     priv->imContext = gtk_im_multicontext_new();
1742
1743     WebKit::InspectorClient* inspectorClient = new WebKit::InspectorClient(webView);
1744     priv->corePage = new Page(new WebKit::ChromeClient(webView), new WebKit::ContextMenuClient(webView), new WebKit::EditorClient(webView), new WebKit::DragClient, inspectorClient);
1745
1746     // We also add a simple wrapper class to provide the public
1747     // interface for the Web Inspector.
1748     priv->webInspector = WEBKIT_WEB_INSPECTOR(g_object_new(WEBKIT_TYPE_WEB_INSPECTOR, NULL));
1749     webkit_web_inspector_set_inspector_client(priv->webInspector, inspectorClient);
1750
1751     priv->horizontalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1752     priv->verticalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1753
1754 #if GLIB_CHECK_VERSION(2,10,0)
1755     g_object_ref_sink(priv->horizontalAdjustment);
1756     g_object_ref_sink(priv->verticalAdjustment);
1757 #else
1758     g_object_ref(priv->horizontalAdjustment);
1759     gtk_object_sink(GTK_OBJECT(priv->horizontalAdjustment));
1760     g_object_ref(priv->verticalAdjustment);
1761     gtk_object_sink(GTK_OBJECT(priv->verticalAdjustment));
1762 #endif
1763
1764     GTK_WIDGET_SET_FLAGS(webView, GTK_CAN_FOCUS);
1765     priv->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
1766     priv->lastPopupXPosition = priv->lastPopupYPosition = -1;
1767     priv->editable = false;
1768
1769     priv->backForwardList = webkit_web_back_forward_list_new_with_web_view(webView);
1770
1771     priv->zoomFullContent = FALSE;
1772
1773 #if GTK_CHECK_VERSION(2,10,0)
1774     GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
1775 #else
1776     GdkAtom textHtml = gdk_atom_intern("text/html", false);
1777 #endif
1778     /* Targets for copy */
1779     priv->copy_target_list = gtk_target_list_new(NULL, 0);
1780     gtk_target_list_add(priv->copy_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
1781     gtk_target_list_add_text_targets(priv->copy_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
1782
1783     /* Targets for pasting */
1784     priv->paste_target_list = gtk_target_list_new(NULL, 0);
1785     gtk_target_list_add(priv->paste_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
1786     gtk_target_list_add_text_targets(priv->paste_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
1787
1788     priv->webSettings = webkit_web_settings_new();
1789     webkit_web_view_update_settings(webView);
1790     g_signal_connect(webView, "screen-changed", G_CALLBACK(webkit_web_view_screen_changed), NULL);
1791     g_signal_connect(priv->webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
1792
1793     priv->webWindowFeatures = webkit_web_window_features_new();
1794 }
1795
1796 GtkWidget* webkit_web_view_new(void)
1797 {
1798     WebKitWebView* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
1799
1800     return GTK_WIDGET(webView);
1801 }
1802
1803 // for internal use only
1804 void webkit_web_view_notify_ready(WebKitWebView* webView)
1805 {
1806     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1807
1808     gboolean isHandled = FALSE;
1809     g_signal_emit(webView, webkit_web_view_signals[WEB_VIEW_READY], 0, &isHandled);
1810 }
1811
1812
1813 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitWebSettings* webSettings)
1814 {
1815     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1816     g_return_if_fail(WEBKIT_IS_WEB_SETTINGS(webSettings));
1817
1818     WebKitWebViewPrivate* priv = webView->priv;
1819     g_signal_handlers_disconnect_by_func(priv->webSettings, (gpointer)webkit_web_view_settings_notify, webView);
1820     g_object_unref(priv->webSettings);
1821     g_object_ref(webSettings);
1822     priv->webSettings = webSettings;
1823     webkit_web_view_update_settings(webView);
1824     g_signal_connect(webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
1825     g_object_notify(G_OBJECT(webView), "settings");
1826 }
1827
1828 WebKitWebSettings* webkit_web_view_get_settings(WebKitWebView* webView)
1829 {
1830     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1831
1832     WebKitWebViewPrivate* priv = webView->priv;
1833     return priv->webSettings;
1834 }
1835
1836 /**
1837  * webkit_web_view_get_inspector:
1838  * @web_view: a #WebKitWebView
1839  *
1840  * Obtains the #WebKitWebInspector associated with the
1841  * #WebKitWebView. Every #WebKitWebView object has a
1842  * #WebKitWebInspector object attached to it as soon as it is created,
1843  * so this function will only return NULL if the argument is not a
1844  * valid #WebKitWebView.
1845  *
1846  * Returns: the #WebKitWebInspector instance associated with the
1847  * #WebKitWebView; %NULL is only returned if the argument is not a
1848  * valid #WebKitWebView.
1849  *
1850  * Since: 1.0.3
1851  */
1852 WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
1853 {
1854     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1855
1856     WebKitWebViewPrivate* priv = webView->priv;
1857     return priv->webInspector;
1858 }
1859
1860 // internal
1861 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures)
1862 {
1863     WebKitWebViewPrivate* priv = webView->priv;
1864
1865     if(webkit_web_window_features_equal(priv->webWindowFeatures, webWindowFeatures))
1866       return;
1867
1868     g_object_unref(priv->webWindowFeatures);
1869     g_object_ref(webWindowFeatures);
1870     priv->webWindowFeatures = webWindowFeatures;
1871 }
1872
1873 /**
1874  * webkit_web_view_get_window_features
1875  * @web_view: a #WebKitWebView
1876  *
1877  * Returns the instance of #WebKitWebWindowFeatures held by the given
1878  * #WebKitWebView.
1879  *
1880  * Return value: the #WebKitWebWindowFeatures
1881  *
1882  * Since: 1.0.3
1883  */
1884 WebKitWebWindowFeatures* webkit_web_view_get_window_features(WebKitWebView* webView)
1885 {
1886     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1887
1888     WebKitWebViewPrivate* priv = webView->priv;
1889     return priv->webWindowFeatures;
1890 }
1891
1892 /**
1893  * webkit_web_view_set_maintains_back_forward_list:
1894  * @web_view: a #WebKitWebView
1895  * @flag: to tell the view to maintain a back or forward list
1896  *
1897  * Set the view to maintain a back or forward list of history items.
1898  */
1899 void webkit_web_view_set_maintains_back_forward_list(WebKitWebView* webView, gboolean flag)
1900 {
1901     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1902
1903     core(webView)->backForwardList()->setEnabled(flag);
1904 }
1905
1906 /**
1907  * webkit_web_view_get_back_forward_list:
1908  * @web_view: a #WebKitWebView
1909  *
1910  * Returns a #WebKitWebBackForwardList
1911  *
1912  * Return value: the #WebKitWebBackForwardList
1913  */
1914 WebKitWebBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
1915 {
1916     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1917
1918     WebKitWebViewPrivate* priv = webView->priv;
1919
1920     if (!core(webView) || !core(webView)->backForwardList()->enabled())
1921         return NULL;
1922
1923     return priv->backForwardList;
1924 }
1925
1926 /**
1927  * webkit_web_view_go_to_back_forward_item:
1928  * @web_view: a #WebKitWebView
1929  * @item: a #WebKitWebHistoryItem*
1930  *
1931  * Go to the specified #WebKitWebHistoryItem
1932  *
1933  * Return value: %TRUE if loading of item is successful, %FALSE if not
1934  */
1935 gboolean webkit_web_view_go_to_back_forward_item(WebKitWebView* webView, WebKitWebHistoryItem* item)
1936 {
1937     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1938     g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(item), FALSE);
1939
1940     WebKitWebBackForwardList* backForwardList = webkit_web_view_get_back_forward_list(webView);
1941     if (!webkit_web_back_forward_list_contains_item(backForwardList, item))
1942         return FALSE;
1943
1944     core(webView)->goToItem(core(item), FrameLoadTypeIndexedBackForward);
1945     return TRUE;
1946 }
1947
1948 /**
1949  * webkit_web_view_go_back:
1950  * @web_view: a #WebKitWebView
1951  *
1952  * Loads the previous history item.
1953  */
1954 void webkit_web_view_go_back(WebKitWebView* webView)
1955 {
1956     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1957
1958     core(webView)->goBack();
1959 }
1960
1961 /**
1962  * webkit_web_view_go_back_or_forward:
1963  * @web_view: a #WebKitWebView
1964  * @steps: the number of steps
1965  *
1966  * Loads the history item that is the number of @steps away from the current
1967  * item. Negative values represent steps backward while positive values
1968  * represent steps forward.
1969  */
1970 void webkit_web_view_go_back_or_forward(WebKitWebView* webView, gint steps)
1971 {
1972     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1973
1974     Frame* frame = core(webView)->mainFrame();
1975     frame->loader()->goBackOrForward(steps);
1976 }
1977
1978 /**
1979  * webkit_web_view_go_forward:
1980  * @web_view: a #WebKitWebView
1981  *
1982  * Loads the next history item.
1983  */
1984 void webkit_web_view_go_forward(WebKitWebView* webView)
1985 {
1986     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1987
1988     core(webView)->goForward();
1989 }
1990
1991 /**
1992  * webkit_web_view_can_go_back:
1993  * @web_view: a #WebKitWebView
1994  *
1995  * Determines whether #web_view has a previous history item.
1996  *
1997  * Return value: %TRUE if able to move back, %FALSE otherwise
1998  */
1999 gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
2000 {
2001     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2002
2003     if (!core(webView) || !core(webView)->backForwardList()->backItem())
2004         return FALSE;
2005
2006     return TRUE;
2007 }
2008
2009 /**
2010  * webkit_web_view_can_go_back_or_forward:
2011  * @web_view: a #WebKitWebView
2012  * @steps: the number of steps
2013  *
2014  * Determines whether #web_view has a history item of @steps. Negative values
2015  * represent steps backward while positive values represent steps forward.
2016  *
2017  * Return value: %TRUE if able to move back or forward the given number of
2018  * steps, %FALSE otherwise
2019  */
2020 gboolean webkit_web_view_can_go_back_or_forward(WebKitWebView* webView, gint steps)
2021 {
2022     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2023
2024     Frame* frame = core(webView)->mainFrame();
2025     return frame->loader()->canGoBackOrForward(steps);
2026 }
2027
2028 /**
2029  * webkit_web_view_can_go_forward:
2030  * @web_view: a #WebKitWebView
2031  *
2032  * Determines whether #web_view has a next history item.
2033  *
2034  * Return value: %TRUE if able to move forward, %FALSE otherwise
2035  */
2036 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
2037 {
2038     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2039
2040     Page* page = core(webView);
2041
2042     if (!page)
2043         return FALSE;
2044
2045     if (!page->backForwardList()->forwardItem())
2046         return FALSE;
2047
2048     return TRUE;
2049 }
2050
2051 /**
2052  * webkit_web_view_open:
2053  * @web_view: a #WebKitWebView
2054  *
2055  * Requests loading of the specified URI string.
2056  *
2057  * Deprecated: 1.1.1: Use webkit_web_view_load_uri() instead.
2058   */
2059 void webkit_web_view_open(WebKitWebView* webView, const gchar* uri)
2060 {
2061     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2062     g_return_if_fail(uri);
2063
2064     webkit_web_view_load_uri(webView, uri);
2065 }
2066
2067 void webkit_web_view_reload(WebKitWebView* webView)
2068 {
2069     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2070
2071     core(webView)->mainFrame()->loader()->reload();
2072 }
2073
2074 /**
2075  * webkit_web_view_reload_bypass_cache:
2076  * @web_view: a #WebKitWebView
2077  *
2078  * Reloads the @web_view without using any cached data.
2079  *
2080  * Since: 1.0.3
2081  */
2082 void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
2083 {
2084     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2085
2086     core(webView)->mainFrame()->loader()->reload(true);
2087 }
2088
2089 /**
2090  * webkit_web_view_load_uri:
2091  * @web_view: a #WebKitWebView
2092  * @uri: an URI string
2093  *
2094  * Requests loading of the specified URI string.
2095  *
2096  * Since: 1.1.1
2097  */
2098 void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
2099 {
2100     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2101     g_return_if_fail(uri);
2102
2103     WebKitWebFrame* frame = webView->priv->mainFrame;
2104     webkit_web_frame_load_uri(frame, uri);
2105 }
2106
2107 /**
2108 +  * webkit_web_view_load_string:
2109 +  * @web_view: a #WebKitWebView
2110 +  * @content: an URI string
2111 +  * @mime_type: the MIME type, or %NULL
2112 +  * @encoding: the encoding, or %NULL
2113 +  * @base_uri: the base URI for relative locations
2114 +  *
2115 +  * Requests loading of the given @content with the specified @mime_type,
2116 +  * @encoding and @base_uri.
2117 +  *
2118 +  * If @mime_type is %NULL, "text/html" is assumed.
2119 +  *
2120 +  * If @encoding is %NULL, "UTF-8" is assumed.
2121 +  */
2122 void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* mimeType, const gchar* encoding, const gchar* baseUri)
2123 {
2124     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2125     g_return_if_fail(content);
2126
2127     WebKitWebFrame* frame = webView->priv->mainFrame;
2128     webkit_web_frame_load_string(frame, content, mimeType, encoding, baseUri);
2129 }
2130 /**
2131  * webkit_web_view_load_html_string:
2132  * @web_view: a #WebKitWebView
2133  * @content: an URI string
2134  * @base_uri: the base URI for relative locations
2135  *
2136  * Requests loading of the given @content with the specified @base_uri.
2137  *
2138  * Deprecated: 1.1.1: Use webkit_web_view_load_string() instead.
2139  */
2140 void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* content, const gchar* baseUri)
2141 {
2142     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2143     g_return_if_fail(content);
2144
2145     webkit_web_view_load_string(webView, content, NULL, NULL, baseUri);
2146 }
2147
2148 /**
2149  * webkit_web_view_load_request:
2150  * @web_view: a #WebKitWebView
2151  * @request: a #WebKitNetworkRequest
2152  *
2153  * Requests loading of the specified asynchronous client request.
2154  *
2155  * Creates a provisional data source that will transition to a committed data
2156  * source once any data has been received. Use webkit_web_view_stop_loading() to
2157  * stop the load.
2158  *
2159  * Since: 1.1.1
2160  */
2161 void webkit_web_view_load_request(WebKitWebView* webView, WebKitNetworkRequest* request)
2162 {
2163     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2164     g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request));
2165
2166     WebKitWebFrame* frame = webView->priv->mainFrame;
2167     webkit_web_frame_load_request(frame, request);
2168 }
2169
2170 void webkit_web_view_stop_loading(WebKitWebView* webView)
2171 {
2172     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2173
2174     Frame* frame = core(webView)->mainFrame();
2175
2176     if (FrameLoader* loader = frame->loader())
2177         loader->stopAllLoaders();
2178 }
2179
2180 /**
2181  * webkit_web_view_search_text:
2182  * @web_view: a #WebKitWebView
2183  * @text: a string to look for
2184  * @forward: whether to find forward or not
2185  * @case_sensitive: whether to respect the case of text
2186  * @wrap: whether to continue looking at the beginning after reaching the end
2187  *
2188  * Looks for a specified string inside #web_view.
2189  *
2190  * Return value: %TRUE on success or %FALSE on failure
2191  */
2192 gboolean webkit_web_view_search_text(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, gboolean forward, gboolean shouldWrap)
2193 {
2194     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2195     g_return_val_if_fail(string, FALSE);
2196
2197     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
2198     FindDirection direction = forward ? FindDirectionForward : FindDirectionBackward;
2199
2200     return core(webView)->findString(String::fromUTF8(string), caseSensitivity, direction, shouldWrap);
2201 }
2202
2203 /**
2204  * webkit_web_view_mark_text_matches:
2205  * @web_view: a #WebKitWebView
2206  * @string: a string to look for
2207  * @case_sensitive: whether to respect the case of text
2208  * @limit: the maximum number of strings to look for or %0 for all
2209  *
2210  * Attempts to highlight all occurances of #string inside #web_view.
2211  *
2212  * Return value: the number of strings highlighted
2213  */
2214 guint webkit_web_view_mark_text_matches(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, guint limit)
2215 {
2216     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2217     g_return_val_if_fail(string, 0);
2218
2219     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
2220
2221     return core(webView)->markAllMatchesForText(String::fromUTF8(string), caseSensitivity, false, limit);
2222 }
2223
2224 /**
2225  * webkit_web_view_set_highlight_text_matches:
2226  * @web_view: a #WebKitWebView
2227  * @highlight: whether to highlight text matches
2228  *
2229  * Highlights text matches previously marked by webkit_web_view_mark_text_matches.
2230  */
2231 void webkit_web_view_set_highlight_text_matches(WebKitWebView* webView, gboolean shouldHighlight)
2232 {
2233     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2234
2235     core(webView)->mainFrame()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
2236 }
2237
2238 /**
2239  * webkit_web_view_unmark_text_matches:
2240  * @web_view: a #WebKitWebView
2241  *
2242  * Removes highlighting previously set by webkit_web_view_mark_text_matches.
2243  */
2244 void webkit_web_view_unmark_text_matches(WebKitWebView* webView)
2245 {
2246     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2247
2248     return core(webView)->unmarkAllTextMatches();
2249 }
2250
2251 WebKitWebFrame* webkit_web_view_get_main_frame(WebKitWebView* webView)
2252 {
2253     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2254
2255     WebKitWebViewPrivate* priv = webView->priv;
2256     return priv->mainFrame;
2257 }
2258
2259 /**
2260  * webkit_web_view_get_focused_frame:
2261  * @web_view: a #WebKitWebView
2262  *
2263  * Returns the frame that has focus or an active text selection.
2264  *
2265  * Return value: The focused #WebKitWebFrame or %NULL if no frame is focused
2266  */
2267 WebKitWebFrame* webkit_web_view_get_focused_frame(WebKitWebView* webView)
2268 {
2269     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2270
2271     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
2272     return kit(focusedFrame);
2273 }
2274
2275 void webkit_web_view_execute_script(WebKitWebView* webView, const gchar* script)
2276 {
2277     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2278     g_return_if_fail(script);
2279
2280     if (FrameLoader* loader = core(webView)->mainFrame()->loader())
2281         loader->executeScript(String::fromUTF8(script), true);
2282 }
2283
2284 /**
2285  * webkit_web_view_cut_clipboard:
2286  * @web_view: a #WebKitWebView
2287  *
2288  * Determines whether or not it is currently possible to cut to the clipboard.
2289  *
2290  * Return value: %TRUE if a selection can be cut, %FALSE if not
2291  */
2292 gboolean webkit_web_view_can_cut_clipboard(WebKitWebView* webView)
2293 {
2294     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2295
2296     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2297     return frame->editor()->canCut() || frame->editor()->canDHTMLCut();
2298 }
2299
2300 /**
2301  * webkit_web_view_copy_clipboard:
2302  * @web_view: a #WebKitWebView
2303  *
2304  * Determines whether or not it is currently possible to copy to the clipboard.
2305  *
2306  * Return value: %TRUE if a selection can be copied, %FALSE if not
2307  */
2308 gboolean webkit_web_view_can_copy_clipboard(WebKitWebView* webView)
2309 {
2310     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2311
2312     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2313     return frame->editor()->canCopy() || frame->editor()->canDHTMLCopy();
2314 }
2315
2316 /**
2317  * webkit_web_view_paste_clipboard:
2318  * @web_view: a #WebKitWebView
2319  *
2320  * Determines whether or not it is currently possible to paste from the clipboard.
2321  *
2322  * Return value: %TRUE if a selection can be pasted, %FALSE if not
2323  */
2324 gboolean webkit_web_view_can_paste_clipboard(WebKitWebView* webView)
2325 {
2326     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2327
2328     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2329     return frame->editor()->canPaste() || frame->editor()->canDHTMLPaste();
2330 }
2331
2332 /**
2333  * webkit_web_view_cut_clipboard:
2334  * @web_view: a #WebKitWebView
2335  *
2336  * Cuts the current selection inside the @web_view to the clipboard.
2337  */
2338 void webkit_web_view_cut_clipboard(WebKitWebView* webView)
2339 {
2340     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2341
2342     if (webkit_web_view_can_cut_clipboard(webView))
2343         g_signal_emit(webView, webkit_web_view_signals[CUT_CLIPBOARD], 0);
2344 }
2345
2346 /**
2347  * webkit_web_view_copy_clipboard:
2348  * @web_view: a #WebKitWebView
2349  *
2350  * Copies the current selection inside the @web_view to the clipboard.
2351  */
2352 void webkit_web_view_copy_clipboard(WebKitWebView* webView)
2353 {
2354     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2355
2356     if (webkit_web_view_can_copy_clipboard(webView))
2357         g_signal_emit(webView, webkit_web_view_signals[COPY_CLIPBOARD], 0);
2358 }
2359
2360 /**
2361  * webkit_web_view_paste_clipboard:
2362  * @web_view: a #WebKitWebView
2363  *
2364  * Pastes the current contents of the clipboard to the @web_view.
2365  */
2366 void webkit_web_view_paste_clipboard(WebKitWebView* webView)
2367 {
2368     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2369
2370     if (webkit_web_view_can_paste_clipboard(webView))
2371         g_signal_emit(webView, webkit_web_view_signals[PASTE_CLIPBOARD], 0);
2372 }
2373
2374 /**
2375  * webkit_web_view_delete_selection:
2376  * @web_view: a #WebKitWebView
2377  *
2378  * Deletes the current selection inside the @web_view.
2379  */
2380 void webkit_web_view_delete_selection(WebKitWebView* webView)
2381 {
2382     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2383
2384     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2385     frame->editor()->performDelete();
2386 }
2387
2388 /**
2389  * webkit_web_view_has_selection:
2390  * @web_view: a #WebKitWebView
2391  *
2392  * Determines whether text was selected.
2393  *
2394  * Return value: %TRUE if there is selected text, %FALSE if not
2395  */
2396 gboolean webkit_web_view_has_selection(WebKitWebView* webView)
2397 {
2398     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2399
2400     return !core(webView)->selection().isNone();
2401 }
2402
2403 /**
2404  * webkit_web_view_get_selected_text:
2405  * @web_view: a #WebKitWebView
2406  *
2407  * Retrieves the selected text if any.
2408  *
2409  * Return value: a newly allocated string with the selection or %NULL
2410  */
2411 gchar* webkit_web_view_get_selected_text(WebKitWebView* webView)
2412 {
2413     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2414
2415     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
2416     return g_strdup(frame->selectedText().utf8().data());
2417 }
2418
2419 /**
2420  * webkit_web_view_select_all:
2421  * @web_view: a #WebKitWebView
2422  *
2423  * Attempts to select everything inside the @web_view.
2424  */
2425 void webkit_web_view_select_all(WebKitWebView* webView)
2426 {
2427     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2428
2429     g_signal_emit(webView, webkit_web_view_signals[SELECT_ALL], 0);
2430 }
2431
2432 /**
2433  * webkit_web_view_get_editable:
2434  * @web_view: a #WebKitWebView
2435  *
2436  * Returns whether the user is allowed to edit the document.
2437  *
2438  * Returns %TRUE if @web_view allows the user to edit the HTML document, %FALSE if
2439  * it doesn't. You can change @web_view's document programmatically regardless of
2440  * this setting.
2441  *
2442  * Return value: a #gboolean indicating the editable state
2443  */
2444 gboolean webkit_web_view_get_editable(WebKitWebView* webView)
2445 {
2446     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2447
2448     WebKitWebViewPrivate* priv = webView->priv;
2449
2450     return priv->editable;
2451 }
2452
2453 /**
2454  * webkit_web_view_set_editable:
2455  * @web_view: a #WebKitWebView
2456  * @flag: a #gboolean indicating the editable state
2457  *
2458  * Sets whether @web_view allows the user to edit its HTML document.
2459  *
2460  * If @flag is %TRUE, @web_view allows the user to edit the document. If @flag is
2461  * %FALSE, an element in @web_view's document can only be edited if the
2462  * CONTENTEDITABLE attribute has been set on the element or one of its parent
2463  * elements. You can change @web_view's document programmatically regardless of
2464  * this setting. By default a #WebKitWebView is not editable.
2465
2466  * Normally, an HTML document is not editable unless the elements within the
2467  * document are editable. This function provides a low-level way to make the
2468  * contents of a #WebKitWebView editable without altering the document or DOM
2469  * structure.
2470  */
2471 void webkit_web_view_set_editable(WebKitWebView* webView, gboolean flag)
2472 {
2473     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2474
2475     WebKitWebViewPrivate* priv = webView->priv;
2476
2477     Frame* frame = core(webView)->mainFrame();
2478     g_return_if_fail(frame);
2479
2480     // TODO: What happens when the frame is replaced?
2481     flag = flag != FALSE;
2482     if (flag == priv->editable)
2483         return;
2484
2485     priv->editable = flag;
2486
2487     if (flag) {
2488         frame->applyEditingStyleToBodyElement();
2489         // TODO: If the WebKitWebView is made editable and the selection is empty, set it to something.
2490         //if (!webkit_web_view_get_selected_dom_range(webView))
2491         //    mainFrame->setSelectionFromNone();
2492     } else
2493         frame->removeEditingStyleFromBodyElement();
2494     g_object_notify(G_OBJECT(webView), "editable");
2495 }
2496
2497 /**
2498  * webkit_web_view_get_copy_target_list:
2499  * @web_view: a #WebKitWebView
2500  *
2501  * This function returns the list of targets this #WebKitWebView can
2502  * provide for clipboard copying and as DND source. The targets in the list are
2503  * added with %info values from the #WebKitWebViewTargetInfo enum,
2504  * using gtk_target_list_add() and
2505  * gtk_target_list_add_text_targets().
2506  *
2507  * Return value: the #GtkTargetList
2508  **/
2509 GtkTargetList* webkit_web_view_get_copy_target_list(WebKitWebView* webView)
2510 {
2511     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2512
2513     WebKitWebViewPrivate* priv = webView->priv;
2514     return priv->copy_target_list;
2515 }
2516
2517 /**
2518  * webkit_web_view_get_paste_target_list:
2519  * @web_view: a #WebKitWebView
2520  *
2521  * This function returns the list of targets this #WebKitWebView can
2522  * provide for clipboard pasting and as DND destination. The targets in the list are
2523  * added with %info values from the #WebKitWebViewTargetInfo enum,
2524  * using gtk_target_list_add() and
2525  * gtk_target_list_add_text_targets().
2526  *
2527  * Return value: the #GtkTargetList
2528  **/
2529 GtkTargetList* webkit_web_view_get_paste_target_list(WebKitWebView* webView)
2530 {
2531     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
2532
2533     WebKitWebViewPrivate* priv = webView->priv;
2534     return priv->paste_target_list;
2535 }
2536
2537 /**
2538  * webkit_web_view_can_show_mime_type:
2539  * @web_view: a #WebKitWebView
2540  * @mime_type: a MIME type
2541  *
2542  * This functions returns whether or not a MIME type can be displayed using this view.
2543  *
2544  * Return value: a #gboolean indicating if the MIME type can be displayed
2545  *
2546  * Since: 1.0.3
2547  **/
2548
2549 gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const gchar* mimeType)
2550 {
2551     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2552
2553     Frame* frame = core(webkit_web_view_get_main_frame(webView));
2554     if (FrameLoader* loader = frame->loader())
2555         return loader->canShowMIMEType(String::fromUTF8(mimeType));
2556     else
2557         return FALSE;
2558 }
2559
2560 /**
2561  * webkit_web_view_get_transparent:
2562  * @web_view: a #WebKitWebView
2563  *
2564  * Returns whether the #WebKitWebView has a transparent background.
2565  *
2566  * Return value: %FALSE when the #WebKitWebView draws a solid background
2567  * (the default), otherwise %TRUE.
2568  */
2569 gboolean webkit_web_view_get_transparent(WebKitWebView* webView)
2570 {
2571     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2572
2573     WebKitWebViewPrivate* priv = webView->priv;
2574     return priv->transparent;
2575 }
2576
2577 /**
2578  * webkit_web_view_set_transparent:
2579  * @web_view: a #WebKitWebView
2580  *
2581  * Sets whether the #WebKitWebView has a transparent background.
2582  *
2583  * Pass %FALSE to have the #WebKitWebView draw a solid background
2584  * (the default), otherwise %TRUE.
2585  */
2586 void webkit_web_view_set_transparent(WebKitWebView* webView, gboolean flag)
2587 {
2588     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2589
2590     WebKitWebViewPrivate* priv = webView->priv;
2591     priv->transparent = flag;
2592
2593     // TODO: This needs to be made persistent or it could become a problem when
2594     // the main frame is replaced.
2595     Frame* frame = core(webView)->mainFrame();
2596     g_return_if_fail(frame);
2597     frame->view()->setTransparent(flag);
2598     g_object_notify(G_OBJECT(webView), "transparent");
2599 }
2600
2601 /**
2602  * webkit_web_view_get_zoom_level:
2603  * @web_view: a #WebKitWebView
2604  *
2605  * Returns the zoom level of @web_view, i.e. the factor by which elements in
2606  * the page are scaled with respect to their original size.
2607  * If the "full-content-zoom" property is set to %FALSE (the default)
2608  * the zoom level changes the text size, or if %TRUE, scales all
2609  * elements in the page.
2610  *
2611  * Return value: the zoom level of @web_view
2612  *
2613  * Since: 1.0.1
2614  */
2615 gfloat webkit_web_view_get_zoom_level(WebKitWebView* webView)
2616 {
2617     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1.0f);
2618
2619     Frame* frame = core(webView)->mainFrame();
2620     if (!frame)
2621         return 1.0f;
2622
2623     return frame->zoomFactor();
2624 }
2625
2626 static void webkit_web_view_apply_zoom_level(WebKitWebView* webView, gfloat zoomLevel)
2627 {
2628     Frame* frame = core(webView)->mainFrame();
2629     if (!frame)
2630         return;
2631
2632     WebKitWebViewPrivate* priv = webView->priv;
2633     frame->setZoomFactor(zoomLevel, !priv->zoomFullContent);
2634 }
2635
2636 /**
2637  * webkit_web_view_set_zoom_level:
2638  * @web_view: a #WebKitWebView
2639  * @zoom_level: the new zoom level
2640  *
2641  * Sets the zoom level of @web_view, i.e. the factor by which elements in
2642  * the page are scaled with respect to their original size.
2643  * If the "full-content-zoom" property is set to %FALSE (the default)
2644  * the zoom level changes the text size, or if %TRUE, scales all
2645  * elements in the page.
2646  *
2647  * Since: 1.0.1
2648  */
2649 void webkit_web_view_set_zoom_level(WebKitWebView* webView, gfloat zoomLevel)
2650 {
2651     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2652
2653     webkit_web_view_apply_zoom_level(webView, zoomLevel);
2654     g_object_notify(G_OBJECT(webView), "zoom-level");
2655 }
2656
2657 /**
2658  * webkit_web_view_zoom_in:
2659  * @web_view: a #WebKitWebView
2660  *
2661  * Increases the zoom level of @web_view. The current zoom
2662  * level is incremented by the value of the "zoom-step"
2663  * property of the #WebKitWebSettings associated with @web_view.
2664  *
2665  * Since: 1.0.1
2666  */
2667 void webkit_web_view_zoom_in(WebKitWebView* webView)
2668 {
2669     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2670
2671     WebKitWebViewPrivate* priv = webView->priv;
2672     gfloat zoomMultiplierRatio;
2673     g_object_get(priv->webSettings, "zoom-step", &zoomMultiplierRatio, NULL);
2674
2675     webkit_web_view_set_zoom_level(webView, webkit_web_view_get_zoom_level(webView) + zoomMultiplierRatio);
2676 }
2677
2678 /**
2679  * webkit_web_view_zoom_out:
2680  * @web_view: a #WebKitWebView
2681  *
2682  * Decreases the zoom level of @web_view. The current zoom
2683  * level is decremented by the value of the "zoom-step"
2684  * property of the #WebKitWebSettings associated with @web_view.
2685  *
2686  * Since: 1.0.1
2687  */
2688 void webkit_web_view_zoom_out(WebKitWebView* webView)
2689 {
2690     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2691
2692     WebKitWebViewPrivate* priv = webView->priv;
2693     gfloat zoomMultiplierRatio;
2694     g_object_get(priv->webSettings, "zoom-step", &zoomMultiplierRatio, NULL);
2695
2696     webkit_web_view_set_zoom_level(webView, webkit_web_view_get_zoom_level(webView) - zoomMultiplierRatio);
2697 }
2698
2699 /**
2700  * webkit_web_view_get_full_content_zoom:
2701  * @web_view: a #WebKitWebView
2702  *
2703  * Returns whether the zoom level affects only text or all elements.
2704  *
2705  * Return value: %FALSE if only text should be scaled (the default),
2706  * %TRUE if the full content of the view should be scaled.
2707  *
2708  * Since: 1.0.1
2709  */
2710 gboolean webkit_web_view_get_full_content_zoom(WebKitWebView* webView)
2711 {
2712     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2713
2714     WebKitWebViewPrivate* priv = webView->priv;
2715     return priv->zoomFullContent;
2716 }
2717
2718 /**
2719  * webkit_web_view_set_full_content_zoom:
2720  * @web_view: a #WebKitWebView
2721  * @full_content_zoom: %FALSE if only text should be scaled (the default),
2722  * %TRUE if the full content of the view should be scaled.
2723  *
2724  * Sets whether the zoom level affects only text or all elements.
2725  *
2726  * Since: 1.0.1
2727  */
2728 void webkit_web_view_set_full_content_zoom(WebKitWebView* webView, gboolean zoomFullContent)
2729 {
2730     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2731
2732     WebKitWebViewPrivate* priv = webView->priv;
2733     if (priv->zoomFullContent == zoomFullContent)
2734       return;
2735
2736     priv->zoomFullContent = zoomFullContent;
2737     webkit_web_view_apply_zoom_level(webView, webkit_web_view_get_zoom_level(webView));
2738
2739     g_object_notify(G_OBJECT(webView), "full-content-zoom");
2740 }
2741
2742 /**
2743  * webkit_get_default_session:
2744  *
2745  * Retrieves the default #SoupSession used by all web views.
2746  * Note that the session features are added by WebKit on demand,
2747  * so if you insert your own #SoupCookieJar before any network
2748  * traffic occurs, WebKit will use it instead of the default.
2749  *
2750  * Return value: the default #SoupSession
2751  *
2752  * Since: 1.1.1
2753  */
2754 SoupSession* webkit_get_default_session ()
2755 {
2756     return ResourceHandle::defaultSession();
2757 }
2758
2759 }