Reviewed by Alp Toker.
[WebKit-https.git] / WebKit / gtk / webkit / webkitwebview.cpp
1 /*
2  *  Copyright (C) 2007 Holger Hans Peter Freyther
3  *  Copyright (C) 2007, 2008 Christian Dywan <christian@imendio.com>
4  *  Copyright (C) 2007 Xan Lopez <xan@gnome.org>
5  *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
6  *  Copyright (C) 2008 Jan Alonzo <jmalonzo@unpluggable.com>
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #include "config.h"
24
25 #include "webkitwebview.h"
26 #include "webkit-marshal.h"
27 #include "webkitprivate.h"
28 #include "webkitwebbackforwardlist.h"
29 #include "webkitwebhistoryitem.h"
30
31 #include "NotImplemented.h"
32 #include "BackForwardList.h"
33 #include "CString.h"
34 #include "ChromeClientGtk.h"
35 #include "ContextMenu.h"
36 #include "ContextMenuClientGtk.h"
37 #include "ContextMenuController.h"
38 #include "Cursor.h"
39 #include "DragClientGtk.h"
40 #include "Editor.h"
41 #include "EditorClientGtk.h"
42 #include "EventHandler.h"
43 #include "FocusController.h"
44 #include "FrameLoaderTypes.h"
45 #include "HitTestRequest.h"
46 #include "HitTestResult.h"
47 #include "GraphicsContext.h"
48 #include "InspectorClientGtk.h"
49 #include "FrameLoader.h"
50 #include "FrameView.h"
51 #include "Editor.h"
52 #include "PasteboardHelper.h"
53 #include "PlatformKeyboardEvent.h"
54 #include "PlatformWheelEvent.h"
55 #include "SubstituteData.h"
56
57 #include <gdk/gdkkeysyms.h>
58
59 static const double defaultDPI = 96.0;
60
61 using namespace WebKit;
62 using namespace WebCore;
63
64 extern "C" {
65
66 enum {
67     /* normal signals */
68     NAVIGATION_REQUESTED,
69     WINDOW_OBJECT_CLEARED,
70     LOAD_STARTED,
71     LOAD_COMMITTED,
72     LOAD_PROGRESS_CHANGED,
73     LOAD_FINISHED,
74     TITLE_CHANGED,
75     HOVERING_OVER_LINK,
76     POPULATE_POPUP,
77     STATUS_BAR_TEXT_CHANGED,
78     ICOND_LOADED,
79     SELECTION_CHANGED,
80     CONSOLE_MESSAGE,
81     SCRIPT_ALERT,
82     SCRIPT_CONFIRM,
83     SCRIPT_PROMPT,
84     SELECT_ALL,
85     COPY_CLIPBOARD,
86     PASTE_CLIPBOARD,
87     CUT_CLIPBOARD,
88     LAST_SIGNAL
89 };
90
91 enum {
92     PROP_0,
93
94     PROP_COPY_TARGET_LIST,
95     PROP_PASTE_TARGET_LIST,
96     PROP_EDITABLE,
97     PROP_SETTINGS,
98     PROP_TRANSPARENT
99 };
100
101 static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };
102
103 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
104
105 static void webkit_web_view_context_menu_position_func(GtkMenu*, gint* x, gint* y, gboolean* pushIn, WebKitWebViewPrivate* data)
106 {
107     *pushIn = FALSE;
108     *x = data->lastPopupXPosition;
109     *y = data->lastPopupYPosition;
110 }
111
112 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
113 {
114     Page* page = core(webView);
115     page->contextMenuController()->clearContextMenu();
116     Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
117
118     if (!focusedFrame->view())
119         return FALSE;
120
121     focusedFrame->view()->setCursor(pointerCursor());
122     bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
123     if (!handledEvent)
124         return FALSE;
125
126     ContextMenu* coreMenu = page->contextMenuController()->contextMenu();
127     if (!coreMenu)
128         return FALSE;
129
130     GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
131     if (!menu)
132         return FALSE;
133
134     g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
135
136     GList* items = gtk_container_get_children(GTK_CONTAINER(menu));
137     bool empty = !g_list_nth(items, 0);
138     g_list_free(items);
139     if (empty)
140         return FALSE;
141
142     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
143     priv->lastPopupXPosition = event.globalX();
144     priv->lastPopupYPosition = event.globalY();
145     gtk_menu_popup(menu, NULL, NULL,
146                    reinterpret_cast<GtkMenuPositionFunc>(webkit_web_view_context_menu_position_func),
147                    priv, event.button() + 1, gtk_get_current_event_time());
148     return TRUE;
149 }
150
151 static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
152 {
153     static const int contextMenuMargin = 1;
154
155     // The context menu event was generated from the keyboard, so show the context menu by the current selection.
156     Page* page = core(WEBKIT_WEB_VIEW(widget));
157     FrameView* view = page->mainFrame()->view();
158     if (!view)
159         return FALSE;    
160
161     Position start = page->mainFrame()->selectionController()->selection().start();
162     Position end = page->mainFrame()->selectionController()->selection().end();
163
164     int rightAligned = FALSE;
165     IntPoint location;
166
167     if (!start.node() || !end.node())
168         location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
169     else {
170         RenderObject* renderer = start.node()->renderer();
171         if (!renderer)
172             return FALSE;
173
174         // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:]).
175         int extraWidthToEndOfLine = 0;
176         IntRect startCaretRect = renderer->caretRect(start.offset(), DOWNSTREAM, &extraWidthToEndOfLine);
177         IntRect endCaretRect = renderer->caretRect(end.offset(), UPSTREAM);
178
179         IntRect firstRect;
180         if (startCaretRect.y() == endCaretRect.y())
181             firstRect = IntRect(MIN(startCaretRect.x(), endCaretRect.x()),
182                                 startCaretRect.y(),
183                                 abs(endCaretRect.x() - startCaretRect.x()),
184                                 MAX(startCaretRect.height(), endCaretRect.height()));
185         else
186             firstRect = IntRect(startCaretRect.x(),
187                                 startCaretRect.y(),
188                                 startCaretRect.width() + extraWidthToEndOfLine,
189                                 startCaretRect.height());
190
191         location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
192     }
193
194     int x, y;
195     gdk_window_get_origin(GTK_WIDGET(view->containingWindow())->window, &x, &y);
196
197     // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
198     // Ideally we'd have the position of a context menu event be separate from its target node.
199     location = view->contentsToWindow(location) + IntSize(0, -1);
200     IntPoint global = location + IntSize(x, y);
201     PlatformMouseEvent event(location, global, NoButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
202
203     return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
204 }
205
206 static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
207 {
208     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
209
210     switch(prop_id) {
211     case PROP_COPY_TARGET_LIST:
212         g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView));
213         break;
214     case PROP_PASTE_TARGET_LIST:
215         g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView));
216         break;
217     case PROP_EDITABLE:
218         g_value_set_boolean(value, webkit_web_view_get_editable(webView));
219         break;
220     case PROP_SETTINGS:
221         g_value_set_object(value, webkit_web_view_get_settings(webView));
222         break;
223     case PROP_TRANSPARENT:
224         g_value_set_boolean(value, webkit_web_view_get_transparent(webView));
225         break;
226     default:
227         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
228     }
229 }
230
231 static void webkit_web_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec)
232 {
233     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
234
235     switch(prop_id) {
236     case PROP_EDITABLE:
237         webkit_web_view_set_editable(webView, g_value_get_boolean(value));
238         break;
239     case PROP_SETTINGS:
240         webkit_web_view_set_settings(webView, WEBKIT_WEB_SETTINGS(g_value_get_object(value)));
241         break;
242     case PROP_TRANSPARENT:
243         webkit_web_view_set_transparent(webView, g_value_get_boolean(value));
244         break;
245     default:
246         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
247     }
248 }
249
250 static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
251 {
252     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
253     WebKitWebViewPrivate* priv = webView->priv;
254
255     Frame* frame = core(webView)->mainFrame();
256     GdkRectangle clip;
257     gdk_region_get_clipbox(event->region, &clip);
258     cairo_t* cr = gdk_cairo_create(event->window);
259     GraphicsContext ctx(cr);
260     ctx.setGdkExposeEvent(event);
261     if (frame->contentRenderer() && frame->view()) {
262         frame->view()->layoutIfNeededRecursive();
263
264         if (priv->transparent) {
265             cairo_save(cr);
266             cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
267             cairo_paint(cr);
268             cairo_restore(cr);
269         }
270
271         frame->view()->paint(&ctx, clip);
272     }
273     cairo_destroy(cr);
274
275     return FALSE;
276 }
277
278 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event)
279 {
280     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
281
282     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
283     PlatformKeyboardEvent keyboardEvent(event);
284
285     if (!frame->view())
286         return FALSE;
287
288     if (frame->eventHandler()->keyEvent(keyboardEvent))
289         return TRUE;
290
291     FrameView* view = frame->view();
292     SelectionController::EAlteration alteration;
293     if (event->state & GDK_SHIFT_MASK)
294         alteration = SelectionController::EXTEND;
295     else
296         alteration = SelectionController::MOVE;
297
298     // TODO: We probably want to use GTK+ key bindings here and perhaps take an
299     // approach more like the Win and Mac ports for key handling.
300     switch (event->keyval) {
301     case GDK_Down:
302         view->scrollBy(0, LINE_STEP);
303         return TRUE;
304     case GDK_Up:
305         view->scrollBy(0, -LINE_STEP);
306         return TRUE;
307     case GDK_Right:
308         view->scrollBy(LINE_STEP, 0);
309         return TRUE;
310     case GDK_Left:
311         view->scrollBy(-LINE_STEP, 0);
312         return TRUE;
313     case GDK_Home:
314         frame->selectionController()->modify(alteration, SelectionController::BACKWARD, DocumentBoundary, true);
315         return TRUE;
316     case GDK_End:
317         frame->selectionController()->modify(alteration, SelectionController::FORWARD, DocumentBoundary, true);
318         return TRUE;
319     }
320
321     /* Chain up to our parent class for binding activation */
322     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event);
323 }
324
325 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event)
326 {
327     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
328
329     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
330     if (!frame->view())
331         return FALSE;
332
333     PlatformKeyboardEvent keyboardEvent(event);
334
335     if (frame->eventHandler()->keyEvent(keyboardEvent))
336         return TRUE;
337
338     /* Chain up to our parent class for binding activation */
339     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event);
340 }
341
342 static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventButton* event)
343 {
344     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
345
346     // FIXME: need to keep track of subframe focus for key events
347     gtk_widget_grab_focus(widget);
348
349     if (event->button == 3)
350         return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
351
352     Frame* frame = core(webView)->mainFrame();
353     if (!frame->view())
354         return FALSE;
355
356     return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
357 }
358
359 static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEventButton* event)
360 {
361     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
362     WebKitWebViewPrivate* priv = webView->priv;
363
364     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
365
366     if (focusedFrame && focusedFrame->editor()->canEdit()) {
367         GdkWindow* window = gtk_widget_get_parent_window(widget);
368         gtk_im_context_set_client_window(priv->imContext, window);
369 #ifdef MAEMO_CHANGES
370         hildon_gtk_im_context_filter_event(priv->imContext, (GdkEvent*)event);
371         hildon_gtk_im_context_show(priv->imContext);
372 #endif
373     }
374
375     Frame* mainFrame = core(webView)->mainFrame();
376     if (!mainFrame->view())
377         return FALSE;
378
379     return mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
380 }
381
382 static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event)
383 {
384     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
385
386     Frame* frame = core(webView)->mainFrame();
387     if (!frame->view())
388         return FALSE;
389
390     return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
391 }
392
393 static gboolean webkit_web_view_scroll_event(GtkWidget* widget, GdkEventScroll* event)
394 {
395     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
396
397     Frame* frame = core(webView)->mainFrame();
398     if (!frame->view())
399         return FALSE;
400
401     PlatformWheelEvent wheelEvent(event);
402     return frame->eventHandler()->handleWheelEvent(wheelEvent);
403 }
404
405 static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
406 {
407     GTK_WIDGET_CLASS(webkit_web_view_parent_class)->size_allocate(widget,allocation);
408
409     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
410
411     Frame* frame = core(webView)->mainFrame();
412     if (!frame->view())
413         return;
414
415     frame->view()->resize(allocation->width, allocation->height);
416     frame->forceLayout();
417     frame->view()->adjustViewSize();
418 }
419
420 static gboolean webkit_web_view_focus_in_event(GtkWidget* widget, GdkEventFocus* event)
421 {
422     // TODO: Improve focus handling as suggested in
423     // http://bugs.webkit.org/show_bug.cgi?id=16910
424     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
425     if (GTK_WIDGET_TOPLEVEL(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {
426         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
427
428         Frame* frame = core(webView)->mainFrame();
429         core(webView)->focusController()->setActive(frame);
430     }
431     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event);
432 }
433
434 static void webkit_web_view_realize(GtkWidget* widget)
435 {
436     GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
437
438     GdkWindowAttr attributes;
439     attributes.window_type = GDK_WINDOW_CHILD;
440     attributes.x = widget->allocation.x;
441     attributes.y = widget->allocation.y;
442     attributes.width = widget->allocation.width;
443     attributes.height = widget->allocation.height;
444     attributes.wclass = GDK_INPUT_OUTPUT;
445     attributes.visual = gtk_widget_get_visual (widget);
446     attributes.colormap = gtk_widget_get_colormap (widget);
447     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
448                             | GDK_EXPOSURE_MASK
449                             | GDK_BUTTON_PRESS_MASK
450                             | GDK_BUTTON_RELEASE_MASK
451                             | GDK_POINTER_MOTION_MASK
452                             | GDK_KEY_PRESS_MASK
453                             | GDK_KEY_RELEASE_MASK
454                             | GDK_BUTTON_MOTION_MASK
455                             | GDK_BUTTON1_MOTION_MASK
456                             | GDK_BUTTON2_MOTION_MASK
457                             | GDK_BUTTON3_MOTION_MASK;
458
459     gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
460     widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
461     gdk_window_set_user_data(widget->window, widget);
462
463     widget->style = gtk_style_attach(widget->style, widget->window);
464     gdk_window_set_background(widget->window, &widget->style->base[GTK_WIDGET_STATE(widget)]);
465 }
466
467 static void webkit_web_view_set_scroll_adjustments(WebKitWebView* webView, GtkAdjustment* hadj, GtkAdjustment* vadj)
468 {
469     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
470
471     if (hadj)
472         g_object_ref(hadj);
473     if (vadj)
474         g_object_ref(vadj);
475
476     WebKitWebViewPrivate* priv = webView->priv;
477
478     if (priv->horizontalAdjustment)
479         g_object_unref(priv->horizontalAdjustment);
480     if (priv->verticalAdjustment)
481         g_object_unref(priv->verticalAdjustment);
482
483     priv->horizontalAdjustment = hadj;
484     priv->verticalAdjustment = vadj;
485
486     if (!view)
487         return;
488
489     view->setGtkAdjustments(hadj, vadj);
490 }
491
492 static void webkit_web_view_container_add(GtkContainer* container, GtkWidget* widget)
493 {
494     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
495     WebKitWebViewPrivate* priv = webView->priv;
496
497     priv->children.add(widget);
498     if (GTK_WIDGET_REALIZED(container))
499         gtk_widget_set_parent_window(widget, GTK_WIDGET(webView)->window);
500     gtk_widget_set_parent(widget, GTK_WIDGET(container));
501 }
502
503 static void webkit_web_view_container_remove(GtkContainer* container, GtkWidget* widget)
504 {
505     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
506     WebKitWebViewPrivate* priv = webView->priv;
507
508     if (priv->children.contains(widget)) {
509         gtk_widget_unparent(widget);
510         priv->children.remove(widget);
511     }
512 }
513
514 static void webkit_web_view_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
515 {
516     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
517     WebKitWebViewPrivate* priv = webView->priv;
518
519     HashSet<GtkWidget*> children = priv->children;
520     HashSet<GtkWidget*>::const_iterator end = children.end();
521     for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
522         (*callback)(*current, callbackData);
523 }
524
525 static WebKitWebView* webkit_web_view_real_create_web_view(WebKitWebView*)
526 {
527     notImplemented();
528     return 0;
529 }
530
531 static WebKitNavigationResponse webkit_web_view_real_navigation_requested(WebKitWebView*, WebKitWebFrame* frame, WebKitNetworkRequest*)
532 {
533     notImplemented();
534     return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
535 }
536
537 static void webkit_web_view_real_window_object_cleared(WebKitWebView*, WebKitWebFrame*, JSGlobalContextRef context, JSObjectRef window_object)
538 {
539     notImplemented();
540 }
541
542 static gchar* webkit_web_view_real_choose_file(WebKitWebView*, WebKitWebFrame*, const gchar* old_name)
543 {
544     notImplemented();
545     return g_strdup(old_name);
546 }
547
548 typedef enum {
549     WEBKIT_SCRIPT_DIALOG_ALERT,
550     WEBKIT_SCRIPT_DIALOG_CONFIRM,
551     WEBKIT_SCRIPT_DIALOG_PROMPT
552  } WebKitScriptDialogType;
553
554 static gboolean webkit_web_view_script_dialog(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
555 {
556     GtkMessageType messageType;
557     GtkButtonsType buttons;
558     gint defaultResponse;
559     GtkWidget* window;
560     GtkWidget* dialog;
561     GtkWidget* entry = 0;
562     gboolean didConfirm = FALSE;
563
564     switch (type) {
565     case WEBKIT_SCRIPT_DIALOG_ALERT:
566         messageType = GTK_MESSAGE_WARNING;
567         buttons = GTK_BUTTONS_CLOSE;
568         defaultResponse = GTK_RESPONSE_CLOSE;
569         break;
570     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
571         messageType = GTK_MESSAGE_QUESTION;
572         buttons = GTK_BUTTONS_YES_NO;
573         defaultResponse = GTK_RESPONSE_YES;
574         break;
575     case WEBKIT_SCRIPT_DIALOG_PROMPT:
576         messageType = GTK_MESSAGE_QUESTION;
577         buttons = GTK_BUTTONS_OK_CANCEL;
578         defaultResponse = GTK_RESPONSE_OK;
579         break;
580     default:
581         g_warning("Unknown value for WebKitScriptDialogType.");
582         return FALSE;
583     }
584
585     window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
586     dialog = gtk_message_dialog_new(GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
587     gchar* title = g_strconcat("JavaScript - ", webkit_web_frame_get_uri(frame), NULL);
588     gtk_window_set_title(GTK_WINDOW(dialog), title);
589     g_free(title);
590
591     if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
592         entry = gtk_entry_new();
593         gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
594         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
595         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
596         gtk_widget_show(entry);
597     }
598
599     gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
600     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
601
602     switch (response) {
603     case GTK_RESPONSE_YES:
604         didConfirm = TRUE;
605         break;
606     case GTK_RESPONSE_OK:
607         didConfirm = TRUE;
608         if (entry)
609             *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
610         else
611             *value = 0;
612         break;
613     case GTK_RESPONSE_NO:
614     case GTK_RESPONSE_CANCEL:
615         didConfirm = FALSE;
616         break;
617
618     }
619     gtk_widget_destroy(GTK_WIDGET(dialog));
620     return didConfirm;
621 }
622
623 static gboolean webkit_web_view_real_script_alert(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message)
624 {
625     webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
626     return TRUE;
627 }
628
629 static gboolean webkit_web_view_real_script_confirm(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm)
630 {
631     *didConfirm = webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
632     return TRUE;
633 }
634
635 static gboolean webkit_web_view_real_script_prompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
636 {
637     if (!webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
638         *value = NULL;
639     return TRUE;
640 }
641
642 static gboolean webkit_web_view_real_console_message(WebKitWebView* webView, const gchar* message, unsigned int line, const gchar* sourceId)
643 {
644     g_print("console message: %s @%d: %s\n", sourceId, line, message);
645     return TRUE;
646 }
647
648 static void webkit_web_view_real_select_all(WebKitWebView* webView)
649 {
650     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
651     frame->editor()->command("SelectAll").execute();
652 }
653
654 static void webkit_web_view_real_cut_clipboard(WebKitWebView* webView)
655 {
656     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
657     frame->editor()->command("Cut").execute();
658 }
659
660 static void webkit_web_view_real_copy_clipboard(WebKitWebView* webView)
661 {
662     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
663     frame->editor()->command("Copy").execute();
664 }
665
666 static void webkit_web_view_real_paste_clipboard(WebKitWebView* webView)
667 {
668     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
669     frame->editor()->command("Paste").execute();
670 }
671
672 static void webkit_web_view_finalize(GObject* object)
673 {
674     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
675     WebKitWebViewPrivate* priv = webView->priv;
676
677     webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object));
678
679     core(priv->mainFrame)->loader()->detachChildren();
680     delete priv->corePage;
681
682     if (priv->horizontalAdjustment)
683         g_object_unref(priv->horizontalAdjustment);
684     if (priv->verticalAdjustment)
685         g_object_unref(priv->verticalAdjustment);
686     g_object_unref(priv->backForwardList);
687     g_object_unref(priv->webSettings);
688     g_object_unref(priv->mainFrame);
689     g_object_unref(priv->imContext);
690     gtk_target_list_unref(priv->copy_target_list);
691     gtk_target_list_unref(priv->paste_target_list);
692     delete priv->userAgent;
693
694     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
695 }
696
697 static gboolean webkit_navigation_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
698 {
699   gboolean continueEmission = TRUE;
700   int signalHandled = g_value_get_int(handlerReturn);
701   g_value_set_int(returnAccu, signalHandled);
702
703   if (signalHandled != WEBKIT_NAVIGATION_RESPONSE_ACCEPT)
704       continueEmission = FALSE;
705
706   return continueEmission;
707 }
708
709 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
710 {
711     GtkBindingSet* binding_set;
712
713     webkit_init();
714
715     /*
716      * Signals
717      */
718
719     webkit_web_view_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation-requested",
720             G_TYPE_FROM_CLASS(webViewClass),
721             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
722             G_STRUCT_OFFSET (WebKitWebViewClass, navigation_requested),
723             webkit_navigation_request_handled,
724             NULL,
725             webkit_marshal_INT__OBJECT_OBJECT,
726             G_TYPE_INT, 2,
727             G_TYPE_OBJECT,
728             G_TYPE_OBJECT);
729
730     /**
731      * WebKitWebView::window-object-cleared:
732      * @web_view: the object on which the signal is emitted
733      * @frame: the #WebKitWebFrame to which @window_object belongs
734      * @context: the #JSGlobalContextRef holding the global object and other
735      * execution state; equivalent to the return value of
736      * webkit_web_frame_get_global_context(@frame)
737      *
738      * @window_object: the #JSObjectRef representing the frame's JavaScript
739      * window object
740      *
741      * Emitted when the JavaScript window object in a #WebKitWebFrame has been
742      * cleared in preparation for a new load. This is the preferred place to
743      * set custom properties on the window object using the JavaScriptCore API.
744      */
745     webkit_web_view_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window-object-cleared",
746             G_TYPE_FROM_CLASS(webViewClass),
747             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
748             G_STRUCT_OFFSET (WebKitWebViewClass, window_object_cleared),
749             NULL,
750             NULL,
751             webkit_marshal_VOID__OBJECT_POINTER_POINTER,
752             G_TYPE_NONE, 3,
753             WEBKIT_TYPE_WEB_FRAME,
754             G_TYPE_POINTER,
755             G_TYPE_POINTER);
756
757     /**
758      * WebKitWebView::load-started:
759      * @web_view: the object on which the signal is emitted
760      * @frame: the frame going to do the load
761      *
762      * When a #WebKitWebFrame begins to load this signal is emitted.
763      */
764     webkit_web_view_signals[LOAD_STARTED] = g_signal_new("load-started",
765             G_TYPE_FROM_CLASS(webViewClass),
766             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
767             0,
768             NULL,
769             NULL,
770             g_cclosure_marshal_VOID__OBJECT,
771             G_TYPE_NONE, 1,
772             WEBKIT_TYPE_WEB_FRAME);
773
774     /**
775      * WebKitWebView::load-committed:
776      * @web_view: the object on which the signal is emitted
777      * @frame: the main frame that received the first data
778      *
779      * When a #WebKitWebFrame loaded the first data this signal is emitted.
780      */
781     webkit_web_view_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
782             G_TYPE_FROM_CLASS(webViewClass),
783             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
784             0,
785             NULL,
786             NULL,
787             g_cclosure_marshal_VOID__OBJECT,
788             G_TYPE_NONE, 1,
789             WEBKIT_TYPE_WEB_FRAME);
790
791
792     /**
793      * WebKitWebView::load-progress-changed:
794      * @web_view: the #WebKitWebView
795      * @progress: the global progress
796      */
797     webkit_web_view_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load-progress-changed",
798             G_TYPE_FROM_CLASS(webViewClass),
799             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
800             0,
801             NULL,
802             NULL,
803             g_cclosure_marshal_VOID__INT,
804             G_TYPE_NONE, 1,
805             G_TYPE_INT);
806
807     webkit_web_view_signals[LOAD_FINISHED] = g_signal_new("load-finished",
808             G_TYPE_FROM_CLASS(webViewClass),
809             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
810             0,
811             NULL,
812             NULL,
813             g_cclosure_marshal_VOID__OBJECT,
814             G_TYPE_NONE, 1,
815             WEBKIT_TYPE_WEB_FRAME);
816
817     /**
818      * WebKitWebView::title-changed:
819      * @web_view: the object on which the signal is emitted
820      * @frame: the main frame
821      * @title: the new title
822      *
823      * When a #WebKitWebFrame changes the document title this signal is emitted.
824      */
825     webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed",
826             G_TYPE_FROM_CLASS(webViewClass),
827             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
828             0,
829             NULL,
830             NULL,
831             webkit_marshal_VOID__OBJECT_STRING,
832             G_TYPE_NONE, 2,
833             WEBKIT_TYPE_WEB_FRAME,
834             G_TYPE_STRING);
835
836     webkit_web_view_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
837             G_TYPE_FROM_CLASS(webViewClass),
838             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
839             0,
840             NULL,
841             NULL,
842             webkit_marshal_VOID__STRING_STRING,
843             G_TYPE_NONE, 2,
844             G_TYPE_STRING,
845             G_TYPE_STRING);
846
847     /**
848      * WebKitWebView::populate-popup:
849      * @web_view: the object on which the signal is emitted
850      * @menu: the context menu
851      *
852      * When a context menu is about to be displayed this signal is emitted.
853      *
854      * Add menu items to #menu to extend the context menu.
855      */
856     webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
857             G_TYPE_FROM_CLASS(webViewClass),
858             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
859             0,
860             NULL,
861             NULL,
862             g_cclosure_marshal_VOID__OBJECT,
863             G_TYPE_NONE, 1,
864             GTK_TYPE_MENU);
865
866     webkit_web_view_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status-bar-text-changed",
867             G_TYPE_FROM_CLASS(webViewClass),
868             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
869             0,
870             NULL,
871             NULL,
872             g_cclosure_marshal_VOID__STRING,
873             G_TYPE_NONE, 1,
874             G_TYPE_STRING);
875
876     webkit_web_view_signals[ICOND_LOADED] = g_signal_new("icon-loaded",
877             G_TYPE_FROM_CLASS(webViewClass),
878             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
879             0,
880             NULL,
881             NULL,
882             g_cclosure_marshal_VOID__VOID,
883             G_TYPE_NONE, 0);
884
885     webkit_web_view_signals[SELECTION_CHANGED] = g_signal_new("selection-changed",
886             G_TYPE_FROM_CLASS(webViewClass),
887             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
888             0,
889             NULL,
890             NULL,
891             g_cclosure_marshal_VOID__VOID,
892             G_TYPE_NONE, 0);
893
894     /**
895      * WebKitWebView::console-message:
896      * @web_view: the object on which the signal is emitted
897      * @message: the message text
898      * @line: the line where the error occured
899      * @source_id: the source id
900      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
901      *
902      * A JavaScript console message was created.
903      */
904     webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message",
905             G_TYPE_FROM_CLASS(webViewClass),
906             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
907             G_STRUCT_OFFSET(WebKitWebViewClass, console_message),
908             g_signal_accumulator_true_handled,
909             NULL,
910             webkit_marshal_BOOLEAN__STRING_INT_STRING,
911             G_TYPE_BOOLEAN, 3,
912             G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
913
914     /**
915      * WebKitWebView::script-alert:
916      * @web_view: the object on which the signal is emitted
917      * @frame: the relevant frame
918      * @message: the message text
919      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
920      *
921      * A JavaScript alert dialog was created.
922      */
923     webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
924             G_TYPE_FROM_CLASS(webViewClass),
925             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
926             G_STRUCT_OFFSET(WebKitWebViewClass, script_alert),
927             g_signal_accumulator_true_handled,
928             NULL,
929             webkit_marshal_BOOLEAN__OBJECT_STRING,
930             G_TYPE_BOOLEAN, 2,
931             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING);
932
933     /**
934      * WebKitWebView::script-confirm:
935      * @web_view: the object on which the signal is emitted
936      * @frame: the relevant frame
937      * @message: the message text
938      * @confirmed: whether the dialog has been confirmed
939      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
940      *
941      * A JavaScript confirm dialog was created, providing Yes and No buttons.
942      */
943     webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm",
944             G_TYPE_FROM_CLASS(webViewClass),
945             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
946             G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm),
947             g_signal_accumulator_true_handled,
948             NULL,
949             webkit_marshal_BOOLEAN__OBJECT_STRING_BOOLEAN,
950             G_TYPE_BOOLEAN, 3,
951             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_BOOLEAN);
952
953     /**
954      * WebKitWebView::script-prompt:
955      * @web_view: the object on which the signal is emitted
956      * @frame: the relevant frame
957      * @message: the message text
958      * @default: the default value
959      * @text: To be filled with the return value or NULL if the dialog was cancelled.
960      * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
961      *
962      * A JavaScript prompt dialog was created, providing an entry to input text.
963      */
964     webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt",
965             G_TYPE_FROM_CLASS(webViewClass),
966             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
967             G_STRUCT_OFFSET(WebKitWebViewClass, script_prompt),
968             g_signal_accumulator_true_handled,
969             NULL,
970             webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
971             G_TYPE_BOOLEAN, 4,
972             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
973
974     /**
975      * WebKitWebView::select-all:
976      * @web_view: the object which received the signal
977      *
978      * The ::select-all signal is a keybinding signal which gets emitted to
979      * select the complete contents of the text view.
980      *
981      * The default bindings for this signal is Ctrl-a.
982      */
983     webkit_web_view_signals[SELECT_ALL] = g_signal_new("select-all",
984             G_TYPE_FROM_CLASS(webViewClass),
985             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
986             G_STRUCT_OFFSET(WebKitWebViewClass, select_all),
987             NULL, NULL,
988             g_cclosure_marshal_VOID__VOID,
989             G_TYPE_NONE, 0);
990
991     /**
992      * WebKitWebView::cut-clipboard:
993      * @web_view: the object which received the signal
994      *
995      * The ::cut-clipboard signal is a keybinding signal which gets emitted to
996      * cut the selection to the clipboard.
997      *
998      * The default bindings for this signal are Ctrl-x and Shift-Delete.
999      */
1000     webkit_web_view_signals[CUT_CLIPBOARD] = g_signal_new("cut-clipboard",
1001             G_TYPE_FROM_CLASS(webViewClass),
1002             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1003             G_STRUCT_OFFSET(WebKitWebViewClass, cut_clipboard),
1004             NULL, NULL,
1005             g_cclosure_marshal_VOID__VOID,
1006             G_TYPE_NONE, 0);
1007
1008     /**
1009      * WebKitWebView::copy-clipboard:
1010      * @web_view: the object which received the signal
1011      *
1012      * The ::copy-clipboard signal is a keybinding signal which gets emitted to
1013      * copy the selection to the clipboard.
1014      *
1015      * The default bindings for this signal are Ctrl-c and Ctrl-Insert.
1016      */
1017     webkit_web_view_signals[COPY_CLIPBOARD] = g_signal_new("copy-clipboard",
1018             G_TYPE_FROM_CLASS(webViewClass),
1019             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1020             G_STRUCT_OFFSET(WebKitWebViewClass, copy_clipboard),
1021             NULL, NULL,
1022             g_cclosure_marshal_VOID__VOID,
1023             G_TYPE_NONE, 0);
1024
1025     /**
1026      * WebKitWebView::paste-clipboard:
1027      * @web_view: the object which received the signal
1028      *
1029      * The ::paste-clipboard signal is a keybinding signal which gets emitted to
1030      * paste the contents of the clipboard into the Web view.
1031      *
1032      * The default bindings for this signal are Ctrl-v and Shift-Insert.
1033      */
1034     webkit_web_view_signals[PASTE_CLIPBOARD] = g_signal_new("paste-clipboard",
1035             G_TYPE_FROM_CLASS(webViewClass),
1036             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1037             G_STRUCT_OFFSET(WebKitWebViewClass, paste_clipboard),
1038             NULL, NULL,
1039             g_cclosure_marshal_VOID__VOID,
1040             G_TYPE_NONE, 0);
1041
1042     /*
1043      * implementations of virtual methods
1044      */
1045     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
1046     webViewClass->navigation_requested = webkit_web_view_real_navigation_requested;
1047     webViewClass->window_object_cleared = webkit_web_view_real_window_object_cleared;
1048     webViewClass->choose_file = webkit_web_view_real_choose_file;
1049     webViewClass->script_alert = webkit_web_view_real_script_alert;
1050     webViewClass->script_confirm = webkit_web_view_real_script_confirm;
1051     webViewClass->script_prompt = webkit_web_view_real_script_prompt;
1052     webViewClass->console_message = webkit_web_view_real_console_message;
1053     webViewClass->select_all = webkit_web_view_real_select_all;
1054     webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard;
1055     webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard;
1056     webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard;
1057
1058     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
1059     objectClass->finalize = webkit_web_view_finalize;
1060     objectClass->get_property = webkit_web_view_get_property;
1061     objectClass->set_property = webkit_web_view_set_property;
1062
1063     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webViewClass);
1064     widgetClass->realize = webkit_web_view_realize;
1065     widgetClass->expose_event = webkit_web_view_expose_event;
1066     widgetClass->key_press_event = webkit_web_view_key_press_event;
1067     widgetClass->key_release_event = webkit_web_view_key_release_event;
1068     widgetClass->button_press_event = webkit_web_view_button_press_event;
1069     widgetClass->button_release_event = webkit_web_view_button_release_event;
1070     widgetClass->motion_notify_event = webkit_web_view_motion_event;
1071     widgetClass->scroll_event = webkit_web_view_scroll_event;
1072     widgetClass->size_allocate = webkit_web_view_size_allocate;
1073     widgetClass->popup_menu = webkit_web_view_popup_menu_handler;
1074     widgetClass->focus_in_event = webkit_web_view_focus_in_event;
1075
1076     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
1077     containerClass->add = webkit_web_view_container_add;
1078     containerClass->remove = webkit_web_view_container_remove;
1079     containerClass->forall = webkit_web_view_container_forall;
1080
1081     /*
1082      * make us scrollable (e.g. addable to a GtkScrolledWindow)
1083      */
1084     webViewClass->set_scroll_adjustments = webkit_web_view_set_scroll_adjustments;
1085     GTK_WIDGET_CLASS(webViewClass)->set_scroll_adjustments_signal = g_signal_new("set-scroll-adjustments",
1086             G_TYPE_FROM_CLASS(webViewClass),
1087             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
1088             G_STRUCT_OFFSET(WebKitWebViewClass, set_scroll_adjustments),
1089             NULL, NULL,
1090             webkit_marshal_VOID__OBJECT_OBJECT,
1091             G_TYPE_NONE, 2,
1092             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1093
1094     /*
1095      * Key bindings
1096      */
1097
1098     binding_set = gtk_binding_set_by_class(webViewClass);
1099
1100     gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
1101                                  "select_all", 0);
1102
1103     /* Cut/copy/paste */
1104
1105     gtk_binding_entry_add_signal(binding_set, GDK_x, GDK_CONTROL_MASK,
1106                                  "cut_clipboard", 0);
1107     gtk_binding_entry_add_signal(binding_set, GDK_c, GDK_CONTROL_MASK,
1108                                  "copy_clipboard", 0);
1109     gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK,
1110                                  "paste_clipboard", 0);
1111
1112     gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_SHIFT_MASK,
1113                                  "cut_clipboard", 0);
1114     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_CONTROL_MASK,
1115                                  "copy_clipboard", 0);
1116     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_SHIFT_MASK,
1117                                  "paste_clipboard", 0);
1118
1119     /*
1120      * properties
1121      */
1122     g_object_class_install_property(objectClass, PROP_COPY_TARGET_LIST,
1123                                     g_param_spec_boxed("copy-target-list",
1124                                                        "Target list",
1125                                                        "The list of targets this Web view supports for copying to the clipboard",
1126                                                        GTK_TYPE_TARGET_LIST,
1127                                                        WEBKIT_PARAM_READABLE));
1128
1129     g_object_class_install_property(objectClass, PROP_PASTE_TARGET_LIST,
1130                                     g_param_spec_boxed("paste-target-list",
1131                                                        "Target list",
1132                                                        "The list of targets this Web view supports for pasting to the clipboard",
1133                                                        GTK_TYPE_TARGET_LIST,
1134                                                        WEBKIT_PARAM_READABLE));
1135
1136     g_object_class_install_property(objectClass, PROP_SETTINGS,
1137                                     g_param_spec_object("settings",
1138                                                         "Settings",
1139                                                         "An associated WebKitWebSettings instance",
1140                                                         WEBKIT_TYPE_WEB_SETTINGS,
1141                                                         WEBKIT_PARAM_READWRITE));
1142
1143     g_object_class_install_property(objectClass, PROP_EDITABLE,
1144                                     g_param_spec_boolean("editable",
1145                                                          "Editable",
1146                                                          "Whether content can be modified by the user",
1147                                                          FALSE,
1148                                                          WEBKIT_PARAM_READWRITE));
1149
1150     g_object_class_install_property(objectClass, PROP_TRANSPARENT,
1151                                     g_param_spec_boolean("transparent",
1152                                                          "Transparent",
1153                                                          "Whether content has a transparent background",
1154                                                          FALSE,
1155                                                          WEBKIT_PARAM_READWRITE));
1156
1157     g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
1158 }
1159
1160 static void webkit_web_view_screen_changed(WebKitWebView* webView, GdkScreen* previousScreen, gpointer userdata)
1161 {
1162     WebKitWebViewPrivate* priv = webView->priv;
1163     WebKitWebSettings* webSettings = priv->webSettings;
1164     Settings* settings = core(webView)->settings();
1165
1166     guint defaultFontSize, defaultMonospaceFontSize, minimumFontSize, minimumLogicalFontSize;
1167
1168     g_object_get(G_OBJECT(webSettings),
1169                  "default-font-size", &defaultFontSize,
1170                  "default-monospace-font-size", &defaultMonospaceFontSize,
1171                  "minimum-font-size", &minimumFontSize,
1172                  "minimum-logical-font-size", &minimumLogicalFontSize,
1173                  NULL);
1174
1175     gdouble DPI = defaultDPI;
1176 #if GTK_CHECK_VERSION(2,10,0)
1177     GdkScreen* screen = gtk_widget_has_screen(GTK_WIDGET(webView)) ? gtk_widget_get_screen(GTK_WIDGET(webView)) : gdk_screen_get_default();
1178     if (screen) {
1179         DPI = gdk_screen_get_resolution(screen);
1180         // gdk_screen_get_resolution() returns -1 when no DPI is set.
1181         if (DPI == -1)
1182             DPI = defaultDPI;
1183     }
1184 #endif
1185     ASSERT(DPI > 0);
1186     settings->setDefaultFontSize(defaultFontSize / 72.0 * DPI);
1187     settings->setDefaultFixedFontSize(defaultMonospaceFontSize / 72.0 * DPI);
1188     settings->setMinimumFontSize(minimumFontSize / 72.0 * DPI);
1189     settings->setMinimumLogicalFontSize(minimumLogicalFontSize / 72.0 * DPI);
1190 }
1191
1192 static void webkit_web_view_update_settings(WebKitWebView* webView)
1193 {
1194     WebKitWebViewPrivate* priv = webView->priv;
1195     WebKitWebSettings* webSettings = priv->webSettings;
1196     Settings* settings = core(webView)->settings();
1197
1198     gchar* defaultEncoding, *cursiveFontFamily, *defaultFontFamily, *fantasyFontFamily, *monospaceFontFamily, *sansSerifFontFamily, *serifFontFamily, *userStylesheetUri;
1199     gboolean autoLoadImages, autoShrinkImages, printBackgrounds, enableScripts, enablePlugins, resizableTextAreas;
1200
1201     g_object_get(G_OBJECT(webSettings),
1202                  "default-encoding", &defaultEncoding,
1203                  "cursive-font-family", &cursiveFontFamily,
1204                  "default-font-family", &defaultFontFamily,
1205                  "fantasy-font-family", &fantasyFontFamily,
1206                  "monospace-font-family", &monospaceFontFamily,
1207                  "sans-serif-font-family", &sansSerifFontFamily,
1208                  "serif-font-family", &serifFontFamily,
1209                  "auto-load-images", &autoLoadImages,
1210                  "auto-shrink-images", &autoShrinkImages,
1211                  "print-backgrounds", &printBackgrounds,
1212                  "enable-scripts", &enableScripts,
1213                  "enable-plugins", &enablePlugins,
1214                  "resizable-text-areas", &resizableTextAreas,
1215                  "user-stylesheet-uri", &userStylesheetUri,
1216                  NULL);
1217
1218     settings->setDefaultTextEncodingName(defaultEncoding);
1219     settings->setCursiveFontFamily(cursiveFontFamily);
1220     settings->setStandardFontFamily(defaultFontFamily);
1221     settings->setFantasyFontFamily(fantasyFontFamily);
1222     settings->setFixedFontFamily(monospaceFontFamily);
1223     settings->setSansSerifFontFamily(sansSerifFontFamily);
1224     settings->setSerifFontFamily(serifFontFamily);
1225     settings->setLoadsImagesAutomatically(autoLoadImages);
1226     settings->setShrinksStandaloneImagesToFit(autoShrinkImages);
1227     settings->setShouldPrintBackgrounds(printBackgrounds);
1228     settings->setJavaScriptEnabled(enableScripts);
1229     settings->setPluginsEnabled(enablePlugins);
1230     settings->setTextAreasAreResizable(resizableTextAreas);
1231     settings->setUserStyleSheetLocation(KURL(userStylesheetUri));
1232
1233     g_free(defaultEncoding);
1234     g_free(cursiveFontFamily);
1235     g_free(defaultFontFamily);
1236     g_free(fantasyFontFamily);
1237     g_free(monospaceFontFamily);
1238     g_free(sansSerifFontFamily);
1239     g_free(serifFontFamily);
1240     g_free(userStylesheetUri);
1241
1242     webkit_web_view_screen_changed(webView, NULL, NULL);
1243 }
1244
1245 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView)
1246 {
1247     Settings* settings = core(webView)->settings();
1248
1249     const gchar* name = g_intern_string(pspec->name);
1250     GValue value = { 0, { { 0 } } };
1251     g_value_init(&value, pspec->value_type);
1252     g_object_get_property(G_OBJECT(webSettings), name, &value);
1253
1254     if (name == g_intern_string("default-encoding"))
1255         settings->setDefaultTextEncodingName(g_value_get_string(&value));
1256     else if (name == g_intern_string("cursive-font-family"))
1257         settings->setCursiveFontFamily(g_value_get_string(&value));
1258     else if (name == g_intern_string("default-font-family"))
1259         settings->setStandardFontFamily(g_value_get_string(&value));
1260     else if (name == g_intern_string("fantasy-font-family"))
1261         settings->setFantasyFontFamily(g_value_get_string(&value));
1262     else if (name == g_intern_string("monospace-font-family"))
1263         settings->setFixedFontFamily(g_value_get_string(&value));
1264     else if (name == g_intern_string("sans-serif-font-family"))
1265         settings->setSansSerifFontFamily(g_value_get_string(&value));
1266     else if (name == g_intern_string("serif-font-family"))
1267         settings->setSerifFontFamily(g_value_get_string(&value));
1268     else if (name == g_intern_string("default-font-size"))
1269         settings->setDefaultFontSize(g_value_get_int(&value));
1270     else if (name == g_intern_string("default-monospace-font-size"))
1271         settings->setDefaultFixedFontSize(g_value_get_int(&value));
1272     else if (name == g_intern_string("minimum-font-size"))
1273         settings->setMinimumFontSize(g_value_get_int(&value));
1274     else if (name == g_intern_string("minimum-logical-font-size"))
1275         settings->setMinimumLogicalFontSize(g_value_get_int(&value));
1276     else if (name == g_intern_string("auto-load-images"))
1277         settings->setLoadsImagesAutomatically(g_value_get_boolean(&value));
1278     else if (name == g_intern_string("auto-shrink-images"))
1279         settings->setShrinksStandaloneImagesToFit(g_value_get_boolean(&value));
1280     else if (name == g_intern_string("print-backgrounds"))
1281         settings->setShouldPrintBackgrounds(g_value_get_boolean(&value));
1282     else if (name == g_intern_string("enable-scripts"))
1283         settings->setJavaScriptEnabled(g_value_get_boolean(&value));
1284     else if (name == g_intern_string("enable-plugins"))
1285         settings->setPluginsEnabled(g_value_get_boolean(&value));
1286     else if (name == g_intern_string("resizable-text-areas"))
1287         settings->setTextAreasAreResizable(g_value_get_boolean(&value));
1288     else if (name == g_intern_string("user-stylesheet-uri"))
1289         settings->setUserStyleSheetLocation(KURL(g_value_get_string(&value)));
1290     else if (!g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), name))
1291         g_warning("Unexpected setting '%s'", name);
1292     g_value_unset(&value);
1293 }
1294
1295 static void webkit_web_view_init(WebKitWebView* webView)
1296 {
1297     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
1298     webView->priv = priv;
1299
1300     priv->imContext = gtk_im_multicontext_new();
1301     priv->corePage = new Page(new WebKit::ChromeClient(webView), new WebKit::ContextMenuClient, new WebKit::EditorClient(webView), new WebKit::DragClient, new WebKit::InspectorClient);
1302
1303     priv->horizontalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1304     priv->verticalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1305
1306 #if GLIB_CHECK_VERSION(2,10,0)
1307     g_object_ref_sink(priv->horizontalAdjustment);
1308     g_object_ref_sink(priv->verticalAdjustment);
1309 #else
1310     g_object_ref(priv->horizontalAdjustment);
1311     gtk_object_sink(GTK_OBJECT(priv->horizontalAdjustment));
1312     g_object_ref(priv->verticalAdjustment);
1313     gtk_object_sink(GTK_OBJECT(priv->verticalAdjustment));
1314 #endif
1315
1316     GTK_WIDGET_SET_FLAGS(webView, GTK_CAN_FOCUS);
1317     priv->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
1318     priv->lastPopupXPosition = priv->lastPopupYPosition = -1;
1319     priv->editable = false;
1320
1321     priv->backForwardList = webkit_web_back_forward_list_new_with_web_view(webView);
1322
1323 #if GTK_CHECK_VERSION(2,10,0)
1324     GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
1325 #else
1326     GdkAtom textHtml = gdk_atom_intern("text/html", false);
1327 #endif
1328     /* Targets for copy */
1329     priv->copy_target_list = gtk_target_list_new(NULL, 0);
1330     gtk_target_list_add(priv->copy_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
1331     gtk_target_list_add_text_targets(priv->copy_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
1332
1333     /* Targets for pasting */
1334     priv->paste_target_list = gtk_target_list_new(NULL, 0);
1335     gtk_target_list_add(priv->paste_target_list, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML);
1336     gtk_target_list_add_text_targets(priv->paste_target_list, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT);
1337
1338     priv->webSettings = webkit_web_settings_new();
1339     webkit_web_view_update_settings(webView);
1340     g_signal_connect(webView, "screen-changed", G_CALLBACK(webkit_web_view_screen_changed), NULL);
1341     g_signal_connect(priv->webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
1342 }
1343
1344 GtkWidget* webkit_web_view_new(void)
1345 {
1346     WebKitWebView* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
1347
1348     return GTK_WIDGET(webView);
1349 }
1350
1351 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitWebSettings* webSettings)
1352 {
1353     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1354     g_return_if_fail(WEBKIT_IS_WEB_SETTINGS(webSettings));
1355
1356     WebKitWebViewPrivate* priv = webView->priv;
1357     g_signal_handlers_disconnect_by_func(priv->webSettings, (gpointer)webkit_web_view_settings_notify, webView);
1358     g_object_unref(priv->webSettings);
1359     g_object_ref(webSettings);
1360     priv->webSettings = webSettings;
1361     webkit_web_view_update_settings(webView);
1362     g_signal_connect(webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
1363 }
1364
1365 WebKitWebSettings* webkit_web_view_get_settings(WebKitWebView* webView)
1366 {
1367     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1368
1369     WebKitWebViewPrivate* priv = webView->priv;
1370     return priv->webSettings;
1371 }
1372
1373 /**
1374  * webkit_web_view_set_maintains_back_forward_list:
1375  * @webView: a #WebKitWebView
1376  * @flag: to tell the view to maintain a back or forward list
1377  *
1378  * Set the view to maintain a back or forward list of history items.
1379  */
1380 void webkit_web_view_set_maintains_back_forward_list(WebKitWebView* webView, gboolean flag)
1381 {
1382     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1383
1384     core(webView)->backForwardList()->setEnabled(flag);
1385 }
1386
1387 /**
1388  * webkit_web_view_get_back_forward_list:
1389  * @webView: a #WebKitWebView
1390  *
1391  * Returns a #WebKitWebBackForwardList
1392  *
1393  * Return value: the #WebKitWebBackForwardList
1394  */
1395 WebKitWebBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
1396 {
1397     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1398
1399     WebKitWebViewPrivate* priv = webView->priv;
1400
1401     if (!core(webView) || !core(webView)->backForwardList()->enabled())
1402         return NULL;
1403
1404     return priv->backForwardList;
1405 }
1406
1407 /**
1408  * webkit_web_view_go_to_back_forward_item:
1409  * @webView: a #WebKitWebView
1410  * @item: a #WebKitWebHistoryItem*
1411  *
1412  * Go to the specified #WebKitWebHistoryItem
1413  *
1414  * Return value: %TRUE if loading of item is successful, %FALSE if not
1415  */
1416 gboolean webkit_web_view_go_to_back_forward_item(WebKitWebView* webView, WebKitWebHistoryItem* item)
1417 {
1418     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1419     g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(item), FALSE);
1420
1421     // FIXME: This always returns TRUE
1422     core(webView)->goToItem(core(item), FrameLoadTypeIndexedBackForward);
1423     return TRUE;
1424 }
1425
1426 /**
1427  * webkit_web_view_go_backward:
1428  * @webView: the #WebKitWebView
1429  *
1430  * @Deprecated: Use webkit_web_view_go_back() instead.
1431  *
1432  * Go to the previous page, if there's any.
1433  */
1434 void webkit_web_view_go_backward(WebKitWebView* webView)
1435 {
1436     g_warning("webkit_web_view_go_backward() is obsolete; use webkit_web_view_go_back()");
1437     webkit_web_view_go_back(webView);
1438 }
1439
1440 /**
1441  * webkit_web_view_go_back:
1442  * @web_view: a #WebKitWebView
1443  *
1444  * Loads the previous history item.
1445  */
1446 void webkit_web_view_go_back(WebKitWebView* webView)
1447 {
1448     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1449
1450     core(webView)->goBack();
1451 }
1452
1453 /**
1454  * webkit_web_view_go_back_or_forward:
1455  * @web_view: a #WebKitWebView
1456  * @steps: the number of steps
1457  *
1458  * Loads the history item that is the number of @steps away from the current
1459  * item. Negative values represent steps backward while positive values
1460  * represent steps forward.
1461  */
1462 void webkit_web_view_go_back_or_forward(WebKitWebView* webView, gint steps)
1463 {
1464     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1465
1466     Frame* frame = core(webView)->mainFrame();
1467     frame->loader()->goBackOrForward(steps);
1468 }
1469
1470 /**
1471  * webkit_web_view_go_forward:
1472  * @web_view: a #WebKitWebView
1473  *
1474  * Loads the next history item.
1475  */
1476 void webkit_web_view_go_forward(WebKitWebView* webView)
1477 {
1478     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1479
1480     core(webView)->goForward();
1481 }
1482
1483 /**
1484  * webkit_web_view_can_go_backward:
1485  * @webView: the #WebKitWebView
1486  *
1487  * Checks whether the view can go back to the previous page
1488  *
1489  * @Deprecated: Use webkit_web_view_can_go_back() instead.
1490  *
1491  * Return value: %TRUE if the page can go back, otherwise returns %FALSE
1492  */
1493 gboolean webkit_web_view_can_go_backward(WebKitWebView* webView)
1494 {
1495     g_warning("webkit_web_view_can_go_backward() is obsolete; use webkit_web_view_can_go_back()");
1496     return webkit_web_view_can_go_back(webView);
1497 }
1498
1499 /**
1500  * webkit_web_view_can_go_back:
1501  * @web_view: a #WebKitWebView
1502  *
1503  * Determines whether #web_view has a previous history item.
1504  *
1505  * Return value: %TRUE if able to move back, %FALSE otherwise
1506  */
1507 gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
1508 {
1509     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1510
1511     if (!core(webView) || !core(webView)->backForwardList()->backItem())
1512         return FALSE;
1513
1514     return TRUE;
1515 }
1516
1517 /**
1518  * webkit_web_view_can_go_back_or_forward:
1519  * @web_view: a #WebKitWebView
1520  * @steps: the number of steps
1521  *
1522  * Determines whether #web_view has a history item of @steps. Negative values
1523  * represent steps backward while positive values represent steps forward.
1524  *
1525  * Return value: %TRUE if able to move back or forward the given number of
1526  * steps, %FALSE otherwise
1527  */
1528 gboolean webkit_web_view_can_go_back_or_forward(WebKitWebView* webView, gint steps)
1529 {
1530     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1531
1532     Frame* frame = core(webView)->mainFrame();
1533     return frame->loader()->canGoBackOrForward(steps);
1534 }
1535
1536 /**
1537  * webkit_web_view_can_go_forward:
1538  * @web_view: a #WebKitWebView
1539  *
1540  * Determines whether #web_view has a next history item.
1541  *
1542  * Return value: %TRUE if able to move forward, %FALSE otherwise
1543  */
1544 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
1545 {
1546     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1547
1548     Page* page = core(webView);
1549
1550     if (!page)
1551         return FALSE;
1552
1553     if (!page->backForwardList()->forwardItem())
1554         return FALSE;
1555
1556     return TRUE;
1557 }
1558
1559 void webkit_web_view_open(WebKitWebView* webView, const gchar* uri)
1560 {
1561     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1562     g_return_if_fail(uri);
1563
1564     Frame* frame = core(webView)->mainFrame();
1565     frame->loader()->load(ResourceRequest(KURL(String::fromUTF8(uri))));
1566 }
1567
1568 void webkit_web_view_reload(WebKitWebView* webView)
1569 {
1570     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1571
1572     core(webView)->mainFrame()->loader()->reload();
1573 }
1574
1575 void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* contentMimeType, const gchar* contentEncoding, const gchar* baseUri)
1576 {
1577     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1578     g_return_if_fail(content);
1579
1580     Frame* frame = core(webView)->mainFrame();
1581
1582     KURL url(baseUri ? String::fromUTF8(baseUri) : "");
1583     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(strdup(content), strlen(content));
1584     SubstituteData substituteData(sharedBuffer.release(), contentMimeType ? String(contentMimeType) : "text/html", contentEncoding ? String(contentEncoding) : "UTF-8", KURL("about:blank"), url);
1585
1586     frame->loader()->load(ResourceRequest(url), substituteData);
1587 }
1588
1589 void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* content, const gchar* baseUri)
1590 {
1591     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1592     g_return_if_fail(content);
1593
1594     webkit_web_view_load_string(webView, content, NULL, NULL, baseUri);
1595 }
1596
1597 void webkit_web_view_stop_loading(WebKitWebView* webView)
1598 {
1599     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1600
1601     Frame* frame = core(webView)->mainFrame();
1602
1603     if (FrameLoader* loader = frame->loader())
1604         loader->stopAllLoaders();
1605 }
1606
1607 /**
1608  * webkit_web_view_search_text:
1609  * @web_view: a #WebKitWebView
1610  * @text: a string to look for
1611  * @forward: whether to find forward or not
1612  * @case_sensitive: whether to respect the case of text
1613  * @wrap: whether to continue looking at the beginning after reaching the end
1614  *
1615  * Looks for a specified string inside #web_view.
1616  *
1617  * Return value: %TRUE on success or %FALSE on failure
1618  */
1619 gboolean webkit_web_view_search_text(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, gboolean forward, gboolean shouldWrap)
1620 {
1621     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1622     g_return_val_if_fail(string, FALSE);
1623
1624     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
1625     FindDirection direction = forward ? FindDirectionForward : FindDirectionBackward;
1626
1627     return core(webView)->findString(String::fromUTF8(string), caseSensitivity, direction, shouldWrap);
1628 }
1629
1630 /**
1631  * webkit_web_view_mark_text_matches:
1632  * @web_view: a #WebKitWebView
1633  * @string: a string to look for
1634  * @case_sensitive: whether to respect the case of text
1635  * @limit: the maximum number of strings to look for or %0 for all
1636  *
1637  * Attempts to highlight all occurances of #string inside #web_view.
1638  *
1639  * Return value: the number of strings highlighted
1640  */
1641 guint webkit_web_view_mark_text_matches(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, guint limit)
1642 {
1643     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1644     g_return_val_if_fail(string, 0);
1645
1646     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
1647
1648     return core(webView)->markAllMatchesForText(String::fromUTF8(string), caseSensitivity, false, limit);
1649 }
1650
1651 /**
1652  * webkit_web_view_set_highlight_text_matches:
1653  * @web_view: a #WebKitWebView
1654  * @highlight: whether to highlight text matches
1655  *
1656  * Highlights text matches previously marked by webkit_web_view_mark_text_matches.
1657  */
1658 void webkit_web_view_set_highlight_text_matches(WebKitWebView* webView, gboolean shouldHighlight)
1659 {
1660     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1661
1662     core(webView)->mainFrame()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
1663 }
1664
1665 /**
1666  * webkit_web_view_unmark_text_matches:
1667  * @web_view: a #WebKitWebView
1668  *
1669  * Removes highlighting previously set by webkit_web_view_mark_text_matches.
1670  */
1671 void webkit_web_view_unmark_text_matches(WebKitWebView* webView)
1672 {
1673     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1674
1675     return core(webView)->unmarkAllTextMatches();
1676 }
1677
1678 WebKitWebFrame* webkit_web_view_get_main_frame(WebKitWebView* webView)
1679 {
1680     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1681
1682     WebKitWebViewPrivate* priv = webView->priv;
1683     return priv->mainFrame;
1684 }
1685
1686 /**
1687  * webkit_web_view_get_focused_frame:
1688  * @web_view: a #WebKitWebView
1689  *
1690  * Returns the frame that has focus or an active text selection.
1691  *
1692  * Return value: The focused #WebKitWebFrame or %NULL if no frame is focused
1693  */
1694 WebKitWebFrame* webkit_web_view_get_focused_frame(WebKitWebView* webView)
1695 {
1696     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1697
1698     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
1699     return kit(focusedFrame);
1700 }
1701
1702 void webkit_web_view_execute_script(WebKitWebView* webView, const gchar* script)
1703 {
1704     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1705     g_return_if_fail(script);
1706
1707     if (FrameLoader* loader = core(webView)->mainFrame()->loader())
1708         loader->executeScript(String::fromUTF8(script), true);
1709 }
1710
1711 /**
1712  * webkit_web_view_cut_clipboard:
1713  * @web_view: a #WebKitWebView
1714  *
1715  * Determines whether or not it is currently possible to cut to the clipboard.
1716  *
1717  * Return value: %TRUE if a selection can be cut, %FALSE if not
1718  */
1719 gboolean webkit_web_view_can_cut_clipboard(WebKitWebView* webView)
1720 {
1721     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1722
1723     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1724     return frame->editor()->canCut() || frame->editor()->canDHTMLCut();
1725 }
1726
1727 /**
1728  * webkit_web_view_copy_clipboard:
1729  * @web_view: a #WebKitWebView
1730  *
1731  * Determines whether or not it is currently possible to copy to the clipboard.
1732  *
1733  * Return value: %TRUE if a selection can be copied, %FALSE if not
1734  */
1735 gboolean webkit_web_view_can_copy_clipboard(WebKitWebView* webView)
1736 {
1737     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1738
1739     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1740     return frame->editor()->canCopy() || frame->editor()->canDHTMLCopy();
1741 }
1742
1743 /**
1744  * webkit_web_view_paste_clipboard:
1745  * @web_view: a #WebKitWebView
1746  *
1747  * Determines whether or not it is currently possible to paste from the clipboard.
1748  *
1749  * Return value: %TRUE if a selection can be pasted, %FALSE if not
1750  */
1751 gboolean webkit_web_view_can_paste_clipboard(WebKitWebView* webView)
1752 {
1753     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1754
1755     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1756     return frame->editor()->canPaste() || frame->editor()->canDHTMLPaste();
1757 }
1758
1759 /**
1760  * webkit_web_view_cut_clipboard:
1761  * @web_view: a #WebKitWebView
1762  *
1763  * Cuts the current selection inside the @web_view to the clipboard.
1764  */
1765 void webkit_web_view_cut_clipboard(WebKitWebView* webView)
1766 {
1767     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1768
1769     if (webkit_web_view_can_cut_clipboard(webView))
1770         g_signal_emit(webView, webkit_web_view_signals[CUT_CLIPBOARD], 0);
1771 }
1772
1773 /**
1774  * webkit_web_view_copy_clipboard:
1775  * @web_view: a #WebKitWebView
1776  *
1777  * Copies the current selection inside the @web_view to the clipboard.
1778  */
1779 void webkit_web_view_copy_clipboard(WebKitWebView* webView)
1780 {
1781     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1782
1783     if (webkit_web_view_can_copy_clipboard(webView))
1784         g_signal_emit(webView, webkit_web_view_signals[COPY_CLIPBOARD], 0);
1785 }
1786
1787 /**
1788  * webkit_web_view_paste_clipboard:
1789  * @web_view: a #WebKitWebView
1790  *
1791  * Pastes the current contents of the clipboard to the @web_view.
1792  */
1793 void webkit_web_view_paste_clipboard(WebKitWebView* webView)
1794 {
1795     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1796
1797     if (webkit_web_view_can_paste_clipboard(webView))
1798         g_signal_emit(webView, webkit_web_view_signals[PASTE_CLIPBOARD], 0);
1799 }
1800
1801 /**
1802  * webkit_web_view_delete_selection:
1803  * @web_view: a #WebKitWebView
1804  *
1805  * Deletes the current selection inside the @web_view.
1806  */
1807 void webkit_web_view_delete_selection(WebKitWebView* webView)
1808 {
1809     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1810
1811     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1812     frame->editor()->performDelete();
1813 }
1814
1815 /**
1816  * webkit_web_view_has_selection:
1817  * @web_view: a #WebKitWebView
1818  *
1819  * Determines whether text was selected.
1820  *
1821  * Return value: %TRUE if there is selected text, %FALSE if not
1822  */
1823 gboolean webkit_web_view_has_selection(WebKitWebView* webView)
1824 {
1825     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1826
1827     return !core(webView)->selection().isNone();
1828 }
1829
1830 /**
1831  * webkit_web_view_get_selected_text:
1832  * @web_view: a #WebKitWebView
1833  *
1834  * Retrieves the selected text if any.
1835  *
1836  * Return value: a newly allocated string with the selection or %NULL
1837  */
1838 gchar* webkit_web_view_get_selected_text(WebKitWebView* webView)
1839 {
1840     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1841
1842     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
1843     return g_strdup(frame->selectedText().utf8().data());
1844 }
1845
1846 /**
1847  * webkit_web_view_select_all:
1848  * @web_view: a #WebKitWebView
1849  *
1850  * Attempts to select everything inside the @web_view.
1851  */
1852 void webkit_web_view_select_all(WebKitWebView* webView)
1853 {
1854     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1855
1856     g_signal_emit(webView, webkit_web_view_signals[SELECT_ALL], 0);
1857 }
1858
1859 /**
1860  * webkit_web_view_get_editable:
1861  * @web_view: a #WebKitWebView
1862  *
1863  * Returns whether the user is allowed to edit the document.
1864  *
1865  * Returns %TRUE if @web_view allows the user to edit the HTML document, %FALSE if
1866  * it doesn't. You can change @web_view's document programmatically regardless of
1867  * this setting.
1868  *
1869  * Return value: a #gboolean indicating the editable state
1870  */
1871 gboolean webkit_web_view_get_editable(WebKitWebView* webView)
1872 {
1873     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1874
1875     WebKitWebViewPrivate* priv = webView->priv;
1876
1877     return priv->editable;
1878 }
1879
1880 /**
1881  * webkit_web_view_set_editable:
1882  * @web_view: a #WebKitWebView
1883  * @flag: a #gboolean indicating the editable state
1884  *
1885  * Sets whether @web_view allows the user to edit its HTML document.
1886  *
1887  * If @flag is %TRUE, @web_view allows the user to edit the document. If @flag is
1888  * %FALSE, an element in @web_view's document can only be edited if the
1889  * CONTENTEDITABLE attribute has been set on the element or one of its parent
1890  * elements. You can change @web_view's document programmatically regardless of
1891  * this setting. By default a #WebKitWebView is not editable.
1892
1893  * Normally, an HTML document is not editable unless the elements within the
1894  * document are editable. This function provides a low-level way to make the
1895  * contents of a #WebKitWebView editable without altering the document or DOM
1896  * structure.
1897  */
1898 void webkit_web_view_set_editable(WebKitWebView* webView, gboolean flag)
1899 {
1900     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1901
1902     WebKitWebViewPrivate* priv = webView->priv;
1903
1904     Frame* frame = core(webView)->mainFrame();
1905     g_return_if_fail(frame);
1906
1907     // TODO: What happens when the frame is replaced?
1908     flag = flag != FALSE;
1909     if (flag == priv->editable)
1910         return;
1911
1912     priv->editable = flag;
1913
1914     if (flag) {
1915         frame->applyEditingStyleToBodyElement();
1916         // TODO: If the WebKitWebView is made editable and the selection is empty, set it to something.
1917         //if (!webkit_web_view_get_selected_dom_range(webView))
1918         //    mainFrame->setSelectionFromNone();
1919     } else
1920         frame->removeEditingStyleFromBodyElement();
1921 }
1922
1923 /**
1924  * webkit_web_view_get_copy_target_list:
1925  * @web_view: a #WebKitWebView
1926  *
1927  * This function returns the list of targets this #WebKitWebView can
1928  * provide for clipboard copying and as DND source. The targets in the list are
1929  * added with %info values from the #WebKitWebViewTargetInfo enum,
1930  * using gtk_target_list_add() and
1931  * gtk_target_list_add_text_targets().
1932  *
1933  * Return value: the #GtkTargetList
1934  **/
1935 GtkTargetList* webkit_web_view_get_copy_target_list(WebKitWebView* webView)
1936 {
1937     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1938
1939     WebKitWebViewPrivate* priv = webView->priv;
1940     return priv->copy_target_list;
1941 }
1942
1943 /**
1944  * webkit_web_view_get_paste_target_list:
1945  * @web_view: a #WebKitWebView
1946  *
1947  * This function returns the list of targets this #WebKitWebView can
1948  * provide for clipboard pasting and as DND destination. The targets in the list are
1949  * added with %info values from the #WebKitWebViewTargetInfo enum,
1950  * using gtk_target_list_add() and
1951  * gtk_target_list_add_text_targets().
1952  *
1953  * Return value: the #GtkTargetList
1954  **/
1955 GtkTargetList* webkit_web_view_get_paste_target_list(WebKitWebView* webView)
1956 {
1957     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
1958
1959     WebKitWebViewPrivate* priv = webView->priv;
1960     return priv->paste_target_list;
1961 }
1962
1963 /**
1964  * webkit_web_view_get_transparent:
1965  * @web_view: a #WebKitWebView
1966  *
1967  * Returns whether the #WebKitWebView has a transparent background.
1968  *
1969  * Return value: %FALSE when the #WebKitWebView draws a solid background
1970  * (the default), otherwise %TRUE.
1971  */
1972 gboolean webkit_web_view_get_transparent(WebKitWebView* webView)
1973 {
1974     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1975
1976     WebKitWebViewPrivate* priv = webView->priv;
1977     return priv->transparent;
1978 }
1979
1980 /**
1981  * webkit_web_view_set_transparent:
1982  * @web_view: a #WebKitWebView
1983  *
1984  * Sets whether the #WebKitWebView has a transparent background.
1985  *
1986  * Pass %FALSE to have the #WebKitWebView draw a solid background
1987  * (the default), otherwise %TRUE.
1988  */
1989 void webkit_web_view_set_transparent(WebKitWebView* webView, gboolean flag)
1990 {
1991     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1992
1993     WebKitWebViewPrivate* priv = webView->priv;
1994     priv->transparent = flag;
1995
1996     // TODO: This needs to be made persistent or it could become a problem when
1997     // the main frame is replaced.
1998     Frame* frame = core(webView)->mainFrame();
1999     g_return_if_fail(frame);
2000     frame->view()->setTransparent(flag);
2001 }
2002
2003 }