Home | History | Annotate | Download | only in webkit
      1 /*
      2  *  Copyright (C) 2007, 2008 Holger Hans Peter Freyther
      3  *  Copyright (C) 2007, 2008, 2009 Christian Dywan <christian (at) imendio.com>
      4  *  Copyright (C) 2007 Xan Lopez <xan (at) gnome.org>
      5  *  Copyright (C) 2007, 2008 Alp Toker <alp (at) atoker.com>
      6  *  Copyright (C) 2008 Jan Alonzo <jmalonzo (at) unpluggable.com>
      7  *  Copyright (C) 2008 Gustavo Noronha Silva <gns (at) gnome.org>
      8  *  Copyright (C) 2008 Nuanti Ltd.
      9  *  Copyright (C) 2008, 2009, 2010 Collabora Ltd.
     10  *  Copyright (C) 2009, 2010 Igalia S.L.
     11  *  Copyright (C) 2009 Movial Creative Technologies Inc.
     12  *  Copyright (C) 2009 Bobby Powers
     13  *  Copyright (C) 2010 Joone Hur <joone (at) kldp.org>
     14  *
     15  *  This library is free software; you can redistribute it and/or
     16  *  modify it under the terms of the GNU Lesser General Public
     17  *  License as published by the Free Software Foundation; either
     18  *  version 2 of the License, or (at your option) any later version.
     19  *
     20  *  This library is distributed in the hope that it will be useful,
     21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     23  *  Lesser General Public License for more details.
     24  *
     25  *  You should have received a copy of the GNU Lesser General Public
     26  *  License along with this library; if not, write to the Free Software
     27  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     28  */
     29 
     30 #include "config.h"
     31 #include "webkitwebview.h"
     32 
     33 #include "AXObjectCache.h"
     34 #include "AbstractDatabase.h"
     35 #include "BackForwardListImpl.h"
     36 #include "Chrome.h"
     37 #include "ChromeClientGtk.h"
     38 #include "ClipboardUtilitiesGtk.h"
     39 #include "ContextMenu.h"
     40 #include "ContextMenuClientGtk.h"
     41 #include "ContextMenuController.h"
     42 #include "Cursor.h"
     43 #include "Document.h"
     44 #include "DocumentLoader.h"
     45 #include "DragActions.h"
     46 #include "DragClientGtk.h"
     47 #include "DragController.h"
     48 #include "DragData.h"
     49 #include "Editor.h"
     50 #include "EditorClientGtk.h"
     51 #include "EventHandler.h"
     52 #include "FloatQuad.h"
     53 #include "FocusController.h"
     54 #include "FrameLoader.h"
     55 #include "FrameLoaderTypes.h"
     56 #include "FrameView.h"
     57 #include "GOwnPtrGtk.h"
     58 #include "GraphicsContext.h"
     59 #include "GtkVersioning.h"
     60 #include "HTMLNames.h"
     61 #include "HitTestRequest.h"
     62 #include "HitTestResult.h"
     63 #include "IconDatabase.h"
     64 #include "InspectorClientGtk.h"
     65 #include "InspectorController.h"
     66 #include "MemoryCache.h"
     67 #include "MouseEventWithHitTestResults.h"
     68 #include "NotImplemented.h"
     69 #include "PageCache.h"
     70 #include "Pasteboard.h"
     71 #include "PasteboardHelper.h"
     72 #include "PasteboardHelperGtk.h"
     73 #include "PlatformKeyboardEvent.h"
     74 #include "PlatformWheelEvent.h"
     75 #include "ProgressTracker.h"
     76 #include "RenderView.h"
     77 #include "ResourceHandle.h"
     78 #include "ScriptValue.h"
     79 #include "Scrollbar.h"
     80 #include "Settings.h"
     81 #include "webkit/WebKitDOMDocumentPrivate.h"
     82 #include "webkitdownload.h"
     83 #include "webkitdownloadprivate.h"
     84 #include "webkitenumtypes.h"
     85 #include "webkitgeolocationpolicydecision.h"
     86 #include "webkitglobalsprivate.h"
     87 #include "webkithittestresultprivate.h"
     88 #include "webkiticondatabase.h"
     89 #include "webkitmarshal.h"
     90 #include "webkitnetworkrequest.h"
     91 #include "webkitnetworkresponse.h"
     92 #include "webkitviewportattributes.h"
     93 #include "webkitviewportattributesprivate.h"
     94 #include "webkitwebbackforwardlist.h"
     95 #include "webkitwebframeprivate.h"
     96 #include "webkitwebhistoryitem.h"
     97 #include "webkitwebhistoryitemprivate.h"
     98 #include "webkitwebinspector.h"
     99 #include "webkitwebinspectorprivate.h"
    100 #include "webkitwebpolicydecision.h"
    101 #include "webkitwebresource.h"
    102 #include "webkitwebsettingsprivate.h"
    103 #include "webkitwebplugindatabaseprivate.h"
    104 #include "webkitwebwindowfeatures.h"
    105 #include "webkitwebviewprivate.h"
    106 #include <gdk/gdkkeysyms.h>
    107 #include <glib/gi18n-lib.h>
    108 #include <wtf/gobject/GOwnPtr.h>
    109 #include <wtf/text/CString.h>
    110 
    111 /**
    112  * SECTION:webkitwebview
    113  * @short_description: The central class of the WebKitGTK+ API
    114  * @see_also: #WebKitWebSettings, #WebKitWebFrame
    115  *
    116  * #WebKitWebView is the central class of the WebKitGTK+ API. It is a
    117  * #GtkWidget implementing the scrolling interface which means you can
    118  * embed in a #GtkScrolledWindow. It is responsible for managing the
    119  * drawing of the content, forwarding of events. You can load any URI
    120  * into the #WebKitWebView or any kind of data string. With #WebKitWebSettings
    121  * you can control various aspects of the rendering and loading of the content.
    122  * Each #WebKitWebView has exactly one #WebKitWebFrame as main frame. A
    123  * #WebKitWebFrame can have n children.
    124  *
    125  * <programlisting>
    126  * /<!-- -->* Create the widgets *<!-- -->/
    127  * GtkWidget *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    128  * GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    129  * GtkWidget *web_view = webkit_web_view_new ();
    130  *
    131  * /<!-- -->* Place the WebKitWebView in the GtkScrolledWindow *<!-- -->/
    132  * gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
    133  * gtk_container_add (GTK_CONTAINER (main_window), scrolled_window);
    134  *
    135  * /<!-- -->* Open a webpage *<!-- -->/
    136  * webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), "http://www.gnome.org");
    137  *
    138  * /<!-- -->* Show the result *<!-- -->/
    139  * gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600);
    140  * gtk_widget_show_all (main_window);
    141  * </programlisting>
    142  */
    143 
    144 static const double defaultDPI = 96.0;
    145 static IntPoint globalPointForClientPoint(GdkWindow* window, const IntPoint& clientPoint);
    146 
    147 using namespace WebKit;
    148 using namespace WebCore;
    149 
    150 enum {
    151     /* normal signals */
    152     NAVIGATION_REQUESTED,
    153     NEW_WINDOW_POLICY_DECISION_REQUESTED,
    154     NAVIGATION_POLICY_DECISION_REQUESTED,
    155     MIME_TYPE_POLICY_DECISION_REQUESTED,
    156     CREATE_WEB_VIEW,
    157     WEB_VIEW_READY,
    158     WINDOW_OBJECT_CLEARED,
    159     LOAD_STARTED,
    160     LOAD_COMMITTED,
    161     LOAD_PROGRESS_CHANGED,
    162     LOAD_ERROR,
    163     LOAD_FINISHED,
    164     TITLE_CHANGED,
    165     HOVERING_OVER_LINK,
    166     POPULATE_POPUP,
    167     STATUS_BAR_TEXT_CHANGED,
    168     ICON_LOADED,
    169     SELECTION_CHANGED,
    170     CONSOLE_MESSAGE,
    171     SCRIPT_ALERT,
    172     SCRIPT_CONFIRM,
    173     SCRIPT_PROMPT,
    174     SELECT_ALL,
    175     COPY_CLIPBOARD,
    176     PASTE_CLIPBOARD,
    177     CUT_CLIPBOARD,
    178     DOWNLOAD_REQUESTED,
    179     MOVE_CURSOR,
    180     PRINT_REQUESTED,
    181     PLUGIN_WIDGET,
    182     CLOSE_WEB_VIEW,
    183     UNDO,
    184     REDO,
    185     DATABASE_QUOTA_EXCEEDED,
    186     RESOURCE_REQUEST_STARTING,
    187     DOCUMENT_LOAD_FINISHED,
    188     GEOLOCATION_POLICY_DECISION_REQUESTED,
    189     GEOLOCATION_POLICY_DECISION_CANCELLED,
    190     ONLOAD_EVENT,
    191     FRAME_CREATED,
    192     SHOULD_BEGIN_EDITING,
    193     SHOULD_END_EDITING,
    194     SHOULD_INSERT_NODE,
    195     SHOULD_INSERT_TEXT,
    196     SHOULD_DELETE_RANGE,
    197     SHOULD_SHOW_DELETE_INTERFACE_FOR_ELEMENT,
    198     SHOULD_CHANGE_SELECTED_RANGE,
    199     SHOULD_APPLY_STYLE,
    200     EDITING_BEGAN,
    201     USER_CHANGED_CONTENTS,
    202     EDITING_ENDED,
    203     VIEWPORT_ATTRIBUTES_RECOMPUTE_REQUESTED,
    204     VIEWPORT_ATTRIBUTES_CHANGED,
    205 
    206     LAST_SIGNAL
    207 };
    208 
    209 enum {
    210     PROP_0,
    211 
    212     PROP_TITLE,
    213     PROP_URI,
    214     PROP_COPY_TARGET_LIST,
    215     PROP_PASTE_TARGET_LIST,
    216     PROP_EDITABLE,
    217     PROP_SETTINGS,
    218     PROP_WEB_INSPECTOR,
    219     PROP_VIEWPORT_ATTRIBUTES,
    220     PROP_WINDOW_FEATURES,
    221     PROP_TRANSPARENT,
    222     PROP_ZOOM_LEVEL,
    223     PROP_FULL_CONTENT_ZOOM,
    224     PROP_LOAD_STATUS,
    225     PROP_PROGRESS,
    226     PROP_ENCODING,
    227     PROP_CUSTOM_ENCODING,
    228     PROP_ICON_URI,
    229     PROP_IM_CONTEXT,
    230 #ifdef GTK_API_VERSION_2
    231     PROP_VIEW_MODE
    232 #else
    233     PROP_VIEW_MODE,
    234     PROP_HADJUSTMENT,
    235     PROP_VADJUSTMENT,
    236     PROP_HSCROLL_POLICY,
    237     PROP_VSCROLL_POLICY
    238 #endif
    239 };
    240 
    241 static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };
    242 
    243 #ifdef GTK_API_VERSION_2
    244 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
    245 #else
    246 G_DEFINE_TYPE_WITH_CODE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER,
    247                         G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, 0))
    248 #endif
    249 
    250 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView);
    251 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures);
    252 
    253 static GtkIMContext* webkit_web_view_get_im_context(WebKitWebView*);
    254 
    255 static void PopupMenuPositionFunc(GtkMenu* menu, gint *x, gint *y, gboolean *pushIn, gpointer userData)
    256 {
    257     WebKitWebView* view = WEBKIT_WEB_VIEW(userData);
    258     WebKitWebViewPrivate* priv = view->priv;
    259     GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(view));
    260     GtkRequisition menuSize;
    261 
    262 #ifdef GTK_API_VERSION_2
    263     gtk_widget_size_request(GTK_WIDGET(menu), &menuSize);
    264 #else
    265     gtk_widget_get_preferred_size(GTK_WIDGET(menu), &menuSize, NULL);
    266 #endif
    267 
    268     *x = priv->lastPopupXPosition;
    269     if ((*x + menuSize.width) >= gdk_screen_get_width(screen))
    270       *x -= menuSize.width;
    271 
    272     *y = priv->lastPopupYPosition;
    273     if ((*y + menuSize.height) >= gdk_screen_get_height(screen))
    274       *y -= menuSize.height;
    275 
    276     *pushIn = FALSE;
    277 }
    278 
    279 static Node* getFocusedNode(Frame* frame)
    280 {
    281     if (Document* doc = frame->document())
    282         return doc->focusedNode();
    283     return 0;
    284 }
    285 
    286 static void contextMenuItemActivated(GtkMenuItem* item, ContextMenuController* controller)
    287 {
    288     ContextMenuItem contextItem(item);
    289     controller->contextMenuItemSelected(&contextItem);
    290 }
    291 
    292 static void contextMenuConnectActivate(GtkMenuItem* item, ContextMenuController* controller)
    293 {
    294     if (GTK_IS_SEPARATOR_MENU_ITEM(item))
    295         return;
    296 
    297     if (GtkWidget* menu = gtk_menu_item_get_submenu(item)) {
    298         gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)contextMenuConnectActivate, controller);
    299         return;
    300     }
    301 
    302     g_signal_connect(item, "activate", G_CALLBACK(contextMenuItemActivated), controller);
    303 }
    304 
    305 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
    306 {
    307     Page* page = core(webView);
    308     page->contextMenuController()->clearContextMenu();
    309     Frame* focusedFrame;
    310     Frame* mainFrame = page->mainFrame();
    311     gboolean mousePressEventResult = FALSE;
    312 
    313     if (!mainFrame->view())
    314         return FALSE;
    315 
    316     mainFrame->view()->setCursor(pointerCursor());
    317     if (page->frameCount()) {
    318         HitTestRequest request(HitTestRequest::Active);
    319         IntPoint point = mainFrame->view()->windowToContents(event.pos());
    320         MouseEventWithHitTestResults mev = mainFrame->document()->prepareMouseEvent(request, point, event);
    321 
    322         Frame* targetFrame = EventHandler::subframeForHitTestResult(mev);
    323         if (!targetFrame)
    324             targetFrame = mainFrame;
    325 
    326         focusedFrame = page->focusController()->focusedOrMainFrame();
    327         if (targetFrame != focusedFrame) {
    328             page->focusController()->setFocusedFrame(targetFrame);
    329             focusedFrame = targetFrame;
    330         }
    331     } else
    332         focusedFrame = mainFrame;
    333 
    334     if (focusedFrame->view() && focusedFrame->eventHandler()->handleMousePressEvent(event))
    335         mousePressEventResult = TRUE;
    336 
    337 
    338     bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
    339     if (!handledEvent)
    340         return FALSE;
    341 
    342     // If coreMenu is NULL, this means WebCore decided to not create
    343     // the default context menu; this may happen when the page is
    344     // handling the right-click for reasons other than the context menu.
    345     ContextMenuController* controller = page->contextMenuController();
    346     ContextMenu* coreMenu = controller->contextMenu();
    347     if (!coreMenu)
    348         return mousePressEventResult;
    349 
    350     // If we reach here, it's because WebCore is going to show the
    351     // default context menu. We check our setting to figure out
    352     // whether we want it or not.
    353     WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
    354     gboolean enableDefaultContextMenu;
    355     g_object_get(settings, "enable-default-context-menu", &enableDefaultContextMenu, NULL);
    356 
    357     if (!enableDefaultContextMenu)
    358         return FALSE;
    359 
    360     GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
    361     if (!menu)
    362         return FALSE;
    363 
    364     // We connect the "activate" signal here rather than in ContextMenuGtk to avoid
    365     // a layering violation. ContextMenuGtk should not know about the ContextMenuController.
    366     gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)contextMenuConnectActivate, controller);
    367 
    368     g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
    369 
    370     // If the context menu is now empty, don't show it.
    371     GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
    372     if (!items)
    373         return FALSE;
    374 
    375     WebKitWebViewPrivate* priv = webView->priv;
    376     priv->currentMenu = menu;
    377     priv->lastPopupXPosition = event.globalX();
    378     priv->lastPopupYPosition = event.globalY();
    379 
    380     gtk_menu_popup(menu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
    381     return TRUE;
    382 }
    383 
    384 static const int gContextMenuMargin = 1;
    385 static IntPoint getLocationForKeyboardGeneratedContextMenu(Frame* frame)
    386 {
    387     SelectionController* selection = frame->selection();
    388     if (!selection->selection().isNonOrphanedCaretOrRange()
    389          || (selection->selection().isCaret() && !selection->selection().isContentEditable())) {
    390         if (Node* focusedNode = getFocusedNode(frame))
    391             return focusedNode->getRect().location();
    392 
    393         // There was no selection and no focused node, so just put the context
    394         // menu into the corner of the view, offset slightly.
    395         return IntPoint(gContextMenuMargin, gContextMenuMargin);
    396     }
    397 
    398     // selection->selection().firstRange can return 0 here, but if that was the case
    399     // selection->selection().isNonOrphanedCaretOrRange() would have returned false
    400     // above, so we do not have to check it.
    401     IntRect firstRect = frame->editor()->firstRectForRange(selection->selection().firstRange().get());
    402     return IntPoint(firstRect.x(), firstRect.maxY());
    403 }
    404 
    405 static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
    406 {
    407     Frame* frame = core(WEBKIT_WEB_VIEW(widget))->focusController()->focusedOrMainFrame();
    408     IntPoint location = getLocationForKeyboardGeneratedContextMenu(frame);
    409 
    410     FrameView* view = frame->view();
    411     if (!view)
    412         return FALSE;
    413 
    414     // Never let the context menu touch the very edge of the view.
    415     location = view->contentsToWindow(location);
    416     location.expandedTo(IntPoint(gContextMenuMargin, gContextMenuMargin));
    417     location.shrunkTo(IntPoint(view->width() - gContextMenuMargin, view->height() - gContextMenuMargin));
    418 
    419     IntPoint globalPoint(globalPointForClientPoint(gtk_widget_get_window(widget), location));
    420     PlatformMouseEvent event(location, globalPoint, RightButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
    421     return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
    422 }
    423 
    424 #ifndef GTK_API_VERSION_2
    425 static void setHorizontalAdjustment(WebKitWebView* webView, GtkAdjustment* adjustment)
    426 {
    427     if (!core(webView))
    428         return;
    429 
    430     webView->priv->horizontalAdjustment = adjustment;
    431     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
    432     if (!view)
    433         return;
    434     view->setHorizontalAdjustment(adjustment);
    435 }
    436 
    437 static void setVerticalAdjustment(WebKitWebView* webView, GtkAdjustment* adjustment)
    438 {
    439     if (!core(webView))
    440         return;
    441 
    442     webView->priv->verticalAdjustment = adjustment;
    443     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
    444     if (!view)
    445         return;
    446     view->setVerticalAdjustment(adjustment);
    447 }
    448 
    449 static GtkAdjustment* getHorizontalAdjustment(WebKitWebView* webView)
    450 {
    451     return webView->priv->horizontalAdjustment.get();
    452 }
    453 
    454 static GtkAdjustment* getVerticalAdjustment(WebKitWebView* webView)
    455 {
    456     return webView->priv->verticalAdjustment.get();
    457 }
    458 
    459 static void setHorizontalScrollPolicy(WebKitWebView* webView, GtkScrollablePolicy policy)
    460 {
    461     webView->priv->horizontalScrollingPolicy = policy;
    462     gtk_widget_queue_resize(GTK_WIDGET(webView));
    463 }
    464 
    465 static void setVerticalScrollPolicy(WebKitWebView* webView, GtkScrollablePolicy policy)
    466 {
    467     webView->priv->verticalScrollingPolicy = policy;
    468     gtk_widget_queue_resize(GTK_WIDGET(webView));
    469 }
    470 
    471 static GtkScrollablePolicy getHorizontalScrollPolicy(WebKitWebView* webView)
    472 {
    473     return webView->priv->horizontalScrollingPolicy;
    474 }
    475 
    476 static GtkScrollablePolicy getVerticalScrollPolicy(WebKitWebView* webView)
    477 {
    478     return webView->priv->verticalScrollingPolicy;
    479 }
    480 
    481 #endif
    482 
    483 static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
    484 {
    485     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
    486 
    487     switch(prop_id) {
    488     case PROP_TITLE:
    489         g_value_set_string(value, webkit_web_view_get_title(webView));
    490         break;
    491     case PROP_URI:
    492         g_value_set_string(value, webkit_web_view_get_uri(webView));
    493         break;
    494     case PROP_COPY_TARGET_LIST:
    495         g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView));
    496         break;
    497     case PROP_PASTE_TARGET_LIST:
    498         g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView));
    499         break;
    500     case PROP_EDITABLE:
    501         g_value_set_boolean(value, webkit_web_view_get_editable(webView));
    502         break;
    503     case PROP_SETTINGS:
    504         g_value_set_object(value, webkit_web_view_get_settings(webView));
    505         break;
    506     case PROP_WEB_INSPECTOR:
    507         g_value_set_object(value, webkit_web_view_get_inspector(webView));
    508         break;
    509     case PROP_VIEWPORT_ATTRIBUTES:
    510         g_value_set_object(value, webkit_web_view_get_viewport_attributes(webView));
    511         break;
    512     case PROP_WINDOW_FEATURES:
    513         g_value_set_object(value, webkit_web_view_get_window_features(webView));
    514         break;
    515     case PROP_TRANSPARENT:
    516         g_value_set_boolean(value, webkit_web_view_get_transparent(webView));
    517         break;
    518     case PROP_ZOOM_LEVEL:
    519         g_value_set_float(value, webkit_web_view_get_zoom_level(webView));
    520         break;
    521     case PROP_FULL_CONTENT_ZOOM:
    522         g_value_set_boolean(value, webkit_web_view_get_full_content_zoom(webView));
    523         break;
    524     case PROP_ENCODING:
    525         g_value_set_string(value, webkit_web_view_get_encoding(webView));
    526         break;
    527     case PROP_CUSTOM_ENCODING:
    528         g_value_set_string(value, webkit_web_view_get_custom_encoding(webView));
    529         break;
    530     case PROP_LOAD_STATUS:
    531         g_value_set_enum(value, webkit_web_view_get_load_status(webView));
    532         break;
    533     case PROP_PROGRESS:
    534         g_value_set_double(value, webkit_web_view_get_progress(webView));
    535         break;
    536     case PROP_ICON_URI:
    537         g_value_set_string(value, webkit_web_view_get_icon_uri(webView));
    538         break;
    539     case PROP_IM_CONTEXT:
    540         g_value_set_object(value, webkit_web_view_get_im_context(webView));
    541         break;
    542     case PROP_VIEW_MODE:
    543         g_value_set_enum(value, webkit_web_view_get_view_mode(webView));
    544         break;
    545 #ifndef GTK_API_VERSION_2
    546     case PROP_HADJUSTMENT:
    547         g_value_set_object(value, getHorizontalAdjustment(webView));
    548         break;
    549     case PROP_VADJUSTMENT:
    550         g_value_set_object(value, getVerticalAdjustment(webView));
    551         break;
    552     case PROP_HSCROLL_POLICY:
    553         g_value_set_enum(value, getHorizontalScrollPolicy(webView));
    554         break;
    555     case PROP_VSCROLL_POLICY:
    556         g_value_set_enum(value, getVerticalScrollPolicy(webView));
    557         break;
    558 #endif
    559     default:
    560         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    561     }
    562 }
    563 
    564 static void webkit_web_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec)
    565 {
    566     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
    567 
    568     switch(prop_id) {
    569     case PROP_EDITABLE:
    570         webkit_web_view_set_editable(webView, g_value_get_boolean(value));
    571         break;
    572     case PROP_SETTINGS:
    573         webkit_web_view_set_settings(webView, WEBKIT_WEB_SETTINGS(g_value_get_object(value)));
    574         break;
    575     case PROP_WINDOW_FEATURES:
    576         webkit_web_view_set_window_features(webView, WEBKIT_WEB_WINDOW_FEATURES(g_value_get_object(value)));
    577         break;
    578     case PROP_TRANSPARENT:
    579         webkit_web_view_set_transparent(webView, g_value_get_boolean(value));
    580         break;
    581     case PROP_ZOOM_LEVEL:
    582         webkit_web_view_set_zoom_level(webView, g_value_get_float(value));
    583         break;
    584     case PROP_FULL_CONTENT_ZOOM:
    585         webkit_web_view_set_full_content_zoom(webView, g_value_get_boolean(value));
    586         break;
    587     case PROP_CUSTOM_ENCODING:
    588         webkit_web_view_set_custom_encoding(webView, g_value_get_string(value));
    589         break;
    590     case PROP_VIEW_MODE:
    591         webkit_web_view_set_view_mode(webView, static_cast<WebKitWebViewViewMode>(g_value_get_enum(value)));
    592         break;
    593 #ifndef GTK_API_VERSION_2
    594     case PROP_HADJUSTMENT:
    595         setHorizontalAdjustment(webView, static_cast<GtkAdjustment*>(g_value_get_object(value)));
    596         break;
    597     case PROP_VADJUSTMENT:
    598         setVerticalAdjustment(webView, static_cast<GtkAdjustment*>(g_value_get_object(value)));
    599         break;
    600     case PROP_HSCROLL_POLICY:
    601         setHorizontalScrollPolicy(webView, static_cast<GtkScrollablePolicy>(g_value_get_enum(value)));
    602         break;
    603     case PROP_VSCROLL_POLICY:
    604         setVerticalScrollPolicy(webView, static_cast<GtkScrollablePolicy>(g_value_get_enum(value)));
    605         break;
    606 #endif
    607     default:
    608         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    609     }
    610 }
    611 
    612 static bool shouldCoalesce(const IntRect& rect, const Vector<IntRect>& rects)
    613 {
    614     const unsigned int cRectThreshold = 10;
    615     const float cWastedSpaceThreshold = 0.75f;
    616     bool useUnionedRect = (rects.size() <= 1) || (rects.size() > cRectThreshold);
    617     if (useUnionedRect)
    618         return true;
    619     // Attempt to guess whether or not we should use the unioned rect or the individual rects.
    620     // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
    621     // is too large, then we will do individual rect painting instead.
    622     float unionPixels = (rect.width() * rect.height());
    623     float singlePixels = 0;
    624     for (size_t i = 0; i < rects.size(); ++i)
    625         singlePixels += rects[i].width() * rects[i].height();
    626     float wastedSpace = 1 - (singlePixels / unionPixels);
    627     if (wastedSpace <= cWastedSpaceThreshold)
    628         useUnionedRect = true;
    629     return useUnionedRect;
    630 }
    631 
    632 static void paintWebView(Frame* frame, gboolean transparent, GraphicsContext& context, const IntRect& clipRect, const Vector<IntRect>& rects)
    633 {
    634     bool coalesce = true;
    635 
    636     if (rects.size() > 0)
    637         coalesce = shouldCoalesce(clipRect, rects);
    638 
    639     if (coalesce) {
    640         context.clip(clipRect);
    641         if (transparent)
    642             context.clearRect(clipRect);
    643         frame->view()->paint(&context, clipRect);
    644     } else {
    645         for (size_t i = 0; i < rects.size(); i++) {
    646             IntRect rect = rects[i];
    647             context.save();
    648             context.clip(rect);
    649             if (transparent)
    650                 context.clearRect(rect);
    651             frame->view()->paint(&context, rect);
    652             context.restore();
    653         }
    654     }
    655 
    656     context.save();
    657     context.clip(clipRect);
    658     frame->page()->inspectorController()->drawNodeHighlight(context);
    659     context.restore();
    660 }
    661 #ifdef GTK_API_VERSION_2
    662 static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
    663 {
    664     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    665     WebKitWebViewPrivate* priv = webView->priv;
    666 
    667     Frame* frame = core(webView)->mainFrame();
    668     if (frame->contentRenderer() && frame->view()) {
    669         frame->view()->updateLayoutAndStyleIfNeededRecursive();
    670 
    671         RefPtr<cairo_t> cr = adoptRef(gdk_cairo_create(event->window));
    672         GraphicsContext gc(cr.get());
    673         gc.setGdkExposeEvent(event);
    674 
    675         int rectCount;
    676         GOwnPtr<GdkRectangle> rects;
    677         gdk_region_get_rectangles(event->region, &rects.outPtr(), &rectCount);
    678         Vector<IntRect> paintRects;
    679         for (int i = 0; i < rectCount; i++)
    680             paintRects.append(IntRect(rects.get()[i]));
    681 
    682         paintWebView(frame, priv->transparent, gc, static_cast<IntRect>(event->area), paintRects);
    683     }
    684 
    685     return FALSE;
    686 }
    687 #else
    688 static gboolean webkit_web_view_draw(GtkWidget* widget, cairo_t* cr)
    689 {
    690     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    691     WebKitWebViewPrivate* priv = webView->priv;
    692     GdkRectangle clipRect;
    693 
    694     if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
    695         return FALSE;
    696 
    697     Frame* frame = core(webView)->mainFrame();
    698     if (frame->contentRenderer() && frame->view()) {
    699         GraphicsContext gc(cr);
    700         IntRect rect = clipRect;
    701         cairo_rectangle_list_t* rectList = cairo_copy_clip_rectangle_list(cr);
    702 
    703         frame->view()->updateLayoutAndStyleIfNeededRecursive();
    704 
    705         Vector<IntRect> rects;
    706         if (!rectList->status && rectList->num_rectangles > 0) {
    707             for (int i = 0; i < rectList->num_rectangles; i++)
    708                 rects.append(enclosingIntRect(FloatRect(rectList->rectangles[i])));
    709         }
    710         paintWebView(frame, priv->transparent, gc, rect, rects);
    711 
    712         cairo_rectangle_list_destroy(rectList);
    713     }
    714 
    715     return FALSE;
    716 }
    717 #endif // GTK_API_VERSION_2
    718 
    719 static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* event)
    720 {
    721     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    722 
    723     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
    724     PlatformKeyboardEvent keyboardEvent(event);
    725 
    726     if (!frame->view())
    727         return FALSE;
    728 
    729     if (frame->eventHandler()->keyEvent(keyboardEvent))
    730         return TRUE;
    731 
    732     /* Chain up to our parent class for binding activation */
    733     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_press_event(widget, event);
    734 }
    735 
    736 static gboolean webkit_web_view_key_release_event(GtkWidget* widget, GdkEventKey* event)
    737 {
    738     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    739 
    740     // GTK+ IM contexts often require us to filter key release events, which
    741     // WebCore does not do by default, so we filter the event here. We only block
    742     // the event if we don't have a pending composition, because that means we
    743     // are using a context like 'simple' which marks every keystroke as filtered.
    744     WebKit::EditorClient* client = static_cast<WebKit::EditorClient*>(core(webView)->editorClient());
    745     if (gtk_im_context_filter_keypress(webView->priv->imContext.get(), event) && !client->hasPendingComposition())
    746         return TRUE;
    747 
    748     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
    749     if (!frame->view())
    750         return FALSE;
    751 
    752     PlatformKeyboardEvent keyboardEvent(event);
    753     if (frame->eventHandler()->keyEvent(keyboardEvent))
    754         return TRUE;
    755 
    756     /* Chain up to our parent class for binding activation */
    757     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->key_release_event(widget, event);
    758 }
    759 
    760 static guint32 getEventTime(GdkEvent* event)
    761 {
    762     guint32 time = gdk_event_get_time(event);
    763     if (time)
    764         return time;
    765 
    766     // Real events always have a non-zero time, but events synthesized
    767     // by the DRT do not and we must calculate a time manually. This time
    768     // is not calculated in the DRT, because GTK+ does not work well with
    769     // anything other than GDK_CURRENT_TIME on synthesized events.
    770     GTimeVal timeValue;
    771     g_get_current_time(&timeValue);
    772     return (timeValue.tv_sec * 1000) + (timeValue.tv_usec / 1000);
    773 }
    774 
    775 static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventButton* event)
    776 {
    777     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    778     WebKitWebViewPrivate* priv = webView->priv;
    779 
    780     // FIXME: need to keep track of subframe focus for key events
    781     gtk_widget_grab_focus(widget);
    782 
    783     // For double and triple clicks GDK sends both a normal button press event
    784     // and a specific type (like GDK_2BUTTON_PRESS). If we detect a special press
    785     // coming up, ignore this event as it certainly generated the double or triple
    786     // click. The consequence of not eating this event is two DOM button press events
    787     // are generated.
    788     GOwnPtr<GdkEvent> nextEvent(gdk_event_peek());
    789     if (nextEvent && (nextEvent->any.type == GDK_2BUTTON_PRESS || nextEvent->any.type == GDK_3BUTTON_PRESS))
    790         return TRUE;
    791 
    792     gint doubleClickDistance = 250;
    793     gint doubleClickTime = 5;
    794     GtkSettings* settings = gtk_settings_get_for_screen(gtk_widget_get_screen(widget));
    795     g_object_get(settings,
    796         "gtk-double-click-distance", &doubleClickDistance,
    797         "gtk-double-click-time", &doubleClickTime, NULL);
    798 
    799     // GTK+ only counts up to triple clicks, but WebCore wants to know about
    800     // quadruple clicks, quintuple clicks, ad infinitum. Here, we replicate the
    801     // GDK logic for counting clicks.
    802     guint32 eventTime = getEventTime(reinterpret_cast<GdkEvent*>(event));
    803     if ((event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
    804         || ((abs(event->x - priv->previousClickPoint.x()) < doubleClickDistance)
    805             && (abs(event->y - priv->previousClickPoint.y()) < doubleClickDistance)
    806             && (eventTime - priv->previousClickTime < static_cast<guint>(doubleClickTime))
    807             && (event->button == priv->previousClickButton)))
    808         priv->currentClickCount++;
    809     else
    810         priv->currentClickCount = 1;
    811 
    812     PlatformMouseEvent platformEvent(event);
    813     platformEvent.setClickCount(priv->currentClickCount);
    814     priv->previousClickPoint = platformEvent.pos();
    815     priv->previousClickButton = event->button;
    816     priv->previousClickTime = eventTime;
    817 
    818     if (event->button == 3)
    819         return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
    820 
    821     Frame* frame = core(webView)->mainFrame();
    822     if (!frame->view())
    823         return FALSE;
    824 
    825     gboolean result = frame->eventHandler()->handleMousePressEvent(platformEvent);
    826     // Handle the IM context when a mouse press fires
    827     static_cast<WebKit::EditorClient*>(core(webView)->editorClient())->handleInputMethodMousePress();
    828 
    829 #if PLATFORM(X11)
    830     /* Copy selection to the X11 selection clipboard */
    831     if (event->button == 2) {
    832         bool primary = webView->priv->usePrimaryForPaste;
    833         webView->priv->usePrimaryForPaste = true;
    834 
    835         Editor* editor = webView->priv->corePage->focusController()->focusedOrMainFrame()->editor();
    836         result = result || editor->canPaste() || editor->canDHTMLPaste();
    837         editor->paste();
    838 
    839         webView->priv->usePrimaryForPaste = primary;
    840     }
    841 #endif
    842 
    843     return result;
    844 }
    845 
    846 static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEventButton* event)
    847 {
    848     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    849 
    850     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
    851 
    852     if (focusedFrame && focusedFrame->editor()->canEdit()) {
    853 #ifdef MAEMO_CHANGES
    854         WebKitWebViewPrivate* priv = webView->priv;
    855         hildon_gtk_im_context_filter_event(priv->imContext.get(), (GdkEvent*)event);
    856 #endif
    857     }
    858 
    859     Frame* mainFrame = core(webView)->mainFrame();
    860     if (mainFrame->view())
    861         mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
    862 
    863     /* We always return FALSE here because WebKit can, for the same click, decide
    864      * to not handle press-event but handle release-event, which can totally confuse
    865      * some GTK+ containers when there are no other events in between. This way we
    866      * guarantee that this case never happens, and that if press-event goes through
    867      * release-event also goes through.
    868      */
    869 
    870     return FALSE;
    871 }
    872 
    873 static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event)
    874 {
    875     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    876 
    877     Frame* frame = core(webView)->mainFrame();
    878     if (!frame->view())
    879         return FALSE;
    880 
    881     return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
    882 }
    883 
    884 static gboolean webkit_web_view_scroll_event(GtkWidget* widget, GdkEventScroll* event)
    885 {
    886     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    887 
    888     Frame* frame = core(webView)->mainFrame();
    889     if (!frame->view())
    890         return FALSE;
    891 
    892     PlatformWheelEvent wheelEvent(event);
    893     return frame->eventHandler()->handleWheelEvent(wheelEvent);
    894 }
    895 
    896 #ifdef GTK_API_VERSION_2
    897 static void webkit_web_view_size_request(GtkWidget* widget, GtkRequisition* requisition)
    898 {
    899     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
    900     Frame* coreFrame = core(webkit_web_view_get_main_frame(web_view));
    901     if (!coreFrame)
    902         return;
    903 
    904     FrameView* view = coreFrame->view();
    905     if (!view)
    906         return;
    907 
    908     requisition->width = view->contentsWidth();
    909     requisition->height = view->contentsHeight();
    910 }
    911 #else
    912 static void webkit_web_view_get_preferred_width(GtkWidget* widget, gint* minimum, gint* natural)
    913 {
    914     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
    915     Frame* coreFrame = core(webkit_web_view_get_main_frame(web_view));
    916     if (!coreFrame)
    917         return;
    918 
    919     FrameView* view = coreFrame->view();
    920     if (!view)
    921         return;
    922 
    923     *minimum = *natural = view->contentsWidth();
    924 }
    925 
    926 static void webkit_web_view_get_preferred_height(GtkWidget* widget, gint* minimum, gint* natural)
    927 {
    928     WebKitWebView* web_view = WEBKIT_WEB_VIEW(widget);
    929     Frame* coreFrame = core(webkit_web_view_get_main_frame(web_view));
    930     if (!coreFrame)
    931         return;
    932 
    933     FrameView* view = coreFrame->view();
    934     if (!view)
    935         return;
    936 
    937     *minimum = *natural = view->contentsHeight();
    938 }
    939 #endif
    940 
    941 static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
    942 {
    943     GTK_WIDGET_CLASS(webkit_web_view_parent_class)->size_allocate(widget,allocation);
    944 
    945     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    946 
    947     Frame* frame = core(webView)->mainFrame();
    948     if (!frame->view())
    949         return;
    950 
    951     frame->view()->resize(allocation->width, allocation->height);
    952 }
    953 
    954 static void webkit_web_view_grab_focus(GtkWidget* widget)
    955 {
    956 
    957     if (gtk_widget_is_sensitive(widget)) {
    958         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    959         FocusController* focusController = core(webView)->focusController();
    960 
    961         focusController->setActive(true);
    962 
    963         if (focusController->focusedFrame())
    964             focusController->setFocused(true);
    965         else
    966             focusController->setFocusedFrame(core(webView)->mainFrame());
    967     }
    968 
    969     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->grab_focus(widget);
    970 }
    971 
    972 static gboolean webkit_web_view_focus_in_event(GtkWidget* widget, GdkEventFocus* event)
    973 {
    974     // TODO: Improve focus handling as suggested in
    975     // http://bugs.webkit.org/show_bug.cgi?id=16910
    976     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
    977     if (gtk_widget_is_toplevel(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {
    978         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    979         FocusController* focusController = core(webView)->focusController();
    980 
    981         focusController->setActive(true);
    982 
    983         if (focusController->focusedFrame())
    984             focusController->setFocused(true);
    985         else
    986             focusController->setFocusedFrame(core(webView)->mainFrame());
    987 
    988         if (focusController->focusedFrame()->editor()->canEdit())
    989             gtk_im_context_focus_in(webView->priv->imContext.get());
    990     }
    991     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_in_event(widget, event);
    992 }
    993 
    994 static gboolean webkit_web_view_focus_out_event(GtkWidget* widget, GdkEventFocus* event)
    995 {
    996     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    997 
    998     // We may hit this code while destroying the widget, and we might
    999     // no longer have a page, then.
   1000     Page* page = core(webView);
   1001     if (page) {
   1002         page->focusController()->setActive(false);
   1003         page->focusController()->setFocused(false);
   1004     }
   1005 
   1006     if (webView->priv->imContext)
   1007         gtk_im_context_focus_out(webView->priv->imContext.get());
   1008 
   1009     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->focus_out_event(widget, event);
   1010 }
   1011 
   1012 static void webkit_web_view_realize(GtkWidget* widget)
   1013 {
   1014     gtk_widget_set_realized(widget, TRUE);
   1015 
   1016     GtkAllocation allocation;
   1017 #if GTK_CHECK_VERSION(2, 18, 0)
   1018     gtk_widget_get_allocation(widget, &allocation);
   1019 #else
   1020     allocation = widget->allocation;
   1021 #endif
   1022 
   1023     GdkWindowAttr attributes;
   1024     attributes.window_type = GDK_WINDOW_CHILD;
   1025     attributes.x = allocation.x;
   1026     attributes.y = allocation.y;
   1027     attributes.width = allocation.width;
   1028     attributes.height = allocation.height;
   1029     attributes.wclass = GDK_INPUT_OUTPUT;
   1030     attributes.visual = gtk_widget_get_visual(widget);
   1031 #ifdef GTK_API_VERSION_2
   1032     attributes.colormap = gtk_widget_get_colormap(widget);
   1033 #endif
   1034     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
   1035                             | GDK_EXPOSURE_MASK
   1036                             | GDK_BUTTON_PRESS_MASK
   1037                             | GDK_BUTTON_RELEASE_MASK
   1038                             | GDK_POINTER_MOTION_MASK
   1039                             | GDK_KEY_PRESS_MASK
   1040                             | GDK_KEY_RELEASE_MASK
   1041                             | GDK_BUTTON_MOTION_MASK
   1042                             | GDK_BUTTON1_MOTION_MASK
   1043                             | GDK_BUTTON2_MOTION_MASK
   1044                             | GDK_BUTTON3_MOTION_MASK;
   1045 
   1046     gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
   1047 #ifdef GTK_API_VERSION_2
   1048     attributes_mask |= GDK_WA_COLORMAP;
   1049 #endif
   1050     GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask);
   1051     gtk_widget_set_window(widget, window);
   1052     gdk_window_set_user_data(window, widget);
   1053 
   1054 #ifdef GTK_API_VERSION_2
   1055 #if GTK_CHECK_VERSION(2, 20, 0)
   1056     gtk_widget_style_attach(widget);
   1057 #else
   1058     widget->style = gtk_style_attach(gtk_widget_get_style(widget), window);
   1059 #endif
   1060     gtk_style_set_background(gtk_widget_get_style(widget), window, GTK_STATE_NORMAL);
   1061 #else
   1062     gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
   1063 #endif
   1064 
   1065     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1066     WebKitWebViewPrivate* priv = webView->priv;
   1067     gtk_im_context_set_client_window(priv->imContext.get(), window);
   1068 }
   1069 
   1070 #ifdef GTK_API_VERSION_2
   1071 static void webkit_web_view_set_scroll_adjustments(WebKitWebView* webView, GtkAdjustment* hadj, GtkAdjustment* vadj)
   1072 {
   1073     if (!core(webView))
   1074         return;
   1075 
   1076     webView->priv->horizontalAdjustment = hadj;
   1077     webView->priv->verticalAdjustment = vadj;
   1078 
   1079     FrameView* view = core(webkit_web_view_get_main_frame(webView))->view();
   1080     if (!view)
   1081         return;
   1082     view->setGtkAdjustments(hadj, vadj);
   1083 }
   1084 #endif
   1085 
   1086 static void webkit_web_view_container_add(GtkContainer* container, GtkWidget* widget)
   1087 {
   1088     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
   1089     WebKitWebViewPrivate* priv = webView->priv;
   1090 
   1091     priv->children.add(widget);
   1092     gtk_widget_set_parent(widget, GTK_WIDGET(container));
   1093 }
   1094 
   1095 static void webkit_web_view_container_remove(GtkContainer* container, GtkWidget* widget)
   1096 {
   1097     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
   1098     WebKitWebViewPrivate* priv = webView->priv;
   1099 
   1100     if (priv->children.contains(widget)) {
   1101         gtk_widget_unparent(widget);
   1102         priv->children.remove(widget);
   1103     }
   1104 }
   1105 
   1106 static void webkit_web_view_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
   1107 {
   1108     WebKitWebView* webView = WEBKIT_WEB_VIEW(container);
   1109     WebKitWebViewPrivate* priv = webView->priv;
   1110 
   1111     HashSet<GtkWidget*> children = priv->children;
   1112     HashSet<GtkWidget*>::const_iterator end = children.end();
   1113     for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
   1114         (*callback)(*current, callbackData);
   1115 }
   1116 
   1117 static WebKitWebView* webkit_web_view_real_create_web_view(WebKitWebView*, WebKitWebFrame*)
   1118 {
   1119     return 0;
   1120 }
   1121 
   1122 static gboolean webkit_web_view_real_web_view_ready(WebKitWebView*)
   1123 {
   1124     return FALSE;
   1125 }
   1126 
   1127 static gboolean webkit_web_view_real_close_web_view(WebKitWebView*)
   1128 {
   1129     return FALSE;
   1130 }
   1131 
   1132 static WebKitNavigationResponse webkit_web_view_real_navigation_requested(WebKitWebView*, WebKitWebFrame*, WebKitNetworkRequest*)
   1133 {
   1134     return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
   1135 }
   1136 
   1137 static void webkit_web_view_real_window_object_cleared(WebKitWebView*, WebKitWebFrame*, JSGlobalContextRef context, JSObjectRef window_object)
   1138 {
   1139     notImplemented();
   1140 }
   1141 
   1142 static gchar* webkit_web_view_real_choose_file(WebKitWebView*, WebKitWebFrame*, const gchar* old_name)
   1143 {
   1144     notImplemented();
   1145     return g_strdup(old_name);
   1146 }
   1147 
   1148 typedef enum {
   1149     WEBKIT_SCRIPT_DIALOG_ALERT,
   1150     WEBKIT_SCRIPT_DIALOG_CONFIRM,
   1151     WEBKIT_SCRIPT_DIALOG_PROMPT
   1152  } WebKitScriptDialogType;
   1153 
   1154 static gboolean webkit_web_view_script_dialog(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
   1155 {
   1156     GtkMessageType messageType;
   1157     GtkButtonsType buttons;
   1158     gint defaultResponse;
   1159     GtkWidget* window;
   1160     GtkWidget* dialog;
   1161     GtkWidget* entry = 0;
   1162     gboolean didConfirm = FALSE;
   1163 
   1164     switch (type) {
   1165     case WEBKIT_SCRIPT_DIALOG_ALERT:
   1166         messageType = GTK_MESSAGE_WARNING;
   1167         buttons = GTK_BUTTONS_CLOSE;
   1168         defaultResponse = GTK_RESPONSE_CLOSE;
   1169         break;
   1170     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
   1171         messageType = GTK_MESSAGE_QUESTION;
   1172         buttons = GTK_BUTTONS_OK_CANCEL;
   1173         defaultResponse = GTK_RESPONSE_OK;
   1174         break;
   1175     case WEBKIT_SCRIPT_DIALOG_PROMPT:
   1176         messageType = GTK_MESSAGE_QUESTION;
   1177         buttons = GTK_BUTTONS_OK_CANCEL;
   1178         defaultResponse = GTK_RESPONSE_OK;
   1179         break;
   1180     default:
   1181         g_warning("Unknown value for WebKitScriptDialogType.");
   1182         return FALSE;
   1183     }
   1184 
   1185     window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
   1186     dialog = gtk_message_dialog_new(gtk_widget_is_toplevel(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
   1187     gchar* title = g_strconcat("JavaScript - ", webkit_web_frame_get_uri(frame), NULL);
   1188     gtk_window_set_title(GTK_WINDOW(dialog), title);
   1189     g_free(title);
   1190 
   1191     if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
   1192         entry = gtk_entry_new();
   1193         gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
   1194         gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
   1195         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
   1196         gtk_widget_show(entry);
   1197     }
   1198 
   1199     gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
   1200     gint response = gtk_dialog_run(GTK_DIALOG(dialog));
   1201 
   1202     switch (response) {
   1203     case GTK_RESPONSE_OK:
   1204         didConfirm = TRUE;
   1205         if (entry)
   1206             *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
   1207         break;
   1208     case GTK_RESPONSE_CANCEL:
   1209         didConfirm = FALSE;
   1210         break;
   1211 
   1212     }
   1213     gtk_widget_destroy(GTK_WIDGET(dialog));
   1214     return didConfirm;
   1215 }
   1216 
   1217 static gboolean webkit_web_view_real_script_alert(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message)
   1218 {
   1219     webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
   1220     return TRUE;
   1221 }
   1222 
   1223 static gboolean webkit_web_view_real_script_confirm(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm)
   1224 {
   1225     *didConfirm = webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
   1226     return TRUE;
   1227 }
   1228 
   1229 static gboolean webkit_web_view_real_script_prompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
   1230 {
   1231     if (!webkit_web_view_script_dialog(webView, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
   1232         *value = NULL;
   1233     return TRUE;
   1234 }
   1235 
   1236 static gboolean webkit_web_view_real_console_message(WebKitWebView* webView, const gchar* message, unsigned int line, const gchar* sourceId)
   1237 {
   1238     g_message("console message: %s @%d: %s\n", sourceId, line, message);
   1239     return TRUE;
   1240 }
   1241 
   1242 static void webkit_web_view_real_select_all(WebKitWebView* webView)
   1243 {
   1244     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1245     frame->editor()->command("SelectAll").execute();
   1246 }
   1247 
   1248 static void webkit_web_view_real_cut_clipboard(WebKitWebView* webView)
   1249 {
   1250     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1251     frame->editor()->command("Cut").execute();
   1252 }
   1253 
   1254 static void webkit_web_view_real_copy_clipboard(WebKitWebView* webView)
   1255 {
   1256     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1257     frame->editor()->command("Copy").execute();
   1258 }
   1259 
   1260 static void webkit_web_view_real_undo(WebKitWebView* webView)
   1261 {
   1262     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1263     frame->editor()->command("Undo").execute();
   1264 }
   1265 
   1266 static void webkit_web_view_real_redo(WebKitWebView* webView)
   1267 {
   1268     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1269     frame->editor()->command("Redo").execute();
   1270 }
   1271 
   1272 static gboolean webkit_web_view_real_move_cursor (WebKitWebView* webView, GtkMovementStep step, gint count)
   1273 {
   1274     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW (webView), FALSE);
   1275     g_return_val_if_fail(step == GTK_MOVEMENT_VISUAL_POSITIONS ||
   1276                          step == GTK_MOVEMENT_DISPLAY_LINES ||
   1277                          step == GTK_MOVEMENT_PAGES ||
   1278                          step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
   1279     g_return_val_if_fail(count == 1 || count == -1, FALSE);
   1280 
   1281     ScrollDirection direction;
   1282     ScrollGranularity granularity;
   1283 
   1284     switch (step) {
   1285     case GTK_MOVEMENT_DISPLAY_LINES:
   1286         granularity = ScrollByLine;
   1287         if (count == 1)
   1288             direction = ScrollDown;
   1289         else
   1290             direction = ScrollUp;
   1291         break;
   1292     case GTK_MOVEMENT_VISUAL_POSITIONS:
   1293         granularity = ScrollByLine;
   1294         if (count == 1)
   1295             direction = ScrollRight;
   1296         else
   1297             direction = ScrollLeft;
   1298         break;
   1299     case GTK_MOVEMENT_PAGES:
   1300         granularity = ScrollByPage;
   1301         if (count == 1)
   1302             direction = ScrollDown;
   1303         else
   1304             direction = ScrollUp;
   1305         break;
   1306     case GTK_MOVEMENT_BUFFER_ENDS:
   1307         granularity = ScrollByDocument;
   1308         if (count == 1)
   1309             direction = ScrollDown;
   1310         else
   1311             direction = ScrollUp;
   1312         break;
   1313     default:
   1314         g_assert_not_reached();
   1315         return false;
   1316     }
   1317 
   1318     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1319     if (!frame->eventHandler()->scrollOverflow(direction, granularity))
   1320         frame->view()->scroll(direction, granularity);
   1321 
   1322     return true;
   1323 }
   1324 
   1325 static void webkit_web_view_real_paste_clipboard(WebKitWebView* webView)
   1326 {
   1327     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1328     frame->editor()->command("Paste").execute();
   1329 }
   1330 
   1331 static gboolean webkit_web_view_real_should_allow_editing_action(WebKitWebView*)
   1332 {
   1333     return TRUE;
   1334 }
   1335 
   1336 static void webkit_web_view_dispose(GObject* object)
   1337 {
   1338     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
   1339     WebKitWebViewPrivate* priv = webView->priv;
   1340 
   1341     priv->disposing = TRUE;
   1342 
   1343     // These smart pointers are cleared manually, because some cleanup operations are
   1344     // very sensitive to their value. We may crash if these are done in the wrong order.
   1345     priv->horizontalAdjustment.clear();
   1346     priv->verticalAdjustment.clear();
   1347     priv->backForwardList.clear();
   1348 
   1349     if (priv->corePage) {
   1350         webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object));
   1351         core(priv->mainFrame)->loader()->detachFromParent();
   1352         delete priv->corePage;
   1353         priv->corePage = 0;
   1354     }
   1355 
   1356     if (priv->webSettings) {
   1357         g_signal_handlers_disconnect_by_func(priv->webSettings.get(), (gpointer)webkit_web_view_settings_notify, webView);
   1358         priv->webSettings.clear();
   1359     }
   1360 
   1361     if (priv->currentMenu) {
   1362         gtk_widget_destroy(GTK_WIDGET(priv->currentMenu));
   1363         priv->currentMenu = 0;
   1364     }
   1365 
   1366     priv->webInspector.clear();
   1367     priv->viewportAttributes.clear();
   1368     priv->webWindowFeatures.clear();
   1369     priv->mainResource.clear();
   1370     priv->subResources.clear();
   1371 
   1372     HashMap<GdkDragContext*, DroppingContext*>::iterator endDroppingContexts = priv->droppingContexts.end();
   1373     for (HashMap<GdkDragContext*, DroppingContext*>::iterator iter = priv->droppingContexts.begin(); iter != endDroppingContexts; ++iter)
   1374         delete (iter->second);
   1375     priv->droppingContexts.clear();
   1376 
   1377     G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object);
   1378 }
   1379 
   1380 static void webkit_web_view_finalize(GObject* object)
   1381 {
   1382     // We need to manually call the destructor here, since this object's memory is managed
   1383     // by GLib. This calls all C++ members' destructors and prevents memory leaks.
   1384     WEBKIT_WEB_VIEW(object)->priv->~WebKitWebViewPrivate();
   1385     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
   1386 }
   1387 
   1388 static gboolean webkit_signal_accumulator_object_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
   1389 {
   1390     gpointer newWebView = g_value_get_object(handlerReturn);
   1391     g_value_set_object(returnAccu, newWebView);
   1392 
   1393     // Continue if we don't have a newWebView
   1394     return !newWebView;
   1395 }
   1396 
   1397 static gboolean webkit_navigation_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
   1398 {
   1399     WebKitNavigationResponse navigationResponse = (WebKitNavigationResponse)g_value_get_enum(handlerReturn);
   1400     g_value_set_enum(returnAccu, navigationResponse);
   1401 
   1402     if (navigationResponse != WEBKIT_NAVIGATION_RESPONSE_ACCEPT)
   1403         return FALSE;
   1404 
   1405     return TRUE;
   1406 }
   1407 
   1408 static AtkObject* webkit_web_view_get_accessible(GtkWidget* widget)
   1409 {
   1410     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1411     if (!core(webView))
   1412         return 0;
   1413 
   1414     AXObjectCache::enableAccessibility();
   1415 
   1416     Frame* coreFrame = core(webView)->mainFrame();
   1417     if (!coreFrame)
   1418         return 0;
   1419 
   1420     Document* doc = coreFrame->document();
   1421     if (!doc)
   1422         return 0;
   1423 
   1424     AccessibilityObject* rootAccessible = doc->axObjectCache()->rootObject();
   1425     if (!rootAccessible)
   1426         return 0;
   1427 
   1428     // We need to return the root accessibility object's first child
   1429     // to get to the actual ATK Object associated with the web view.
   1430     // See https://bugs.webkit.org/show_bug.cgi?id=51932
   1431     AtkObject* axRoot = rootAccessible->wrapper();
   1432     if (!axRoot || !ATK_IS_OBJECT(axRoot))
   1433         return 0;
   1434 
   1435     AtkObject* axWebView = atk_object_ref_accessible_child(ATK_OBJECT(axRoot), 0);
   1436     if (!axWebView || !ATK_IS_OBJECT(axWebView))
   1437         return 0;
   1438 
   1439     // We don't want the extra reference returned by ref_accessible_child.
   1440     g_object_unref(axWebView);
   1441     return axWebView;
   1442 }
   1443 
   1444 static gdouble webViewGetDPI(WebKitWebView* webView)
   1445 {
   1446     WebKitWebViewPrivate* priv = webView->priv;
   1447     WebKitWebSettings* webSettings = priv->webSettings.get();
   1448     gboolean enforce96DPI;
   1449     g_object_get(webSettings, "enforce-96-dpi", &enforce96DPI, NULL);
   1450     if (enforce96DPI)
   1451         return 96.0;
   1452 
   1453     gdouble DPI = defaultDPI;
   1454     GdkScreen* screen = gtk_widget_has_screen(GTK_WIDGET(webView)) ? gtk_widget_get_screen(GTK_WIDGET(webView)) : gdk_screen_get_default();
   1455     if (screen) {
   1456         DPI = gdk_screen_get_resolution(screen);
   1457         // gdk_screen_get_resolution() returns -1 when no DPI is set.
   1458         if (DPI == -1)
   1459             DPI = defaultDPI;
   1460     }
   1461     ASSERT(DPI > 0);
   1462     return DPI;
   1463 }
   1464 
   1465 static void webkit_web_view_screen_changed(GtkWidget* widget, GdkScreen* previousScreen)
   1466 {
   1467     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1468     WebKitWebViewPrivate* priv = webView->priv;
   1469 
   1470     if (priv->disposing)
   1471         return;
   1472 
   1473     WebKitWebSettings* webSettings = priv->webSettings.get();
   1474     Settings* settings = core(webView)->settings();
   1475     gdouble DPI = webViewGetDPI(webView);
   1476 
   1477     guint defaultFontSize, defaultMonospaceFontSize, minimumFontSize, minimumLogicalFontSize;
   1478 
   1479     g_object_get(webSettings,
   1480                  "default-font-size", &defaultFontSize,
   1481                  "default-monospace-font-size", &defaultMonospaceFontSize,
   1482                  "minimum-font-size", &minimumFontSize,
   1483                  "minimum-logical-font-size", &minimumLogicalFontSize,
   1484                  NULL);
   1485 
   1486     settings->setDefaultFontSize(defaultFontSize / 72.0 * DPI);
   1487     settings->setDefaultFixedFontSize(defaultMonospaceFontSize / 72.0 * DPI);
   1488     settings->setMinimumFontSize(minimumFontSize / 72.0 * DPI);
   1489     settings->setMinimumLogicalFontSize(minimumLogicalFontSize / 72.0 * DPI);
   1490 }
   1491 
   1492 static IntPoint globalPointForClientPoint(GdkWindow* window, const IntPoint& clientPoint)
   1493 {
   1494     int x, y;
   1495     gdk_window_get_origin(window, &x, &y);
   1496     return clientPoint + IntSize(x, y);
   1497 }
   1498 
   1499 
   1500 static void webkit_web_view_drag_end(GtkWidget* widget, GdkDragContext* context)
   1501 {
   1502     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1503     WebKitWebViewPrivate* priv = webView->priv;
   1504 
   1505     // This might happen if a drag is still in progress after a WebKitWebView
   1506     // is disposed and before it is finalized.
   1507     if (!priv->draggingDataObjects.contains(context))
   1508         return;
   1509 
   1510     priv->draggingDataObjects.remove(context);
   1511 
   1512     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   1513     if (!frame)
   1514         return;
   1515 
   1516     GOwnPtr<GdkEvent> event(gdk_event_new(GDK_BUTTON_RELEASE));
   1517     int x, y, xRoot, yRoot;
   1518     GdkModifierType modifiers = static_cast<GdkModifierType>(0);
   1519 #ifdef GTK_API_VERSION_2
   1520     GdkDisplay* display = gdk_display_get_default();
   1521     gdk_display_get_pointer(display, 0, &xRoot, &yRoot, &modifiers);
   1522     event->button.window = gdk_display_get_window_at_pointer(display, &x, &y);
   1523 #else
   1524     GdkDevice* device = gdk_drag_context_get_device(context);
   1525     event->button.window = gdk_device_get_window_at_position(device, &x, &y);
   1526     gdk_device_get_position(device, 0, &xRoot, &yRoot);
   1527 #endif
   1528 
   1529     if (event->button.window)
   1530         g_object_ref(event->button.window);
   1531     event->button.x = x;
   1532     event->button.y = y;
   1533     event->button.x_root = xRoot;
   1534     event->button.y_root = yRoot;
   1535     event->button.state = modifiers;
   1536 
   1537     PlatformMouseEvent platformEvent(&event->button);
   1538     frame->eventHandler()->dragSourceEndedAt(platformEvent, gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
   1539 }
   1540 
   1541 static void webkit_web_view_drag_data_get(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint)
   1542 {
   1543     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(widget)->priv;
   1544 
   1545     // This might happen if a drag is still in progress after a WebKitWebView
   1546     // is diposed and before it is finalized.
   1547     if (!priv->draggingDataObjects.contains(context))
   1548         return;
   1549 
   1550     pasteboardHelperInstance()->fillSelectionData(selectionData, info, priv->draggingDataObjects.get(context).get());
   1551 }
   1552 
   1553 static gboolean doDragLeaveLater(DroppingContext* context)
   1554 {
   1555     WebKitWebView* webView = context->webView;
   1556     WebKitWebViewPrivate* priv = webView->priv;
   1557 
   1558     if (!priv->droppingContexts.contains(context->gdkContext))
   1559         return FALSE;
   1560 
   1561     // If the view doesn't know about the drag yet (there are still pending data)
   1562     // requests, don't update it with information about the drag.
   1563     if (context->pendingDataRequests)
   1564         return FALSE;
   1565 
   1566     // Don't call dragExited if we have just received a drag-drop signal. This
   1567     // happens in the case of a successful drop onto the view.
   1568     if (!context->dropHappened) {
   1569         const IntPoint& position = context->lastMotionPosition;
   1570         DragData dragData(context->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(GTK_WIDGET(webView)), position), DragOperationNone);
   1571         core(webView)->dragController()->dragExited(&dragData);
   1572     }
   1573 
   1574     core(webView)->dragController()->dragEnded();
   1575     priv->droppingContexts.remove(context->gdkContext);
   1576     delete context;
   1577     return FALSE;
   1578 }
   1579 
   1580 static void webkit_web_view_drag_leave(GtkWidget* widget, GdkDragContext* context, guint time)
   1581 {
   1582     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1583     WebKitWebViewPrivate* priv = webView->priv;
   1584 
   1585     if (!priv->droppingContexts.contains(context))
   1586         return;
   1587 
   1588     // During a drop GTK+ will fire a drag-leave signal right before firing
   1589     // the drag-drop signal. We want the actions for drag-leave to happen after
   1590     // those for drag-drop, so schedule them to happen asynchronously here.
   1591     g_timeout_add(0, reinterpret_cast<GSourceFunc>(doDragLeaveLater), priv->droppingContexts.get(context));
   1592 }
   1593 
   1594 static gboolean webkit_web_view_drag_motion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
   1595 {
   1596     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1597     WebKitWebViewPrivate* priv = webView->priv;
   1598 
   1599     DroppingContext* droppingContext = 0;
   1600     IntPoint position = IntPoint(x, y);
   1601     if (!priv->droppingContexts.contains(context)) {
   1602         droppingContext = new DroppingContext;
   1603         droppingContext->webView = webView;
   1604         droppingContext->gdkContext = context;
   1605         droppingContext->dataObject = WebCore::DataObjectGtk::create();
   1606         droppingContext->dropHappened = false;
   1607         droppingContext->lastMotionPosition = position;
   1608         priv->droppingContexts.set(context, droppingContext);
   1609 
   1610         Vector<GdkAtom> acceptableTargets(pasteboardHelperInstance()->dropAtomsForContext(widget, context));
   1611         droppingContext->pendingDataRequests = acceptableTargets.size();
   1612         for (size_t i = 0; i < acceptableTargets.size(); i++)
   1613             gtk_drag_get_data(widget, context, acceptableTargets.at(i), time);
   1614     } else {
   1615         droppingContext = priv->droppingContexts.get(context);
   1616         droppingContext->lastMotionPosition = position;
   1617     }
   1618 
   1619     // Don't send any drag information to WebCore until we've retrieved all
   1620     // the data for this drag operation. Otherwise we'd have to block to wait
   1621     // for the drag's data.
   1622     ASSERT(droppingContext);
   1623     if (droppingContext->pendingDataRequests > 0)
   1624         return TRUE;
   1625 
   1626     DragData dragData(droppingContext->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(widget), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
   1627     DragOperation operation = core(webView)->dragController()->dragUpdated(&dragData);
   1628     gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
   1629 
   1630     return TRUE;
   1631 }
   1632 
   1633 static void webkit_web_view_drag_data_received(GtkWidget* widget, GdkDragContext* context, gint x, gint y, GtkSelectionData* selectionData, guint info, guint time)
   1634 {
   1635     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1636     WebKitWebViewPrivate* priv = webView->priv;
   1637 
   1638     if (!priv->droppingContexts.contains(context))
   1639         return;
   1640 
   1641     DroppingContext* droppingContext = priv->droppingContexts.get(context);
   1642     droppingContext->pendingDataRequests--;
   1643     pasteboardHelperInstance()->fillDataObjectFromDropData(selectionData, info, droppingContext->dataObject.get());
   1644 
   1645     if (droppingContext->pendingDataRequests)
   1646         return;
   1647 
   1648     // The coordinates passed to drag-data-received signal are sometimes
   1649     // inaccurate in DRT, so use the coordinates of the last motion event.
   1650     const IntPoint& position = droppingContext->lastMotionPosition;
   1651 
   1652     // If there are no more pending requests, start sending dragging data to WebCore.
   1653     DragData dragData(droppingContext->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(widget), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
   1654     DragOperation operation = core(webView)->dragController()->dragEntered(&dragData);
   1655     gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
   1656 }
   1657 
   1658 static gboolean webkit_web_view_drag_drop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
   1659 {
   1660     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1661     WebKitWebViewPrivate* priv = webView->priv;
   1662 
   1663     if (!priv->droppingContexts.contains(context))
   1664         return FALSE;
   1665 
   1666     DroppingContext* droppingContext = priv->droppingContexts.get(context);
   1667     droppingContext->dropHappened = true;
   1668 
   1669     IntPoint position(x, y);
   1670     DragData dragData(droppingContext->dataObject.get(), position, globalPointForClientPoint(gtk_widget_get_window(widget), position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
   1671     core(webView)->dragController()->performDrag(&dragData);
   1672 
   1673     gtk_drag_finish(context, TRUE, FALSE, time);
   1674     return TRUE;
   1675 }
   1676 
   1677 #if GTK_CHECK_VERSION(2, 12, 0)
   1678 static gboolean webkit_web_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip)
   1679 {
   1680     WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(widget)->priv;
   1681 
   1682     if (keyboard_mode) {
   1683         WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
   1684 
   1685         // Get the title of the current focused element.
   1686         Frame* coreFrame = core(webView)->focusController()->focusedOrMainFrame();
   1687         if (!coreFrame)
   1688             return FALSE;
   1689 
   1690         Node* node = getFocusedNode(coreFrame);
   1691         if (!node)
   1692             return FALSE;
   1693 
   1694         for (Node* titleNode = node; titleNode; titleNode = titleNode->parentNode()) {
   1695             if (titleNode->isElementNode()) {
   1696                 String title = static_cast<Element*>(titleNode)->title();
   1697                 if (!title.isEmpty()) {
   1698                     if (FrameView* view = coreFrame->view()) {
   1699                         GdkRectangle area = view->contentsToWindow(node->getRect());
   1700                         gtk_tooltip_set_tip_area(tooltip, &area);
   1701                     }
   1702                     gtk_tooltip_set_text(tooltip, title.utf8().data());
   1703 
   1704                     return TRUE;
   1705                 }
   1706             }
   1707         }
   1708 
   1709         return FALSE;
   1710     }
   1711 
   1712     if (priv->tooltipText.length() > 0) {
   1713         if (!keyboard_mode) {
   1714             if (!priv->tooltipArea.isEmpty()) {
   1715                 GdkRectangle area = priv->tooltipArea;
   1716                 gtk_tooltip_set_tip_area(tooltip, &area);
   1717             } else
   1718                 gtk_tooltip_set_tip_area(tooltip, 0);
   1719         }
   1720         gtk_tooltip_set_text(tooltip, priv->tooltipText.data());
   1721         return TRUE;
   1722     }
   1723 
   1724     return FALSE;
   1725 }
   1726 
   1727 static gboolean webkit_web_view_show_help(GtkWidget* widget, GtkWidgetHelpType help_type)
   1728 {
   1729     if (help_type == GTK_WIDGET_HELP_TOOLTIP)
   1730         gtk_widget_set_has_tooltip(widget, TRUE);
   1731 
   1732     return GTK_WIDGET_CLASS(webkit_web_view_parent_class)->show_help(widget, help_type);
   1733 }
   1734 #endif
   1735 
   1736 static GtkIMContext* webkit_web_view_get_im_context(WebKitWebView* webView)
   1737 {
   1738     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   1739     return GTK_IM_CONTEXT(webView->priv->imContext.get());
   1740 }
   1741 
   1742 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
   1743 {
   1744     GtkBindingSet* binding_set;
   1745 
   1746     webkitInit();
   1747 
   1748     /*
   1749      * Signals
   1750      */
   1751 
   1752     /**
   1753      * WebKitWebView::create-web-view:
   1754      * @webView: the object on which the signal is emitted
   1755      * @frame: the #WebKitWebFrame
   1756      *
   1757      * Emitted when the creation of a new window is requested.
   1758      * If this signal is handled the signal handler should return the
   1759      * newly created #WebKitWebView.
   1760      *
   1761      * The new #WebKitWebView should not be displayed to the user
   1762      * until the #WebKitWebView::web-view-ready signal is emitted.
   1763      *
   1764      * The signal handlers should not try to deal with the reference count for
   1765      * the new #WebKitWebView. The widget to which the widget is added will
   1766      * handle that.
   1767      *
   1768      * Return value: (transfer full): a newly allocated #WebKitWebView, or %NULL
   1769      *
   1770      * Since: 1.0.3
   1771      */
   1772     webkit_web_view_signals[CREATE_WEB_VIEW] = g_signal_new("create-web-view",
   1773             G_TYPE_FROM_CLASS(webViewClass),
   1774             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1775             G_STRUCT_OFFSET (WebKitWebViewClass, create_web_view),
   1776             webkit_signal_accumulator_object_handled,
   1777             NULL,
   1778             webkit_marshal_OBJECT__OBJECT,
   1779             WEBKIT_TYPE_WEB_VIEW , 1,
   1780             WEBKIT_TYPE_WEB_FRAME);
   1781 
   1782     /**
   1783      * WebKitWebView::web-view-ready:
   1784      * @webView: the object on which the signal is emitted
   1785      *
   1786      * Emitted after #WebKitWebView::create-web-view when the new #WebKitWebView
   1787      * should be displayed to the user. When this signal is emitted
   1788      * all the information about how the window should look, including
   1789      * size, position, whether the location, status and scroll bars
   1790      * should be displayed, is already set on the
   1791      * #WebKitWebWindowFeatures object contained by the #WebKitWebView.
   1792      *
   1793      * Notice that some of that information may change during the life
   1794      * time of the window, so you may want to connect to the ::notify
   1795      * signal of the #WebKitWebWindowFeatures object to handle those.
   1796      *
   1797      * Return value: %TRUE to stop handlers from being invoked for the event or
   1798      * %FALSE to propagate the event furter
   1799      *
   1800      * Since: 1.0.3
   1801      */
   1802     webkit_web_view_signals[WEB_VIEW_READY] = g_signal_new("web-view-ready",
   1803             G_TYPE_FROM_CLASS(webViewClass),
   1804             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1805             G_STRUCT_OFFSET (WebKitWebViewClass, web_view_ready),
   1806             g_signal_accumulator_true_handled,
   1807             NULL,
   1808             webkit_marshal_BOOLEAN__VOID,
   1809             G_TYPE_BOOLEAN, 0);
   1810 
   1811     /**
   1812      * WebKitWebView::close-web-view:
   1813      * @webView: the object on which the signal is emitted
   1814      *
   1815      * Emitted when closing a #WebKitWebView is requested. This occurs when a
   1816      * call is made from JavaScript's window.close function. The default
   1817      * signal handler does not do anything. It is the owner's responsibility
   1818      * to hide or delete the web view, if necessary.
   1819      *
   1820      * Return value: %TRUE to stop handlers from being invoked for the event or
   1821      * %FALSE to propagate the event furter
   1822      *
   1823      * Since: 1.1.11
   1824      */
   1825     webkit_web_view_signals[CLOSE_WEB_VIEW] = g_signal_new("close-web-view",
   1826             G_TYPE_FROM_CLASS(webViewClass),
   1827             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1828             G_STRUCT_OFFSET (WebKitWebViewClass, close_web_view),
   1829             g_signal_accumulator_true_handled,
   1830             NULL,
   1831             webkit_marshal_BOOLEAN__VOID,
   1832             G_TYPE_BOOLEAN, 0);
   1833 
   1834     /**
   1835      * WebKitWebView::navigation-requested:
   1836      * @webView: the object on which the signal is emitted
   1837      * @frame: the #WebKitWebFrame that required the navigation
   1838      * @request: a #WebKitNetworkRequest
   1839      *
   1840      * Emitted when @frame requests a navigation to another page.
   1841      *
   1842      * Return value: a #WebKitNavigationResponse
   1843      *
   1844      * Deprecated: Use WebKitWebView::navigation-policy-decision-requested
   1845      * instead
   1846      */
   1847     webkit_web_view_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation-requested",
   1848             G_TYPE_FROM_CLASS(webViewClass),
   1849             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1850             G_STRUCT_OFFSET (WebKitWebViewClass, navigation_requested),
   1851             webkit_navigation_request_handled,
   1852             NULL,
   1853             webkit_marshal_ENUM__OBJECT_OBJECT,
   1854             WEBKIT_TYPE_NAVIGATION_RESPONSE, 2,
   1855             WEBKIT_TYPE_WEB_FRAME,
   1856             WEBKIT_TYPE_NETWORK_REQUEST);
   1857 
   1858     /**
   1859      * WebKitWebView::new-window-policy-decision-requested:
   1860      * @webView: the object on which the signal is emitted
   1861      * @frame: the #WebKitWebFrame that required the navigation
   1862      * @request: a #WebKitNetworkRequest
   1863      * @navigation_action: a #WebKitWebNavigationAction
   1864      * @policy_decision: a #WebKitWebPolicyDecision
   1865      *
   1866      * Emitted when @frame requests opening a new window. With this
   1867      * signal the browser can use the context of the request to decide
   1868      * about the new window. If the request is not handled the default
   1869      * behavior is to allow opening the new window to load the URI,
   1870      * which will cause a create-web-view signal emission where the
   1871      * browser handles the new window action but without information
   1872      * of the context that caused the navigation. The following
   1873      * navigation-policy-decision-requested emissions will load the
   1874      * page after the creation of the new window just with the
   1875      * information of this new navigation context, without any
   1876      * information about the action that made this new window to be
   1877      * opened.
   1878      *
   1879      * Notice that if you return TRUE, meaning that you handled the
   1880      * signal, you are expected to have decided what to do, by calling
   1881      * webkit_web_policy_decision_ignore(),
   1882      * webkit_web_policy_decision_use(), or
   1883      * webkit_web_policy_decision_download() on the @policy_decision
   1884      * object.
   1885      *
   1886      * Return value: %TRUE if a decision was made, %FALSE to have the
   1887      * default behavior apply
   1888      *
   1889      * Since: 1.1.4
   1890      */
   1891     webkit_web_view_signals[NEW_WINDOW_POLICY_DECISION_REQUESTED] =
   1892         g_signal_new("new-window-policy-decision-requested",
   1893             G_TYPE_FROM_CLASS(webViewClass),
   1894             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1895             0,
   1896             g_signal_accumulator_true_handled,
   1897             NULL,
   1898             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
   1899             G_TYPE_BOOLEAN, 4,
   1900             WEBKIT_TYPE_WEB_FRAME,
   1901             WEBKIT_TYPE_NETWORK_REQUEST,
   1902             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
   1903             WEBKIT_TYPE_WEB_POLICY_DECISION);
   1904 
   1905     /**
   1906      * WebKitWebView::navigation-policy-decision-requested:
   1907      * @webView: the object on which the signal is emitted
   1908      * @frame: the #WebKitWebFrame that required the navigation
   1909      * @request: a #WebKitNetworkRequest
   1910      * @navigation_action: a #WebKitWebNavigationAction
   1911      * @policy_decision: a #WebKitWebPolicyDecision
   1912      *
   1913      * Emitted when @frame requests a navigation to another page.
   1914      * If this signal is not handled, the default behavior is to allow the
   1915      * navigation.
   1916      *
   1917      * Notice that if you return TRUE, meaning that you handled the
   1918      * signal, you are expected to have decided what to do, by calling
   1919      * webkit_web_policy_decision_ignore(),
   1920      * webkit_web_policy_decision_use(), or
   1921      * webkit_web_policy_decision_download() on the @policy_decision
   1922      * object.
   1923      *
   1924      * Return value: %TRUE if a decision was made, %FALSE to have the
   1925      * default behavior apply
   1926      *
   1927      * Since: 1.0.3
   1928      */
   1929     webkit_web_view_signals[NAVIGATION_POLICY_DECISION_REQUESTED] = g_signal_new("navigation-policy-decision-requested",
   1930             G_TYPE_FROM_CLASS(webViewClass),
   1931             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1932             0,
   1933             g_signal_accumulator_true_handled,
   1934             NULL,
   1935             webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT,
   1936             G_TYPE_BOOLEAN, 4,
   1937             WEBKIT_TYPE_WEB_FRAME,
   1938             WEBKIT_TYPE_NETWORK_REQUEST,
   1939             WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
   1940             WEBKIT_TYPE_WEB_POLICY_DECISION);
   1941 
   1942     /**
   1943      * WebKitWebView::mime-type-policy-decision-requested:
   1944      * @webView: the object on which the signal is emitted
   1945      * @frame: the #WebKitWebFrame that required the policy decision
   1946      * @request: a WebKitNetworkRequest
   1947      * @mimetype: the MIME type attempted to load
   1948      * @policy_decision: a #WebKitWebPolicyDecision
   1949      *
   1950      * Decide whether or not to display the given MIME type.  If this
   1951      * signal is not handled, the default behavior is to show the
   1952      * content of the requested URI if WebKit can show this MIME
   1953      * type and the content disposition is not a download; if WebKit
   1954      * is not able to show the MIME type nothing happens.
   1955      *
   1956      * Notice that if you return TRUE, meaning that you handled the
   1957      * signal, you are expected to be aware of the "Content-Disposition"
   1958      * header. A value of "attachment" usually indicates a download
   1959      * regardless of the MIME type, see also
   1960      * soup_message_headers_get_content_disposition(). And you must call
   1961      * webkit_web_policy_decision_ignore(),
   1962      * webkit_web_policy_decision_use(), or
   1963      * webkit_web_policy_decision_download() on the @policy_decision
   1964      * object.
   1965      *
   1966      * Return value: %TRUE if a decision was made, %FALSE to have the
   1967      * default behavior apply
   1968      *
   1969      * Since: 1.0.3
   1970      */
   1971     webkit_web_view_signals[MIME_TYPE_POLICY_DECISION_REQUESTED] = g_signal_new("mime-type-policy-decision-requested",
   1972             G_TYPE_FROM_CLASS(webViewClass),
   1973             (GSignalFlags)G_SIGNAL_RUN_LAST,
   1974             0,
   1975             g_signal_accumulator_true_handled,
   1976             NULL,
   1977             webkit_marshal_BOOLEAN__OBJECT_OBJECT_STRING_OBJECT,
   1978             G_TYPE_BOOLEAN, 4,
   1979             WEBKIT_TYPE_WEB_FRAME,
   1980             WEBKIT_TYPE_NETWORK_REQUEST,
   1981             G_TYPE_STRING,
   1982             WEBKIT_TYPE_WEB_POLICY_DECISION);
   1983 
   1984     /**
   1985      * WebKitWebView::window-object-cleared:
   1986      * @webView: the object on which the signal is emitted
   1987      * @frame: the #WebKitWebFrame to which @window_object belongs
   1988      * @context: the #JSGlobalContextRef holding the global object and other
   1989      * execution state; equivalent to the return value of
   1990      * webkit_web_frame_get_global_context(@frame)
   1991      * @window_object: the #JSObjectRef representing the frame's JavaScript
   1992      * window object
   1993      *
   1994      * Emitted when the JavaScript window object in a #WebKitWebFrame has been
   1995      * cleared in preparation for a new load. This is the preferred place to
   1996      * set custom properties on the window object using the JavaScriptCore API.
   1997      */
   1998     webkit_web_view_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window-object-cleared",
   1999             G_TYPE_FROM_CLASS(webViewClass),
   2000             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2001             G_STRUCT_OFFSET (WebKitWebViewClass, window_object_cleared),
   2002             NULL,
   2003             NULL,
   2004             webkit_marshal_VOID__OBJECT_POINTER_POINTER,
   2005             G_TYPE_NONE, 3,
   2006             WEBKIT_TYPE_WEB_FRAME,
   2007             G_TYPE_POINTER,
   2008             G_TYPE_POINTER);
   2009 
   2010     /**
   2011      * WebKitWebView::download-requested:
   2012      * @webView: the object on which the signal is emitted
   2013      * @download: a #WebKitDownload object that lets you control the
   2014      * download process
   2015      *
   2016      * A new Download is being requested. By default, if the signal is
   2017      * not handled, the download is cancelled. If you handle the download
   2018      * and call webkit_download_set_destination_uri(), it will be
   2019      * started for you. If you need to set the destination asynchronously
   2020      * you are responsible for starting or cancelling it yourself.
   2021      *
   2022      * If you intend to handle downloads yourself rather than using
   2023      * the #WebKitDownload helper object you must handle this signal,
   2024      * and return %FALSE.
   2025      *
   2026      * Also, keep in mind that the default policy for WebKitGTK+ is to
   2027      * ignore files with a MIME type that it does not know how to
   2028      * handle, which means this signal won't be emitted in the default
   2029      * setup. One way to trigger downloads is to connect to
   2030      * WebKitWebView::mime-type-policy-decision-requested and call
   2031      * webkit_web_policy_decision_download() on the
   2032      * #WebKitWebPolicyDecision in the parameter list for the kind of
   2033      * files you want your application to download (a common solution
   2034      * is to download anything that WebKit can't handle, which you can
   2035      * figure out by using webkit_web_view_can_show_mime_type()).
   2036      *
   2037      * Return value: TRUE if the download should be performed, %FALSE to
   2038      * cancel it
   2039      *
   2040      * Since: 1.1.2
   2041      */
   2042     webkit_web_view_signals[DOWNLOAD_REQUESTED] = g_signal_new("download-requested",
   2043             G_TYPE_FROM_CLASS(webViewClass),
   2044             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2045             0,
   2046             g_signal_accumulator_true_handled,
   2047             NULL,
   2048             webkit_marshal_BOOLEAN__OBJECT,
   2049             G_TYPE_BOOLEAN, 1,
   2050             G_TYPE_OBJECT);
   2051 
   2052     /**
   2053      * WebKitWebView::load-started:
   2054      * @webView: the object on which the signal is emitted
   2055      * @frame: the frame going to do the load
   2056      *
   2057      * When a #WebKitWebFrame begins to load this signal is emitted.
   2058      *
   2059      * Deprecated: Use the "load-status" property instead.
   2060      */
   2061     webkit_web_view_signals[LOAD_STARTED] = g_signal_new("load-started",
   2062             G_TYPE_FROM_CLASS(webViewClass),
   2063             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2064             0,
   2065             NULL,
   2066             NULL,
   2067             g_cclosure_marshal_VOID__OBJECT,
   2068             G_TYPE_NONE, 1,
   2069             WEBKIT_TYPE_WEB_FRAME);
   2070 
   2071     /**
   2072      * WebKitWebView::load-committed:
   2073      * @webView: the object on which the signal is emitted
   2074      * @frame: the main frame that received the first data
   2075      *
   2076      * When a #WebKitWebFrame loaded the first data this signal is emitted.
   2077      *
   2078      * Deprecated: Use the "load-status" property instead.
   2079      */
   2080     webkit_web_view_signals[LOAD_COMMITTED] = g_signal_new("load-committed",
   2081             G_TYPE_FROM_CLASS(webViewClass),
   2082             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2083             0,
   2084             NULL,
   2085             NULL,
   2086             g_cclosure_marshal_VOID__OBJECT,
   2087             G_TYPE_NONE, 1,
   2088             WEBKIT_TYPE_WEB_FRAME);
   2089 
   2090 
   2091     /**
   2092      * WebKitWebView::load-progress-changed:
   2093      * @webView: the #WebKitWebView
   2094      * @progress: the global progress
   2095      *
   2096      * Deprecated: Use the "progress" property instead.
   2097      */
   2098     webkit_web_view_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load-progress-changed",
   2099             G_TYPE_FROM_CLASS(webViewClass),
   2100             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2101             0,
   2102             NULL,
   2103             NULL,
   2104             g_cclosure_marshal_VOID__INT,
   2105             G_TYPE_NONE, 1,
   2106             G_TYPE_INT);
   2107 
   2108     /**
   2109      * WebKitWebView::load-error
   2110      * @webView: the object on which the signal is emitted
   2111      * @web_frame: the #WebKitWebFrame
   2112      * @uri: the URI that triggered the error
   2113      * @web_error: the #GError that was triggered
   2114      *
   2115      * An error occurred while loading. By default, if the signal is not
   2116      * handled, the @web_view will display a stock error page. You need to
   2117      * handle the signal if you want to provide your own error page.
   2118      *
   2119      * Since: 1.1.6
   2120      *
   2121      * Return value: %TRUE to stop other handlers from being invoked for the
   2122      * event. %FALSE to propagate the event further.
   2123      */
   2124     webkit_web_view_signals[LOAD_ERROR] = g_signal_new("load-error",
   2125             G_TYPE_FROM_CLASS(webViewClass),
   2126             (GSignalFlags)(G_SIGNAL_RUN_LAST),
   2127             0,
   2128             g_signal_accumulator_true_handled,
   2129             NULL,
   2130             webkit_marshal_BOOLEAN__OBJECT_STRING_POINTER,
   2131             G_TYPE_BOOLEAN, 3,
   2132             WEBKIT_TYPE_WEB_FRAME,
   2133             G_TYPE_STRING,
   2134             G_TYPE_POINTER);
   2135 
   2136     /**
   2137      * WebKitWebView::load-finished:
   2138      * @webView: the #WebKitWebView
   2139      * @frame: the #WebKitWebFrame
   2140      *
   2141      * Deprecated: Use the "load-status" property instead.
   2142      */
   2143     webkit_web_view_signals[LOAD_FINISHED] = g_signal_new("load-finished",
   2144             G_TYPE_FROM_CLASS(webViewClass),
   2145             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2146             0,
   2147             NULL,
   2148             NULL,
   2149             g_cclosure_marshal_VOID__OBJECT,
   2150             G_TYPE_NONE, 1,
   2151             WEBKIT_TYPE_WEB_FRAME);
   2152 
   2153     /**
   2154      * WebKitWebView::onload-event:
   2155      * @webView: the object on which the signal is emitted
   2156      * @frame: the frame
   2157      *
   2158      * When a #WebKitWebFrame receives an onload event this signal is emitted.
   2159      */
   2160     webkit_web_view_signals[ONLOAD_EVENT] = g_signal_new("onload-event",
   2161             G_TYPE_FROM_CLASS(webViewClass),
   2162             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2163             0,
   2164             NULL,
   2165             NULL,
   2166             g_cclosure_marshal_VOID__OBJECT,
   2167             G_TYPE_NONE, 1,
   2168             WEBKIT_TYPE_WEB_FRAME);
   2169 
   2170     /**
   2171      * WebKitWebView::title-changed:
   2172      * @webView: the object on which the signal is emitted
   2173      * @frame: the main frame
   2174      * @title: the new title
   2175      *
   2176      * When a #WebKitWebFrame changes the document title this signal is emitted.
   2177      *
   2178      * Deprecated: 1.1.4: Use "notify::title" instead.
   2179      */
   2180     webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed",
   2181             G_TYPE_FROM_CLASS(webViewClass),
   2182             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2183             0,
   2184             NULL,
   2185             NULL,
   2186             webkit_marshal_VOID__OBJECT_STRING,
   2187             G_TYPE_NONE, 2,
   2188             WEBKIT_TYPE_WEB_FRAME,
   2189             G_TYPE_STRING);
   2190 
   2191     /**
   2192      * WebKitWebView::hovering-over-link:
   2193      * @webView: the object on which the signal is emitted
   2194      * @title: the link's title
   2195      * @uri: the URI the link points to
   2196      *
   2197      * When the cursor is over a link, this signal is emitted.
   2198      */
   2199     webkit_web_view_signals[HOVERING_OVER_LINK] = g_signal_new("hovering-over-link",
   2200             G_TYPE_FROM_CLASS(webViewClass),
   2201             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2202             0,
   2203             NULL,
   2204             NULL,
   2205             webkit_marshal_VOID__STRING_STRING,
   2206             G_TYPE_NONE, 2,
   2207             G_TYPE_STRING,
   2208             G_TYPE_STRING);
   2209 
   2210     /**
   2211      * WebKitWebView::populate-popup:
   2212      * @webView: the object on which the signal is emitted
   2213      * @menu: the context menu
   2214      *
   2215      * When a context menu is about to be displayed this signal is emitted.
   2216      *
   2217      * Add menu items to #menu to extend the context menu.
   2218      */
   2219     webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
   2220             G_TYPE_FROM_CLASS(webViewClass),
   2221             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2222             0,
   2223             NULL,
   2224             NULL,
   2225             g_cclosure_marshal_VOID__OBJECT,
   2226             G_TYPE_NONE, 1,
   2227             GTK_TYPE_MENU);
   2228 
   2229     /**
   2230      * WebKitWebView::print-requested
   2231      * @webView: the object in which the signal is emitted
   2232      * @web_frame: the frame that is requesting to be printed
   2233      *
   2234      * Emitted when printing is requested by the frame, usually
   2235      * because of a javascript call. When handling this signal you
   2236      * should call webkit_web_frame_print_full() or
   2237      * webkit_web_frame_print() to do the actual printing.
   2238      *
   2239      * The default handler will present a print dialog and carry a
   2240      * print operation. Notice that this means that if you intend to
   2241      * ignore a print request you must connect to this signal, and
   2242      * return %TRUE.
   2243      *
   2244      * Return value: %TRUE if the print request has been handled, %FALSE if
   2245      * the default handler should run
   2246      *
   2247      * Since: 1.1.5
   2248      */
   2249     webkit_web_view_signals[PRINT_REQUESTED] = g_signal_new("print-requested",
   2250             G_TYPE_FROM_CLASS(webViewClass),
   2251             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2252             0,
   2253             g_signal_accumulator_true_handled,
   2254             NULL,
   2255             webkit_marshal_BOOLEAN__OBJECT,
   2256             G_TYPE_BOOLEAN, 1,
   2257             WEBKIT_TYPE_WEB_FRAME);
   2258 
   2259     webkit_web_view_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status-bar-text-changed",
   2260             G_TYPE_FROM_CLASS(webViewClass),
   2261             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2262             0,
   2263             NULL,
   2264             NULL,
   2265             g_cclosure_marshal_VOID__STRING,
   2266             G_TYPE_NONE, 1,
   2267             G_TYPE_STRING);
   2268 
   2269     /**
   2270      * WebKitWebView::icon-loaded:
   2271      * @webView: the object on which the signal is emitted
   2272      * @icon_uri: the URI for the icon
   2273      *
   2274      * This signal is emitted when the main frame has got a favicon.
   2275      * See WebKitIconDatabase::icon-loaded if you want to keep track of
   2276      * icons for child frames.
   2277      *
   2278      * Since: 1.1.18
   2279      */
   2280     webkit_web_view_signals[ICON_LOADED] = g_signal_new("icon-loaded",
   2281             G_TYPE_FROM_CLASS(webViewClass),
   2282             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2283             0,
   2284             NULL,
   2285             NULL,
   2286             g_cclosure_marshal_VOID__STRING,
   2287             G_TYPE_NONE, 1,
   2288             G_TYPE_STRING);
   2289 
   2290     /**
   2291      * WebKitWebView::console-message:
   2292      * @webView: the object on which the signal is emitted
   2293      * @message: the message text
   2294      * @line: the line where the error occured
   2295      * @source_id: the source id
   2296      *
   2297      * A JavaScript console message was created.
   2298      *
   2299      * Return value: %TRUE to stop other handlers from being invoked for the
   2300      * event. %FALSE to propagate the event further.
   2301      */
   2302     webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message",
   2303             G_TYPE_FROM_CLASS(webViewClass),
   2304             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2305             G_STRUCT_OFFSET(WebKitWebViewClass, console_message),
   2306             g_signal_accumulator_true_handled,
   2307             NULL,
   2308             webkit_marshal_BOOLEAN__STRING_INT_STRING,
   2309             G_TYPE_BOOLEAN, 3,
   2310             G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
   2311 
   2312     /**
   2313      * WebKitWebView::script-alert:
   2314      * @webView: the object on which the signal is emitted
   2315      * @frame: the relevant frame
   2316      * @message: the message text
   2317      *
   2318      * A JavaScript alert dialog was created.
   2319      *
   2320      * Return value: %TRUE to stop other handlers from being invoked for the
   2321      * event. %FALSE to propagate the event further.
   2322      */
   2323     webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
   2324             G_TYPE_FROM_CLASS(webViewClass),
   2325             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2326             G_STRUCT_OFFSET(WebKitWebViewClass, script_alert),
   2327             g_signal_accumulator_true_handled,
   2328             NULL,
   2329             webkit_marshal_BOOLEAN__OBJECT_STRING,
   2330             G_TYPE_BOOLEAN, 2,
   2331             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING);
   2332 
   2333     /**
   2334      * WebKitWebView::script-confirm:
   2335      * @webView: the object on which the signal is emitted
   2336      * @frame: the relevant frame
   2337      * @message: the message text
   2338      * @confirmed: whether the dialog has been confirmed
   2339      *
   2340      * A JavaScript confirm dialog was created, providing Yes and No buttons.
   2341      *
   2342      * Return value: %TRUE to stop other handlers from being invoked for the
   2343      * event. %FALSE to propagate the event further.
   2344      */
   2345     webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm",
   2346             G_TYPE_FROM_CLASS(webViewClass),
   2347             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2348             G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm),
   2349             g_signal_accumulator_true_handled,
   2350             NULL,
   2351             webkit_marshal_BOOLEAN__OBJECT_STRING_POINTER,
   2352             G_TYPE_BOOLEAN, 3,
   2353             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_POINTER);
   2354 
   2355     /**
   2356      * WebKitWebView::script-prompt:
   2357      * @webView: the object on which the signal is emitted
   2358      * @frame: the relevant frame
   2359      * @message: the message text
   2360      * @default: the default value
   2361      * @text: To be filled with the return value or NULL if the dialog was cancelled.
   2362      *
   2363      * A JavaScript prompt dialog was created, providing an entry to input text.
   2364      *
   2365      * Return value: %TRUE to stop other handlers from being invoked for the
   2366      * event. %FALSE to propagate the event further.
   2367      */
   2368     webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt",
   2369             G_TYPE_FROM_CLASS(webViewClass),
   2370             (GSignalFlags)G_SIGNAL_RUN_LAST,
   2371             G_STRUCT_OFFSET(WebKitWebViewClass, script_prompt),
   2372             g_signal_accumulator_true_handled,
   2373             NULL,
   2374             webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
   2375             G_TYPE_BOOLEAN, 4,
   2376             WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
   2377 
   2378     /**
   2379      * WebKitWebView::select-all:
   2380      * @webView: the object which received the signal
   2381      *
   2382      * The #WebKitWebView::select-all signal is a keybinding signal which gets emitted to
   2383      * select the complete contents of the text view.
   2384      *
   2385      * The default bindings for this signal is Ctrl-a.
   2386      */
   2387     webkit_web_view_signals[SELECT_ALL] = g_signal_new("select-all",
   2388             G_TYPE_FROM_CLASS(webViewClass),
   2389             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2390             G_STRUCT_OFFSET(WebKitWebViewClass, select_all),
   2391             NULL, NULL,
   2392             g_cclosure_marshal_VOID__VOID,
   2393             G_TYPE_NONE, 0);
   2394 
   2395     /**
   2396      * WebKitWebView::cut-clipboard:
   2397      * @webView: the object which received the signal
   2398      *
   2399      * The #WebKitWebView::cut-clipboard signal is a keybinding signal which gets emitted to
   2400      * cut the selection to the clipboard.
   2401      *
   2402      * The default bindings for this signal are Ctrl-x and Shift-Delete.
   2403      */
   2404     webkit_web_view_signals[CUT_CLIPBOARD] = g_signal_new("cut-clipboard",
   2405             G_TYPE_FROM_CLASS(webViewClass),
   2406             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2407             G_STRUCT_OFFSET(WebKitWebViewClass, cut_clipboard),
   2408             NULL, NULL,
   2409             g_cclosure_marshal_VOID__VOID,
   2410             G_TYPE_NONE, 0);
   2411 
   2412     /**
   2413      * WebKitWebView::copy-clipboard:
   2414      * @webView: the object which received the signal
   2415      *
   2416      * The #WebKitWebView::copy-clipboard signal is a keybinding signal which gets emitted to
   2417      * copy the selection to the clipboard.
   2418      *
   2419      * The default bindings for this signal are Ctrl-c and Ctrl-Insert.
   2420      */
   2421     webkit_web_view_signals[COPY_CLIPBOARD] = g_signal_new("copy-clipboard",
   2422             G_TYPE_FROM_CLASS(webViewClass),
   2423             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2424             G_STRUCT_OFFSET(WebKitWebViewClass, copy_clipboard),
   2425             NULL, NULL,
   2426             g_cclosure_marshal_VOID__VOID,
   2427             G_TYPE_NONE, 0);
   2428 
   2429     /**
   2430      * WebKitWebView::paste-clipboard:
   2431      * @webView: the object which received the signal
   2432      *
   2433      * The #WebKitWebView::paste-clipboard signal is a keybinding signal which gets emitted to
   2434      * paste the contents of the clipboard into the Web view.
   2435      *
   2436      * The default bindings for this signal are Ctrl-v and Shift-Insert.
   2437      */
   2438     webkit_web_view_signals[PASTE_CLIPBOARD] = g_signal_new("paste-clipboard",
   2439             G_TYPE_FROM_CLASS(webViewClass),
   2440             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2441             G_STRUCT_OFFSET(WebKitWebViewClass, paste_clipboard),
   2442             NULL, NULL,
   2443             g_cclosure_marshal_VOID__VOID,
   2444             G_TYPE_NONE, 0);
   2445 
   2446     /**
   2447      * WebKitWebView::undo
   2448      * @webView: the object which received the signal
   2449      *
   2450      * The #WebKitWebView::undo signal is a keybinding signal which gets emitted to
   2451      * undo the last editing command.
   2452      *
   2453      * The default binding for this signal is Ctrl-z
   2454      *
   2455      * Since: 1.1.14
   2456      */
   2457     webkit_web_view_signals[UNDO] = g_signal_new("undo",
   2458             G_TYPE_FROM_CLASS(webViewClass),
   2459             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2460             G_STRUCT_OFFSET(WebKitWebViewClass, undo),
   2461             NULL, NULL,
   2462             g_cclosure_marshal_VOID__VOID,
   2463             G_TYPE_NONE, 0);
   2464 
   2465     /**
   2466      * WebKitWebView::redo
   2467      * @webView: the object which received the signal
   2468      *
   2469      * The #WebKitWebView::redo signal is a keybinding signal which gets emitted to
   2470      * redo the last editing command.
   2471      *
   2472      * The default binding for this signal is Ctrl-Shift-z
   2473      *
   2474      * Since: 1.1.14
   2475      */
   2476     webkit_web_view_signals[REDO] = g_signal_new("redo",
   2477             G_TYPE_FROM_CLASS(webViewClass),
   2478             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2479             G_STRUCT_OFFSET(WebKitWebViewClass, redo),
   2480             NULL, NULL,
   2481             g_cclosure_marshal_VOID__VOID,
   2482             G_TYPE_NONE, 0);
   2483 
   2484     /**
   2485      * WebKitWebView::move-cursor:
   2486      * @webView: the object which received the signal
   2487      * @step: the type of movement, one of #GtkMovementStep
   2488      * @count: an integer indicating the subtype of movement. Currently
   2489      *         the permitted values are '1' = forward, '-1' = backwards.
   2490      *
   2491      * The #WebKitWebView::move-cursor will be emitted to apply the
   2492      * cursor movement described by its parameters to the @view.
   2493      *
   2494      * Return value: %TRUE or %FALSE
   2495      *
   2496      * Since: 1.1.4
   2497      */
   2498     webkit_web_view_signals[MOVE_CURSOR] = g_signal_new("move-cursor",
   2499             G_TYPE_FROM_CLASS(webViewClass),
   2500             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2501             G_STRUCT_OFFSET(WebKitWebViewClass, move_cursor),
   2502             NULL, NULL,
   2503             webkit_marshal_BOOLEAN__ENUM_INT,
   2504             G_TYPE_BOOLEAN, 2,
   2505             GTK_TYPE_MOVEMENT_STEP,
   2506             G_TYPE_INT);
   2507 
   2508     /**
   2509      * WebKitWebView::create-plugin-widget:
   2510      * @webView: the object which received the signal
   2511      * @mime_type: the mimetype of the requested object
   2512      * @uri: the URI to load
   2513      * @param: a #GHashTable with additional attributes (strings)
   2514      *
   2515      * The #WebKitWebView::create-plugin-widget signal will be emitted to
   2516      * create a plugin widget for embed or object HTML tags. This
   2517      * allows to embed a GtkWidget as a plugin into HTML content. In
   2518      * case of a textual selection of the GtkWidget WebCore will attempt
   2519      * to set the property value of "webkit-widget-is-selected". This can
   2520      * be used to draw a visual indicator of the selection.
   2521      *
   2522      * Return value: (transfer full): a new #GtkWidget, or %NULL
   2523      *
   2524      * Since: 1.1.8
   2525      */
   2526     webkit_web_view_signals[PLUGIN_WIDGET] = g_signal_new("create-plugin-widget",
   2527             G_TYPE_FROM_CLASS(webViewClass),
   2528             (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2529             0,
   2530             webkit_signal_accumulator_object_handled,
   2531             NULL,
   2532             webkit_marshal_OBJECT__STRING_STRING_POINTER,
   2533             GTK_TYPE_WIDGET, 3,
   2534             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_HASH_TABLE);
   2535 
   2536     /**
   2537      * WebKitWebView::database-quota-exceeded
   2538      * @webView: the object which received the signal
   2539      * @frame: the relevant frame
   2540      * @database: the #WebKitWebDatabase which exceeded the quota of its #WebKitSecurityOrigin
   2541      *
   2542      * The #WebKitWebView::database-quota-exceeded signal will be emitted when
   2543      * a Web Database exceeds the quota of its security origin. This signal
   2544      * may be used to increase the size of the quota before the originating
   2545      * operation fails.
   2546      *
   2547      * Since: 1.1.14
   2548      */
   2549     webkit_web_view_signals[DATABASE_QUOTA_EXCEEDED] = g_signal_new("database-quota-exceeded",
   2550             G_TYPE_FROM_CLASS(webViewClass),
   2551             (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2552             0,
   2553             NULL, NULL,
   2554             webkit_marshal_VOID__OBJECT_OBJECT,
   2555             G_TYPE_NONE, 2,
   2556             G_TYPE_OBJECT, G_TYPE_OBJECT);
   2557 
   2558     /**
   2559      * WebKitWebView::resource-request-starting:
   2560      * @webView: the object which received the signal
   2561      * @web_frame: the #WebKitWebFrame whose load dispatched this request
   2562      * @web_resource: an empty #WebKitWebResource object
   2563      * @request: the #WebKitNetworkRequest that will be dispatched
   2564      * @response: the #WebKitNetworkResponse representing the redirect
   2565      * response, if any
   2566      *
   2567      * Emitted when a request is about to be sent. You can modify the
   2568      * request while handling this signal. You can set the URI in the
   2569      * #WebKitNetworkRequest object itself, and add/remove/replace
   2570      * headers using the #SoupMessage object it carries, if it is
   2571      * present. See webkit_network_request_get_message(). Setting the
   2572      * request URI to "about:blank" will effectively cause the request
   2573      * to load nothing, and can be used to disable the loading of
   2574      * specific resources.
   2575      *
   2576      * Notice that information about an eventual redirect is available
   2577      * in @response's #SoupMessage, not in the #SoupMessage carried by
   2578      * the @request. If @response is %NULL, then this is not a
   2579      * redirected request.
   2580      *
   2581      * The #WebKitWebResource object will be the same throughout all
   2582      * the lifetime of the resource, but the contents may change from
   2583      * inbetween signal emissions.
   2584      *
   2585      * Since: 1.1.14
   2586      */
   2587     webkit_web_view_signals[RESOURCE_REQUEST_STARTING] = g_signal_new("resource-request-starting",
   2588             G_TYPE_FROM_CLASS(webViewClass),
   2589             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2590             0,
   2591             NULL, NULL,
   2592             webkit_marshal_VOID__OBJECT_OBJECT_OBJECT_OBJECT,
   2593             G_TYPE_NONE, 4,
   2594             WEBKIT_TYPE_WEB_FRAME,
   2595             WEBKIT_TYPE_WEB_RESOURCE,
   2596             WEBKIT_TYPE_NETWORK_REQUEST,
   2597             WEBKIT_TYPE_NETWORK_RESPONSE);
   2598 
   2599     /**
   2600      * WebKitWebView::geolocation-policy-decision-requested:
   2601      * @webView: the object on which the signal is emitted
   2602      * @frame: the frame that requests permission
   2603      * @policy_decision: a WebKitGeolocationPolicyDecision
   2604      *
   2605      * This signal is emitted when a @frame wants to obtain the user's
   2606      * location. The decision can be made asynchronously, but you must
   2607      * call g_object_ref() the @policy_decision, and return %TRUE if
   2608      * you are going to handle the request. To actually make the
   2609      * decision you need to call webkit_geolocation_policy_allow() or
   2610      * webkit_geolocation_policy_deny() on @policy_decision.
   2611      *
   2612      * Since: 1.1.23
   2613      */
   2614     webkit_web_view_signals[GEOLOCATION_POLICY_DECISION_REQUESTED] = g_signal_new("geolocation-policy-decision-requested",
   2615             G_TYPE_FROM_CLASS(webViewClass),
   2616             (GSignalFlags)(G_SIGNAL_RUN_LAST),
   2617             0,
   2618             NULL, NULL,
   2619             webkit_marshal_BOOLEAN__OBJECT_OBJECT,
   2620             G_TYPE_BOOLEAN, 2,
   2621             WEBKIT_TYPE_WEB_FRAME,
   2622             WEBKIT_TYPE_GEOLOCATION_POLICY_DECISION);
   2623 
   2624     /**
   2625      * WebKitWebView::geolocation-policy-decision-cancelled:
   2626      * @webView: the object on which the signal is emitted
   2627      * @frame: the frame that cancels geolocation request.
   2628      *
   2629      * When a @frame wants to cancel geolocation permission it had requested
   2630      * before.
   2631      *
   2632      * Since: 1.1.23
   2633      */
   2634     webkit_web_view_signals[GEOLOCATION_POLICY_DECISION_CANCELLED] = g_signal_new("geolocation-policy-decision-cancelled",
   2635             G_TYPE_FROM_CLASS(webViewClass),
   2636             (GSignalFlags)(G_SIGNAL_RUN_LAST),
   2637             0,
   2638             NULL, NULL,
   2639             g_cclosure_marshal_VOID__OBJECT,
   2640             G_TYPE_NONE, 1,
   2641             WEBKIT_TYPE_WEB_FRAME);
   2642 
   2643     /*
   2644      * DOM-related signals. These signals are experimental, for now,
   2645      * and may change API and ABI. Their comments lack one * on
   2646      * purpose, to make them not be catched by gtk-doc.
   2647      */
   2648 
   2649     /*
   2650      * WebKitWebView::document-load-finished
   2651      * @webView: the object which received the signal
   2652      * @web_frame: the #WebKitWebFrame whose load dispatched this request
   2653      *
   2654      * Emitted when the DOM document object load is finished for the
   2655      * given frame.
   2656      */
   2657     webkit_web_view_signals[DOCUMENT_LOAD_FINISHED] = g_signal_new("document-load-finished",
   2658             G_TYPE_FROM_CLASS(webViewClass),
   2659             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2660             0,
   2661             NULL, NULL,
   2662             g_cclosure_marshal_VOID__OBJECT,
   2663             G_TYPE_NONE, 1,
   2664             WEBKIT_TYPE_WEB_FRAME);
   2665 
   2666     /*
   2667      * WebKitWebView::frame-created
   2668      * @webView: the object which received the signal
   2669      * @web_frame: the #WebKitWebFrame which was just created.
   2670      *
   2671      * Emitted when a WebKitWebView has created a new frame. This signal will
   2672      * be emitted for all sub-frames created during page load. It will not be
   2673      * emitted for the main frame, which originates in the WebKitWebView constructor
   2674      * and may be accessed at any time using webkit_web_view_get_main_frame.
   2675      *
   2676      * Since: 1.3.4
   2677      */
   2678     webkit_web_view_signals[FRAME_CREATED] = g_signal_new("frame-created",
   2679             G_TYPE_FROM_CLASS(webViewClass),
   2680             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2681             0,
   2682             NULL, NULL,
   2683             g_cclosure_marshal_VOID__OBJECT,
   2684             G_TYPE_NONE, 1,
   2685             WEBKIT_TYPE_WEB_FRAME);
   2686 
   2687     webkit_web_view_signals[SHOULD_BEGIN_EDITING] = g_signal_new("should-begin-editing",
   2688         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2689         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2690         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_RANGE);
   2691 
   2692     webkit_web_view_signals[SHOULD_END_EDITING] = g_signal_new("should-end-editing", G_TYPE_FROM_CLASS(webViewClass),
   2693         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2694         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2695         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_RANGE);
   2696 
   2697     webkit_web_view_signals[SHOULD_INSERT_NODE] = g_signal_new("should-insert-node", G_TYPE_FROM_CLASS(webViewClass),
   2698         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2699         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2700         webkit_marshal_BOOLEAN__OBJECT_OBJECT_ENUM, G_TYPE_BOOLEAN,
   2701         3, WEBKIT_TYPE_DOM_NODE, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_INSERT_ACTION);
   2702 
   2703     webkit_web_view_signals[SHOULD_INSERT_TEXT] = g_signal_new("should-insert-text", G_TYPE_FROM_CLASS(webViewClass),
   2704         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2705         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2706         webkit_marshal_BOOLEAN__STRING_OBJECT_ENUM, G_TYPE_BOOLEAN,
   2707         3, G_TYPE_STRING, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_INSERT_ACTION);
   2708 
   2709     webkit_web_view_signals[SHOULD_DELETE_RANGE] = g_signal_new("should-delete-range", G_TYPE_FROM_CLASS(webViewClass),
   2710         static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2711         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2712         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_RANGE);
   2713 
   2714     webkit_web_view_signals[SHOULD_SHOW_DELETE_INTERFACE_FOR_ELEMENT] = g_signal_new("should-show-delete-interface-for-element",
   2715         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2716         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2717         webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_HTML_ELEMENT);
   2718 
   2719     webkit_web_view_signals[SHOULD_CHANGE_SELECTED_RANGE] = g_signal_new("should-change-selected-range",
   2720         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2721         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2722         webkit_marshal_BOOLEAN__OBJECT_OBJECT_ENUM_BOOLEAN, G_TYPE_BOOLEAN,
   2723          4, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_DOM_RANGE, WEBKIT_TYPE_SELECTION_AFFINITY, G_TYPE_BOOLEAN);
   2724 
   2725     webkit_web_view_signals[SHOULD_APPLY_STYLE] = g_signal_new("should-apply-style",
   2726         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2727         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
   2728         webkit_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN,
   2729          2, WEBKIT_TYPE_DOM_CSS_STYLE_DECLARATION, WEBKIT_TYPE_DOM_RANGE);
   2730 
   2731     webkit_web_view_signals[EDITING_BEGAN] = g_signal_new("editing-began",
   2732         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
   2733         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
   2734 
   2735     webkit_web_view_signals[USER_CHANGED_CONTENTS] = g_signal_new("user-changed-contents",
   2736         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
   2737         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
   2738 
   2739     webkit_web_view_signals[EDITING_ENDED] = g_signal_new("editing-ended",
   2740         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
   2741         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
   2742 
   2743     webkit_web_view_signals[SELECTION_CHANGED] = g_signal_new("selection-changed",
   2744         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, 0, 0,
   2745         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
   2746 
   2747     /*
   2748      * WebKitWebView::viewport-attributes-recompute-requested
   2749      * @web_view: the object which received the signal
   2750      * @viewport_attributes: the #WebKitViewportAttributes which has the viewport attributes.
   2751      *
   2752      * The #WebKitWebView::viewport-attributes-recompute-requested
   2753      * signal will be emitted when a page with a viewport meta tag
   2754      * loads and when webkit_viewport_attributes_recompute is called.
   2755      *
   2756      * The #WebKitViewportAttributes will have device size, available size,
   2757      * desktop width, and device DPI pre-filled by values that make sense
   2758      * for the current screen and widget, but you can override those values
   2759      * if you have special requirements (for instance, if you made your
   2760      * widget bigger than the available visible area, you should override
   2761      * the available-width and available-height properties to the actual
   2762      * visible area).
   2763      *
   2764      * Since: 1.3.8
   2765      */
   2766     webkit_web_view_signals[VIEWPORT_ATTRIBUTES_RECOMPUTE_REQUESTED] = g_signal_new("viewport-attributes-recompute-requested",
   2767             G_TYPE_FROM_CLASS(webViewClass),
   2768             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2769             0,
   2770             0, 0,
   2771             g_cclosure_marshal_VOID__OBJECT,
   2772             G_TYPE_NONE, 1,
   2773             WEBKIT_TYPE_VIEWPORT_ATTRIBUTES);
   2774 
   2775     /*
   2776      * WebKitWebView::viewport-attributes-changed
   2777      * @web_view: the object which received the signal
   2778      * @viewport_attributes: the #WebKitViewportAttributes which has the viewport attributes.
   2779      *
   2780      * The #WebKitWebView::viewport-attributes-changed signal will be emitted
   2781      * after the emission of #WebKitWebView::viewport-attributes-recompute-requested
   2782      * and the subsequent viewport attribute recomputation. At this point,
   2783      * if the #WebKitViewportAttributes are valid, the viewport attributes are available.
   2784      *
   2785      * Since: 1.3.8
   2786      */
   2787     webkit_web_view_signals[VIEWPORT_ATTRIBUTES_CHANGED] = g_signal_new("viewport-attributes-changed",
   2788             G_TYPE_FROM_CLASS(webViewClass),
   2789             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2790             0,
   2791             0, 0,
   2792             g_cclosure_marshal_VOID__OBJECT,
   2793             G_TYPE_NONE, 1,
   2794             WEBKIT_TYPE_VIEWPORT_ATTRIBUTES);
   2795 
   2796     /*
   2797      * implementations of virtual methods
   2798      */
   2799     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
   2800     webViewClass->web_view_ready = webkit_web_view_real_web_view_ready;
   2801     webViewClass->close_web_view = webkit_web_view_real_close_web_view;
   2802     webViewClass->navigation_requested = webkit_web_view_real_navigation_requested;
   2803     webViewClass->window_object_cleared = webkit_web_view_real_window_object_cleared;
   2804     webViewClass->choose_file = webkit_web_view_real_choose_file;
   2805     webViewClass->script_alert = webkit_web_view_real_script_alert;
   2806     webViewClass->script_confirm = webkit_web_view_real_script_confirm;
   2807     webViewClass->script_prompt = webkit_web_view_real_script_prompt;
   2808     webViewClass->console_message = webkit_web_view_real_console_message;
   2809     webViewClass->select_all = webkit_web_view_real_select_all;
   2810     webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard;
   2811     webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard;
   2812     webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard;
   2813     webViewClass->undo = webkit_web_view_real_undo;
   2814     webViewClass->redo = webkit_web_view_real_redo;
   2815     webViewClass->move_cursor = webkit_web_view_real_move_cursor;
   2816     webViewClass->should_allow_editing_action = webkit_web_view_real_should_allow_editing_action;
   2817 
   2818     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
   2819     objectClass->dispose = webkit_web_view_dispose;
   2820     objectClass->finalize = webkit_web_view_finalize;
   2821     objectClass->get_property = webkit_web_view_get_property;
   2822     objectClass->set_property = webkit_web_view_set_property;
   2823 
   2824     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webViewClass);
   2825     widgetClass->realize = webkit_web_view_realize;
   2826 #ifdef GTK_API_VERSION_2
   2827     widgetClass->expose_event = webkit_web_view_expose_event;
   2828 #else
   2829     widgetClass->draw = webkit_web_view_draw;
   2830 #endif
   2831     widgetClass->key_press_event = webkit_web_view_key_press_event;
   2832     widgetClass->key_release_event = webkit_web_view_key_release_event;
   2833     widgetClass->button_press_event = webkit_web_view_button_press_event;
   2834     widgetClass->button_release_event = webkit_web_view_button_release_event;
   2835     widgetClass->motion_notify_event = webkit_web_view_motion_event;
   2836     widgetClass->scroll_event = webkit_web_view_scroll_event;
   2837     widgetClass->size_allocate = webkit_web_view_size_allocate;
   2838 #ifdef GTK_API_VERSION_2
   2839     widgetClass->size_request = webkit_web_view_size_request;
   2840 #else
   2841     widgetClass->get_preferred_width = webkit_web_view_get_preferred_width;
   2842     widgetClass->get_preferred_height = webkit_web_view_get_preferred_height;
   2843 #endif
   2844     widgetClass->popup_menu = webkit_web_view_popup_menu_handler;
   2845     widgetClass->grab_focus = webkit_web_view_grab_focus;
   2846     widgetClass->focus_in_event = webkit_web_view_focus_in_event;
   2847     widgetClass->focus_out_event = webkit_web_view_focus_out_event;
   2848     widgetClass->get_accessible = webkit_web_view_get_accessible;
   2849     widgetClass->screen_changed = webkit_web_view_screen_changed;
   2850     widgetClass->drag_end = webkit_web_view_drag_end;
   2851     widgetClass->drag_data_get = webkit_web_view_drag_data_get;
   2852     widgetClass->drag_motion = webkit_web_view_drag_motion;
   2853     widgetClass->drag_leave = webkit_web_view_drag_leave;
   2854     widgetClass->drag_drop = webkit_web_view_drag_drop;
   2855     widgetClass->drag_data_received = webkit_web_view_drag_data_received;
   2856 #if GTK_CHECK_VERSION(2, 12, 0)
   2857     widgetClass->query_tooltip = webkit_web_view_query_tooltip;
   2858     widgetClass->show_help = webkit_web_view_show_help;
   2859 #endif
   2860 
   2861     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
   2862     containerClass->add = webkit_web_view_container_add;
   2863     containerClass->remove = webkit_web_view_container_remove;
   2864     containerClass->forall = webkit_web_view_container_forall;
   2865 
   2866     /*
   2867      * make us scrollable (e.g. addable to a GtkScrolledWindow)
   2868      */
   2869 #ifdef GTK_API_VERSION_2
   2870     webViewClass->set_scroll_adjustments = webkit_web_view_set_scroll_adjustments;
   2871     GTK_WIDGET_CLASS(webViewClass)->set_scroll_adjustments_signal = g_signal_new("set-scroll-adjustments",
   2872             G_TYPE_FROM_CLASS(webViewClass),
   2873             (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
   2874             G_STRUCT_OFFSET(WebKitWebViewClass, set_scroll_adjustments),
   2875             NULL, NULL,
   2876             webkit_marshal_VOID__OBJECT_OBJECT,
   2877             G_TYPE_NONE, 2,
   2878             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
   2879 #else
   2880     g_object_class_override_property(objectClass, PROP_HADJUSTMENT, "hadjustment");
   2881     g_object_class_override_property(objectClass, PROP_VADJUSTMENT, "vadjustment");
   2882     g_object_class_override_property(objectClass, PROP_HSCROLL_POLICY, "hscroll-policy");
   2883     g_object_class_override_property(objectClass, PROP_VSCROLL_POLICY, "vscroll-policy");
   2884 #endif
   2885 
   2886     /*
   2887      * Key bindings
   2888      */
   2889 
   2890     binding_set = gtk_binding_set_by_class(webViewClass);
   2891 
   2892     gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
   2893                                  "select_all", 0);
   2894 
   2895     /* Cut/copy/paste */
   2896 
   2897     gtk_binding_entry_add_signal(binding_set, GDK_x, GDK_CONTROL_MASK,
   2898                                  "cut_clipboard", 0);
   2899     gtk_binding_entry_add_signal(binding_set, GDK_c, GDK_CONTROL_MASK,
   2900                                  "copy_clipboard", 0);
   2901     gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK,
   2902                                  "paste_clipboard", 0);
   2903     gtk_binding_entry_add_signal(binding_set, GDK_z, GDK_CONTROL_MASK,
   2904                                  "undo", 0);
   2905     gtk_binding_entry_add_signal(binding_set, GDK_z, static_cast<GdkModifierType>(GDK_CONTROL_MASK | GDK_SHIFT_MASK),
   2906                                  "redo", 0);
   2907 
   2908     gtk_binding_entry_add_signal(binding_set, GDK_Delete, GDK_SHIFT_MASK,
   2909                                  "cut_clipboard", 0);
   2910     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_CONTROL_MASK,
   2911                                  "copy_clipboard", 0);
   2912     gtk_binding_entry_add_signal(binding_set, GDK_Insert, GDK_SHIFT_MASK,
   2913                                  "paste_clipboard", 0);
   2914 
   2915     /* Movement */
   2916 
   2917     gtk_binding_entry_add_signal(binding_set, GDK_Down, static_cast<GdkModifierType>(0),
   2918                                  "move-cursor", 2,
   2919                                  G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINES,
   2920                                  G_TYPE_INT, 1);
   2921     gtk_binding_entry_add_signal(binding_set, GDK_Up, static_cast<GdkModifierType>(0),
   2922                                  "move-cursor", 2,
   2923                                  G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINES,
   2924                                  G_TYPE_INT, -1);
   2925     gtk_binding_entry_add_signal(binding_set, GDK_Right, static_cast<GdkModifierType>(0),
   2926                                  "move-cursor", 2,
   2927                                  G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
   2928                                  G_TYPE_INT, 1);
   2929     gtk_binding_entry_add_signal(binding_set, GDK_Left, static_cast<GdkModifierType>(0),
   2930                                  "move-cursor", 2,
   2931                                  G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
   2932                                  G_TYPE_INT, -1);
   2933     gtk_binding_entry_add_signal(binding_set, GDK_space, static_cast<GdkModifierType>(0),
   2934                                  "move-cursor", 2,
   2935                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
   2936                                  G_TYPE_INT, 1);
   2937     gtk_binding_entry_add_signal(binding_set, GDK_space, GDK_SHIFT_MASK,
   2938                                  "move-cursor", 2,
   2939                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
   2940                                  G_TYPE_INT, -1);
   2941     gtk_binding_entry_add_signal(binding_set, GDK_Page_Down, static_cast<GdkModifierType>(0),
   2942                                  "move-cursor", 2,
   2943                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
   2944                                  G_TYPE_INT, 1);
   2945     gtk_binding_entry_add_signal(binding_set, GDK_Page_Up, static_cast<GdkModifierType>(0),
   2946                                  "move-cursor", 2,
   2947                                  G_TYPE_ENUM, GTK_MOVEMENT_PAGES,
   2948                                  G_TYPE_INT, -1);
   2949     gtk_binding_entry_add_signal(binding_set, GDK_End, static_cast<GdkModifierType>(0),
   2950                                  "move-cursor", 2,
   2951                                  G_TYPE_ENUM, GTK_MOVEMENT_BUFFER_ENDS,
   2952                                  G_TYPE_INT, 1);
   2953     gtk_binding_entry_add_signal(binding_set, GDK_Home, static_cast<GdkModifierType>(0),
   2954                                  "move-cursor", 2,
   2955                                  G_TYPE_ENUM, GTK_MOVEMENT_BUFFER_ENDS,
   2956                                  G_TYPE_INT, -1);
   2957 
   2958     /*
   2959      * properties
   2960      */
   2961 
   2962     /**
   2963     * WebKitWebView:title:
   2964     *
   2965     * Returns the @web_view's document title.
   2966     *
   2967     * Since: 1.1.4
   2968     */
   2969     g_object_class_install_property(objectClass, PROP_TITLE,
   2970                                     g_param_spec_string("title",
   2971                                                         _("Title"),
   2972                                                         _("Returns the @web_view's document title"),
   2973                                                         NULL,
   2974                                                         WEBKIT_PARAM_READABLE));
   2975 
   2976     /**
   2977     * WebKitWebView:uri:
   2978     *
   2979     * Returns the current URI of the contents displayed by the @web_view.
   2980     *
   2981     * Since: 1.1.4
   2982     */
   2983     g_object_class_install_property(objectClass, PROP_URI,
   2984                                     g_param_spec_string("uri",
   2985                                                         _("URI"),
   2986                                                         _("Returns the current URI of the contents displayed by the @web_view"),
   2987                                                         NULL,
   2988                                                         WEBKIT_PARAM_READABLE));
   2989 
   2990     /**
   2991     * WebKitWebView:copy-target-list:
   2992     *
   2993     * The list of targets this web view supports for clipboard copying.
   2994     *
   2995     * Since: 1.0.2
   2996     */
   2997     g_object_class_install_property(objectClass, PROP_COPY_TARGET_LIST,
   2998                                     g_param_spec_boxed("copy-target-list",
   2999                                                        _("Copy target list"),
   3000                                                        _("The list of targets this web view supports for clipboard copying"),
   3001                                                        GTK_TYPE_TARGET_LIST,
   3002                                                        WEBKIT_PARAM_READABLE));
   3003 
   3004     /**
   3005     * WebKitWebView:paste-target-list:
   3006     *
   3007     * The list of targets this web view supports for clipboard pasting.
   3008     *
   3009     * Since: 1.0.2
   3010     */
   3011     g_object_class_install_property(objectClass, PROP_PASTE_TARGET_LIST,
   3012                                     g_param_spec_boxed("paste-target-list",
   3013                                                        _("Paste target list"),
   3014                                                        _("The list of targets this web view supports for clipboard pasting"),
   3015                                                        GTK_TYPE_TARGET_LIST,
   3016                                                        WEBKIT_PARAM_READABLE));
   3017 
   3018     g_object_class_install_property(objectClass, PROP_SETTINGS,
   3019                                     g_param_spec_object("settings",
   3020                                                         _("Settings"),
   3021                                                         _("An associated WebKitWebSettings instance"),
   3022                                                         WEBKIT_TYPE_WEB_SETTINGS,
   3023                                                         WEBKIT_PARAM_READWRITE));
   3024 
   3025     /**
   3026     * WebKitWebView:web-inspector:
   3027     *
   3028     * The associated WebKitWebInspector instance.
   3029     *
   3030     * Since: 1.0.3
   3031     */
   3032     g_object_class_install_property(objectClass, PROP_WEB_INSPECTOR,
   3033                                     g_param_spec_object("web-inspector",
   3034                                                         _("Web Inspector"),
   3035                                                         _("The associated WebKitWebInspector instance"),
   3036                                                         WEBKIT_TYPE_WEB_INSPECTOR,
   3037                                                         WEBKIT_PARAM_READABLE));
   3038 
   3039     /**
   3040     * WebKitWebView:viewport-attributes:
   3041     *
   3042     * The associated #WebKitViewportAttributes instance.
   3043     *
   3044     * Since: 1.3.8
   3045     */
   3046     g_object_class_install_property(objectClass, PROP_VIEWPORT_ATTRIBUTES,
   3047                                     g_param_spec_object("viewport-attributes",
   3048                                                         _("Viewport Attributes"),
   3049                                                         _("The associated WebKitViewportAttributes instance"),
   3050                                                         WEBKIT_TYPE_VIEWPORT_ATTRIBUTES,
   3051                                                         WEBKIT_PARAM_READABLE));
   3052 
   3053     /**
   3054     * WebKitWebView:window-features:
   3055     *
   3056     * An associated WebKitWebWindowFeatures instance.
   3057     *
   3058     * Since: 1.0.3
   3059     */
   3060     g_object_class_install_property(objectClass, PROP_WINDOW_FEATURES,
   3061                                     g_param_spec_object("window-features",
   3062                                                         "Window Features",
   3063                                                         "An associated WebKitWebWindowFeatures instance",
   3064                                                         WEBKIT_TYPE_WEB_WINDOW_FEATURES,
   3065                                                         WEBKIT_PARAM_READWRITE));
   3066 
   3067     g_object_class_install_property(objectClass, PROP_EDITABLE,
   3068                                     g_param_spec_boolean("editable",
   3069                                                          _("Editable"),
   3070                                                          _("Whether content can be modified by the user"),
   3071                                                          FALSE,
   3072                                                          WEBKIT_PARAM_READWRITE));
   3073 
   3074     g_object_class_install_property(objectClass, PROP_TRANSPARENT,
   3075                                     g_param_spec_boolean("transparent",
   3076                                                          _("Transparent"),
   3077                                                          _("Whether content has a transparent background"),
   3078                                                          FALSE,
   3079                                                          WEBKIT_PARAM_READWRITE));
   3080 
   3081     /**
   3082     * WebKitWebView:zoom-level:
   3083     *
   3084     * The level of zoom of the content.
   3085     *
   3086     * Since: 1.0.1
   3087     */
   3088     g_object_class_install_property(objectClass, PROP_ZOOM_LEVEL,
   3089                                     g_param_spec_float("zoom-level",
   3090                                                        _("Zoom level"),
   3091                                                        _("The level of zoom of the content"),
   3092                                                        G_MINFLOAT,
   3093                                                        G_MAXFLOAT,
   3094                                                        1.0f,
   3095                                                        WEBKIT_PARAM_READWRITE));
   3096 
   3097     /**
   3098     * WebKitWebView:full-content-zoom:
   3099     *
   3100     * Whether the full content is scaled when zooming.
   3101     *
   3102     * Since: 1.0.1
   3103     */
   3104     g_object_class_install_property(objectClass, PROP_FULL_CONTENT_ZOOM,
   3105                                     g_param_spec_boolean("full-content-zoom",
   3106                                                          _("Full content zoom"),
   3107                                                          _("Whether the full content is scaled when zooming"),
   3108                                                          FALSE,
   3109                                                          WEBKIT_PARAM_READWRITE));
   3110 
   3111     /**
   3112      * WebKitWebView:encoding:
   3113      *
   3114      * The default encoding of the web view.
   3115      *
   3116      * Since: 1.1.2
   3117      */
   3118     g_object_class_install_property(objectClass, PROP_ENCODING,
   3119                                     g_param_spec_string("encoding",
   3120                                                         _("Encoding"),
   3121                                                         _("The default encoding of the web view"),
   3122                                                         NULL,
   3123                                                         WEBKIT_PARAM_READABLE));
   3124 
   3125     /**
   3126      * WebKitWebView:custom-encoding:
   3127      *
   3128      * The custom encoding of the web view.
   3129      *
   3130      * Since: 1.1.2
   3131      */
   3132     g_object_class_install_property(objectClass, PROP_CUSTOM_ENCODING,
   3133                                     g_param_spec_string("custom-encoding",
   3134                                                         _("Custom Encoding"),
   3135                                                         _("The custom encoding of the web view"),
   3136                                                         NULL,
   3137                                                         WEBKIT_PARAM_READWRITE));
   3138 
   3139     /**
   3140     * WebKitWebView:load-status:
   3141     *
   3142     * Determines the current status of the load.
   3143     *
   3144     * Connect to "notify::load-status" to monitor loading.
   3145     *
   3146     * Some versions of WebKitGTK+ emitted this signal for the default
   3147     * error page, while loading it. This behavior was considered bad,
   3148     * because it was essentially exposing an implementation
   3149     * detail. From 1.1.19 onwards this signal is no longer emitted for
   3150     * the default error pages, but keep in mind that if you override
   3151     * the error pages by using webkit_web_frame_load_alternate_string()
   3152     * the signals will be emitted.
   3153     *
   3154     * Since: 1.1.7
   3155     */
   3156     g_object_class_install_property(objectClass, PROP_LOAD_STATUS,
   3157                                     g_param_spec_enum("load-status",
   3158                                                       "Load Status",
   3159                                                       "Determines the current status of the load",
   3160                                                       WEBKIT_TYPE_LOAD_STATUS,
   3161                                                       WEBKIT_LOAD_FINISHED,
   3162                                                       WEBKIT_PARAM_READABLE));
   3163 
   3164     /**
   3165     * WebKitWebView:progress:
   3166     *
   3167     * Determines the current progress of the load.
   3168     *
   3169     * Since: 1.1.7
   3170     */
   3171     g_object_class_install_property(objectClass, PROP_PROGRESS,
   3172                                     g_param_spec_double("progress",
   3173                                                         "Progress",
   3174                                                         "Determines the current progress of the load",
   3175                                                         0.0, 1.0, 1.0,
   3176                                                         WEBKIT_PARAM_READABLE));
   3177 
   3178     /**
   3179      * WebKitWebView:icon-uri:
   3180      *
   3181      * The URI for the favicon for the #WebKitWebView.
   3182      *
   3183      * Since: 1.1.18
   3184      */
   3185     g_object_class_install_property(objectClass, PROP_ICON_URI,
   3186                                     g_param_spec_string("icon-uri",
   3187                                                         _("Icon URI"),
   3188                                                         _("The URI for the favicon for the #WebKitWebView."),
   3189                                                         NULL,
   3190                                                         WEBKIT_PARAM_READABLE));
   3191     /**
   3192     * WebKitWebView:im-context:
   3193     *
   3194     * The GtkIMMulticontext for the #WebKitWebView.
   3195     *
   3196     * This is the input method context used for all text entry widgets inside
   3197     * the #WebKitWebView. It can be used to generate context menu items for
   3198     * controlling the active input method.
   3199     *
   3200     * Since: 1.1.20
   3201     */
   3202     g_object_class_install_property(objectClass, PROP_IM_CONTEXT,
   3203                                     g_param_spec_object("im-context",
   3204                                                         "IM Context",
   3205                                                         "The GtkIMMultiContext for the #WebKitWebView.",
   3206                                                         GTK_TYPE_IM_CONTEXT,
   3207                                                         WEBKIT_PARAM_READABLE));
   3208 
   3209     /**
   3210     * WebKitWebView:view-mode:
   3211     *
   3212     * The "view-mode" media feature for the #WebKitWebView.
   3213     *
   3214     * The "view-mode" media feature is additional information for web
   3215     * applications about how the application is running, when it comes
   3216     * to user experience. Whether the application is running inside a
   3217     * regular browser window, in a dedicated window, fullscreen, for
   3218     * instance.
   3219     *
   3220     * This property stores a %WebKitWebViewViewMode value that matches
   3221     * the "view-mode" media feature the web application will see.
   3222     *
   3223     * See http://www.w3.org/TR/view-mode/ for more information.
   3224     *
   3225     * Since: 1.3.4
   3226     */
   3227     g_object_class_install_property(objectClass, PROP_VIEW_MODE,
   3228                                     g_param_spec_enum("view-mode",
   3229                                                       "View Mode",
   3230                                                       "The view-mode media feature for the #WebKitWebView.",
   3231                                                       WEBKIT_TYPE_WEB_VIEW_VIEW_MODE,
   3232                                                       WEBKIT_WEB_VIEW_VIEW_MODE_WINDOWED,
   3233                                                       WEBKIT_PARAM_READWRITE));
   3234 
   3235     g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
   3236 }
   3237 
   3238 static void webkit_web_view_update_settings(WebKitWebView* webView)
   3239 {
   3240     WebKitWebViewPrivate* priv = webView->priv;
   3241     WebKitWebSettings* webSettings = priv->webSettings.get();
   3242     Settings* settings = core(webView)->settings();
   3243 
   3244     gchar* defaultEncoding, *cursiveFontFamily, *defaultFontFamily, *fantasyFontFamily, *monospaceFontFamily, *sansSerifFontFamily, *serifFontFamily, *userStylesheetUri, *defaultSpellCheckingLanguages;
   3245     gboolean autoLoadImages, autoShrinkImages, printBackgrounds,
   3246         enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas,
   3247         enablePrivateBrowsing, enableCaretBrowsing, enableHTML5Database, enableHTML5LocalStorage,
   3248         enableXSSAuditor, enableSpatialNavigation, enableFrameFlattening, javascriptCanOpenWindows,
   3249         javaScriptCanAccessClipboard, enableOfflineWebAppCache,
   3250         enableUniversalAccessFromFileURI, enableFileAccessFromFileURI,
   3251         enableDOMPaste, tabKeyCyclesThroughElements, enableWebGL,
   3252         enableSiteSpecificQuirks, usePageCache, enableJavaApplet,
   3253         enableHyperlinkAuditing, enableFullscreen, enableDNSPrefetching;
   3254 
   3255     WebKitEditingBehavior editingBehavior;
   3256 
   3257     g_object_get(webSettings,
   3258                  "default-encoding", &defaultEncoding,
   3259                  "cursive-font-family", &cursiveFontFamily,
   3260                  "default-font-family", &defaultFontFamily,
   3261                  "fantasy-font-family", &fantasyFontFamily,
   3262                  "monospace-font-family", &monospaceFontFamily,
   3263                  "sans-serif-font-family", &sansSerifFontFamily,
   3264                  "serif-font-family", &serifFontFamily,
   3265                  "auto-load-images", &autoLoadImages,
   3266                  "auto-shrink-images", &autoShrinkImages,
   3267                  "print-backgrounds", &printBackgrounds,
   3268                  "enable-scripts", &enableScripts,
   3269                  "enable-plugins", &enablePlugins,
   3270                  "resizable-text-areas", &resizableTextAreas,
   3271                  "user-stylesheet-uri", &userStylesheetUri,
   3272                  "enable-developer-extras", &enableDeveloperExtras,
   3273                  "enable-private-browsing", &enablePrivateBrowsing,
   3274                  "enable-caret-browsing", &enableCaretBrowsing,
   3275                  "enable-html5-database", &enableHTML5Database,
   3276                  "enable-html5-local-storage", &enableHTML5LocalStorage,
   3277                  "enable-xss-auditor", &enableXSSAuditor,
   3278                  "enable-spatial-navigation", &enableSpatialNavigation,
   3279                  "enable-frame-flattening", &enableFrameFlattening,
   3280                  "javascript-can-open-windows-automatically", &javascriptCanOpenWindows,
   3281                  "javascript-can-access-clipboard", &javaScriptCanAccessClipboard,
   3282                  "enable-offline-web-application-cache", &enableOfflineWebAppCache,
   3283                  "editing-behavior", &editingBehavior,
   3284                  "enable-universal-access-from-file-uris", &enableUniversalAccessFromFileURI,
   3285                  "enable-file-access-from-file-uris", &enableFileAccessFromFileURI,
   3286                  "enable-dom-paste", &enableDOMPaste,
   3287                  "tab-key-cycles-through-elements", &tabKeyCyclesThroughElements,
   3288                  "enable-site-specific-quirks", &enableSiteSpecificQuirks,
   3289                  "enable-page-cache", &usePageCache,
   3290                  "enable-java-applet", &enableJavaApplet,
   3291                  "enable-hyperlink-auditing", &enableHyperlinkAuditing,
   3292                  "spell-checking-languages", &defaultSpellCheckingLanguages,
   3293                  "enable-fullscreen", &enableFullscreen,
   3294                  "enable-dns-prefetching", &enableDNSPrefetching,
   3295                  "enable-webgl", &enableWebGL,
   3296                  NULL);
   3297 
   3298     settings->setDefaultTextEncodingName(defaultEncoding);
   3299     settings->setCursiveFontFamily(cursiveFontFamily);
   3300     settings->setStandardFontFamily(defaultFontFamily);
   3301     settings->setFantasyFontFamily(fantasyFontFamily);
   3302     settings->setFixedFontFamily(monospaceFontFamily);
   3303     settings->setSansSerifFontFamily(sansSerifFontFamily);
   3304     settings->setSerifFontFamily(serifFontFamily);
   3305     settings->setLoadsImagesAutomatically(autoLoadImages);
   3306     settings->setShrinksStandaloneImagesToFit(autoShrinkImages);
   3307     settings->setShouldPrintBackgrounds(printBackgrounds);
   3308     settings->setJavaScriptEnabled(enableScripts);
   3309     settings->setPluginsEnabled(enablePlugins);
   3310     settings->setTextAreasAreResizable(resizableTextAreas);
   3311     settings->setUserStyleSheetLocation(KURL(KURL(), userStylesheetUri));
   3312     settings->setDeveloperExtrasEnabled(enableDeveloperExtras);
   3313     settings->setPrivateBrowsingEnabled(enablePrivateBrowsing);
   3314     settings->setCaretBrowsingEnabled(enableCaretBrowsing);
   3315 #if ENABLE(DATABASE)
   3316     AbstractDatabase::setIsAvailable(enableHTML5Database);
   3317 #endif
   3318     settings->setLocalStorageEnabled(enableHTML5LocalStorage);
   3319     settings->setXSSAuditorEnabled(enableXSSAuditor);
   3320     settings->setSpatialNavigationEnabled(enableSpatialNavigation);
   3321     settings->setFrameFlatteningEnabled(enableFrameFlattening);
   3322     settings->setJavaScriptCanOpenWindowsAutomatically(javascriptCanOpenWindows);
   3323     settings->setJavaScriptCanAccessClipboard(javaScriptCanAccessClipboard);
   3324     settings->setOfflineWebApplicationCacheEnabled(enableOfflineWebAppCache);
   3325     settings->setEditingBehaviorType(static_cast<WebCore::EditingBehaviorType>(editingBehavior));
   3326     settings->setAllowUniversalAccessFromFileURLs(enableUniversalAccessFromFileURI);
   3327     settings->setAllowFileAccessFromFileURLs(enableFileAccessFromFileURI);
   3328     settings->setDOMPasteAllowed(enableDOMPaste);
   3329     settings->setNeedsSiteSpecificQuirks(enableSiteSpecificQuirks);
   3330     settings->setUsesPageCache(usePageCache);
   3331     settings->setJavaEnabled(enableJavaApplet);
   3332     settings->setHyperlinkAuditingEnabled(enableHyperlinkAuditing);
   3333     settings->setDNSPrefetchingEnabled(enableDNSPrefetching);
   3334 
   3335 #if ENABLE(FULLSCREEN_API)
   3336     settings->setFullScreenEnabled(enableFullscreen);
   3337 #endif
   3338 
   3339 #if ENABLE(SPELLCHECK)
   3340     WebKit::EditorClient* client = static_cast<WebKit::EditorClient*>(core(webView)->editorClient());
   3341     static_cast<WebKit::TextCheckerClientEnchant*>(client->textChecker())->updateSpellCheckingLanguage(defaultSpellCheckingLanguages);
   3342 #endif
   3343 
   3344 #if ENABLE(WEBGL)
   3345     settings->setWebGLEnabled(enableWebGL);
   3346 #endif
   3347 
   3348     Page* page = core(webView);
   3349     if (page)
   3350         page->setTabKeyCyclesThroughElements(tabKeyCyclesThroughElements);
   3351 
   3352     g_free(defaultEncoding);
   3353     g_free(cursiveFontFamily);
   3354     g_free(defaultFontFamily);
   3355     g_free(fantasyFontFamily);
   3356     g_free(monospaceFontFamily);
   3357     g_free(sansSerifFontFamily);
   3358     g_free(serifFontFamily);
   3359     g_free(userStylesheetUri);
   3360 
   3361     webkit_web_view_screen_changed(GTK_WIDGET(webView), NULL);
   3362 }
   3363 
   3364 static inline gint pixelsFromSize(WebKitWebView* webView, gint size)
   3365 {
   3366     gdouble DPI = webViewGetDPI(webView);
   3367     return size / 72.0 * DPI;
   3368 }
   3369 
   3370 static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView)
   3371 {
   3372     Settings* settings = core(webView)->settings();
   3373 
   3374     const gchar* name = g_intern_string(pspec->name);
   3375     GValue value = { 0, { { 0 } } };
   3376     g_value_init(&value, pspec->value_type);
   3377     g_object_get_property(G_OBJECT(webSettings), name, &value);
   3378 
   3379     if (name == g_intern_string("default-encoding"))
   3380         settings->setDefaultTextEncodingName(g_value_get_string(&value));
   3381     else if (name == g_intern_string("cursive-font-family"))
   3382         settings->setCursiveFontFamily(g_value_get_string(&value));
   3383     else if (name == g_intern_string("default-font-family"))
   3384         settings->setStandardFontFamily(g_value_get_string(&value));
   3385     else if (name == g_intern_string("fantasy-font-family"))
   3386         settings->setFantasyFontFamily(g_value_get_string(&value));
   3387     else if (name == g_intern_string("monospace-font-family"))
   3388         settings->setFixedFontFamily(g_value_get_string(&value));
   3389     else if (name == g_intern_string("sans-serif-font-family"))
   3390         settings->setSansSerifFontFamily(g_value_get_string(&value));
   3391     else if (name == g_intern_string("serif-font-family"))
   3392         settings->setSerifFontFamily(g_value_get_string(&value));
   3393     else if (name == g_intern_string("default-font-size"))
   3394         settings->setDefaultFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
   3395     else if (name == g_intern_string("default-monospace-font-size"))
   3396         settings->setDefaultFixedFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
   3397     else if (name == g_intern_string("minimum-font-size"))
   3398         settings->setMinimumFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
   3399     else if (name == g_intern_string("minimum-logical-font-size"))
   3400         settings->setMinimumLogicalFontSize(pixelsFromSize(webView, g_value_get_int(&value)));
   3401     else if (name == g_intern_string("enforce-96-dpi"))
   3402         webkit_web_view_screen_changed(GTK_WIDGET(webView), NULL);
   3403     else if (name == g_intern_string("auto-load-images"))
   3404         settings->setLoadsImagesAutomatically(g_value_get_boolean(&value));
   3405     else if (name == g_intern_string("auto-shrink-images"))
   3406         settings->setShrinksStandaloneImagesToFit(g_value_get_boolean(&value));
   3407     else if (name == g_intern_string("print-backgrounds"))
   3408         settings->setShouldPrintBackgrounds(g_value_get_boolean(&value));
   3409     else if (name == g_intern_string("enable-scripts"))
   3410         settings->setJavaScriptEnabled(g_value_get_boolean(&value));
   3411     else if (name == g_intern_string("enable-plugins"))
   3412         settings->setPluginsEnabled(g_value_get_boolean(&value));
   3413     else if (name == g_intern_string("enable-dns-prefetching"))
   3414         settings->setDNSPrefetchingEnabled(g_value_get_boolean(&value));
   3415     else if (name == g_intern_string("resizable-text-areas"))
   3416         settings->setTextAreasAreResizable(g_value_get_boolean(&value));
   3417     else if (name == g_intern_string("user-stylesheet-uri"))
   3418         settings->setUserStyleSheetLocation(KURL(KURL(), g_value_get_string(&value)));
   3419     else if (name == g_intern_string("enable-developer-extras"))
   3420         settings->setDeveloperExtrasEnabled(g_value_get_boolean(&value));
   3421     else if (name == g_intern_string("enable-private-browsing"))
   3422         settings->setPrivateBrowsingEnabled(g_value_get_boolean(&value));
   3423     else if (name == g_intern_string("enable-caret-browsing"))
   3424         settings->setCaretBrowsingEnabled(g_value_get_boolean(&value));
   3425 #if ENABLE(DATABASE)
   3426     else if (name == g_intern_string("enable-html5-database")) {
   3427         AbstractDatabase::setIsAvailable(g_value_get_boolean(&value));
   3428     }
   3429 #endif
   3430     else if (name == g_intern_string("enable-html5-local-storage"))
   3431         settings->setLocalStorageEnabled(g_value_get_boolean(&value));
   3432     else if (name == g_intern_string("enable-xss-auditor"))
   3433         settings->setXSSAuditorEnabled(g_value_get_boolean(&value));
   3434     else if (name == g_intern_string("enable-spatial-navigation"))
   3435         settings->setSpatialNavigationEnabled(g_value_get_boolean(&value));
   3436     else if (name == g_intern_string("enable-frame-flattening"))
   3437         settings->setFrameFlatteningEnabled(g_value_get_boolean(&value));
   3438     else if (name == g_intern_string("javascript-can-open-windows-automatically"))
   3439         settings->setJavaScriptCanOpenWindowsAutomatically(g_value_get_boolean(&value));
   3440     else if (name == g_intern_string("javascript-can-access-clipboard"))
   3441         settings->setJavaScriptCanAccessClipboard(g_value_get_boolean(&value));
   3442     else if (name == g_intern_string("enable-offline-web-application-cache"))
   3443         settings->setOfflineWebApplicationCacheEnabled(g_value_get_boolean(&value));
   3444     else if (name == g_intern_string("editing-behavior"))
   3445         settings->setEditingBehaviorType(static_cast<WebCore::EditingBehaviorType>(g_value_get_enum(&value)));
   3446     else if (name == g_intern_string("enable-universal-access-from-file-uris"))
   3447         settings->setAllowUniversalAccessFromFileURLs(g_value_get_boolean(&value));
   3448     else if (name == g_intern_string("enable-file-access-from-file-uris"))
   3449         settings->setAllowFileAccessFromFileURLs(g_value_get_boolean(&value));
   3450     else if (name == g_intern_string("enable-dom-paste"))
   3451         settings->setDOMPasteAllowed(g_value_get_boolean(&value));
   3452     else if (name == g_intern_string("tab-key-cycles-through-elements")) {
   3453         Page* page = core(webView);
   3454         if (page)
   3455             page->setTabKeyCyclesThroughElements(g_value_get_boolean(&value));
   3456     } else if (name == g_intern_string("enable-site-specific-quirks"))
   3457         settings->setNeedsSiteSpecificQuirks(g_value_get_boolean(&value));
   3458     else if (name == g_intern_string("enable-page-cache"))
   3459         settings->setUsesPageCache(g_value_get_boolean(&value));
   3460     else if (name == g_intern_string("enable-java-applet"))
   3461         settings->setJavaEnabled(g_value_get_boolean(&value));
   3462     else if (name == g_intern_string("enable-hyperlink-auditing"))
   3463         settings->setHyperlinkAuditingEnabled(g_value_get_boolean(&value));
   3464 
   3465 #if ENABLE(SPELLCHECK)
   3466     else if (name == g_intern_string("spell-checking-languages")) {
   3467         WebKit::EditorClient* client = static_cast<WebKit::EditorClient*>(core(webView)->editorClient());
   3468         static_cast<WebKit::TextCheckerClientEnchant*>(client->textChecker())->updateSpellCheckingLanguage(g_value_get_string(&value));
   3469     }
   3470 #endif
   3471 
   3472 #if ENABLE(WEBGL)
   3473     else if (name == g_intern_string("enable-webgl"))
   3474         settings->setWebGLEnabled(g_value_get_boolean(&value));
   3475 #endif
   3476 
   3477     else if (!g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), name))
   3478         g_warning("Unexpected setting '%s'", name);
   3479     g_value_unset(&value);
   3480 }
   3481 
   3482 static void webkit_web_view_init(WebKitWebView* webView)
   3483 {
   3484     WebKitWebViewPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(webView, WEBKIT_TYPE_WEB_VIEW, WebKitWebViewPrivate);
   3485     webView->priv = priv;
   3486     // This is the placement new syntax: http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10
   3487     // It allows us to call a constructor on manually allocated locations in memory. We must use it
   3488     // in this case, because GLib manages the memory for the private data section, but we wish it
   3489     // to contain C++ object members. The use of placement new calls the constructor on all C++ data
   3490     // members, which ensures they are initialized properly.
   3491     new (priv) WebKitWebViewPrivate();
   3492 
   3493     priv->imContext = adoptGRef(gtk_im_multicontext_new());
   3494 
   3495     Page::PageClients pageClients;
   3496     pageClients.chromeClient = new WebKit::ChromeClient(webView);
   3497     pageClients.contextMenuClient = new WebKit::ContextMenuClient(webView);
   3498     pageClients.editorClient = new WebKit::EditorClient(webView);
   3499     pageClients.dragClient = new WebKit::DragClient(webView);
   3500     pageClients.inspectorClient = new WebKit::InspectorClient(webView);
   3501     priv->corePage = new Page(pageClients);
   3502 
   3503     // Pages within a same session need to be linked together otherwise some functionalities such
   3504     // as visited link coloration (across pages) and changing popup window location will not work.
   3505     // To keep the default behavior simple (and because no PageGroup API exist in WebKitGTK at the
   3506     // time of writing this comment), we simply set all the pages to the same group.
   3507     priv->corePage->setGroupName("org.webkit.gtk.WebKitGTK");
   3508 
   3509     // We also add a simple wrapper class to provide the public
   3510     // interface for the Web Inspector.
   3511     priv->webInspector = adoptGRef(WEBKIT_WEB_INSPECTOR(g_object_new(WEBKIT_TYPE_WEB_INSPECTOR, NULL)));
   3512     webkit_web_inspector_set_inspector_client(priv->webInspector.get(), priv->corePage);
   3513 
   3514     // And our ViewportAttributes friend.
   3515     priv->viewportAttributes = adoptGRef(WEBKIT_VIEWPORT_ATTRIBUTES(g_object_new(WEBKIT_TYPE_VIEWPORT_ATTRIBUTES, NULL)));
   3516     priv->viewportAttributes->priv->webView = webView;
   3517 
   3518     // The smart pointer will call g_object_ref_sink on these adjustments.
   3519     priv->horizontalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
   3520     priv->verticalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
   3521 
   3522     gtk_widget_set_can_focus(GTK_WIDGET(webView), TRUE);
   3523     priv->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
   3524     priv->lastPopupXPosition = priv->lastPopupYPosition = -1;
   3525 
   3526     priv->backForwardList = adoptGRef(webkit_web_back_forward_list_new_with_web_view(webView));
   3527 
   3528     priv->zoomFullContent = FALSE;
   3529 
   3530     priv->webSettings = adoptGRef(webkit_web_settings_new());
   3531     webkit_web_view_update_settings(webView);
   3532     g_signal_connect(priv->webSettings.get(), "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
   3533 
   3534     priv->webWindowFeatures = adoptGRef(webkit_web_window_features_new());
   3535 
   3536     priv->subResources = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref));
   3537 
   3538     priv->currentClickCount = 0;
   3539     priv->previousClickButton = 0;
   3540     priv->previousClickTime = 0;
   3541     gtk_drag_dest_set(GTK_WIDGET(webView), static_cast<GtkDestDefaults>(0), 0, 0, static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
   3542     gtk_drag_dest_set_target_list(GTK_WIDGET(webView), pasteboardHelperInstance()->targetList());
   3543 }
   3544 
   3545 GtkWidget* webkit_web_view_new(void)
   3546 {
   3547     WebKitWebView* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
   3548 
   3549     return GTK_WIDGET(webView);
   3550 }
   3551 
   3552 // for internal use only
   3553 void webkit_web_view_notify_ready(WebKitWebView* webView)
   3554 {
   3555     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3556 
   3557     gboolean isHandled = FALSE;
   3558     g_signal_emit(webView, webkit_web_view_signals[WEB_VIEW_READY], 0, &isHandled);
   3559 }
   3560 
   3561 void webkit_web_view_request_download(WebKitWebView* webView, WebKitNetworkRequest* request, const ResourceResponse& response, ResourceHandle* handle)
   3562 {
   3563     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3564 
   3565     WebKitDownload* download;
   3566 
   3567     if (handle)
   3568         download = webkit_download_new_with_handle(request, handle, response);
   3569     else
   3570         download = webkit_download_new(request);
   3571 
   3572     gboolean handled;
   3573     g_signal_emit(webView, webkit_web_view_signals[DOWNLOAD_REQUESTED], 0, download, &handled);
   3574 
   3575     if (!handled) {
   3576         webkit_download_cancel(download);
   3577         g_object_unref(download);
   3578         return;
   3579     }
   3580 
   3581     /* Start the download now if it has a destination URI, otherwise it
   3582         may be handled asynchronously by the application. */
   3583     if (webkit_download_get_destination_uri(download))
   3584         webkit_download_start(download);
   3585 }
   3586 
   3587 bool webkit_web_view_use_primary_for_paste(WebKitWebView* webView)
   3588 {
   3589     return webView->priv->usePrimaryForPaste;
   3590 }
   3591 
   3592 /**
   3593  * webkit_web_view_set_settings:
   3594  * @webView: a #WebKitWebView
   3595  * @settings: (transfer none): the #WebKitWebSettings to be set
   3596  *
   3597  * Replaces the #WebKitWebSettings instance that is currently attached
   3598  * to @web_view with @settings. The reference held by the @web_view on
   3599  * the old #WebKitWebSettings instance is dropped, and the reference
   3600  * count of @settings is inscreased.
   3601  *
   3602  * The settings are automatically applied to @web_view.
   3603  */
   3604 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitWebSettings* webSettings)
   3605 {
   3606     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3607     g_return_if_fail(WEBKIT_IS_WEB_SETTINGS(webSettings));
   3608 
   3609     WebKitWebViewPrivate* priv = webView->priv;
   3610     g_signal_handlers_disconnect_by_func(priv->webSettings.get(), (gpointer)webkit_web_view_settings_notify, webView);
   3611     priv->webSettings = webSettings;
   3612     webkit_web_view_update_settings(webView);
   3613     g_signal_connect(webSettings, "notify", G_CALLBACK(webkit_web_view_settings_notify), webView);
   3614     g_object_notify(G_OBJECT(webView), "settings");
   3615 }
   3616 
   3617 /**
   3618  * webkit_web_view_get_settings:
   3619  * @webView: a #WebKitWebView
   3620  *
   3621  * Obtains the #WebKitWebSettings associated with the
   3622  * #WebKitWebView. The #WebKitWebView always has an associated
   3623  * instance of #WebKitWebSettings. The reference that is returned by
   3624  * this call is owned by the #WebKitWebView. You may need to increase
   3625  * its reference count if you intend to keep it alive for longer than
   3626  * the #WebKitWebView.
   3627  *
   3628  * Return value: (transfer none): the #WebKitWebSettings instance
   3629  */
   3630 WebKitWebSettings* webkit_web_view_get_settings(WebKitWebView* webView)
   3631 {
   3632     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   3633     return webView->priv->webSettings.get();
   3634 }
   3635 
   3636 /**
   3637  * webkit_web_view_get_inspector:
   3638  * @webView: a #WebKitWebView
   3639  *
   3640  * Obtains the #WebKitWebInspector associated with the
   3641  * #WebKitWebView. Every #WebKitWebView object has a
   3642  * #WebKitWebInspector object attached to it as soon as it is created,
   3643  * so this function will only return NULL if the argument is not a
   3644  * valid #WebKitWebView.
   3645  *
   3646  * Return value: (transfer none): the #WebKitWebInspector instance.
   3647  *
   3648  * Since: 1.0.3
   3649  */
   3650 WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
   3651 {
   3652     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   3653     return webView->priv->webInspector.get();
   3654 }
   3655 
   3656 /**
   3657  * webkit_web_view_get_viewport_attributes:
   3658  * @webView: a #WebKitWebView
   3659  *
   3660  * Obtains the #WebKitViewportAttributes associated with the
   3661  * #WebKitWebView. Every #WebKitWebView object has a
   3662  * #WebKitWebViewporAttributes object attached to it as soon as it is
   3663  * created, so this function will only return NULL if the argument is
   3664  * not a valid #WebKitWebView. Do note however that the viewport
   3665  * attributes object only contains valid information when the current
   3666  * page has a viewport meta tag. You can check whether the data should
   3667  * be used by checking the #WebKitViewport:valid property.
   3668  *
   3669  * Return value: (transfer none): the #WebKitViewportAttributes instance.
   3670  *
   3671  * Since: 1.3.8
   3672  */
   3673 WebKitViewportAttributes* webkit_web_view_get_viewport_attributes(WebKitWebView* webView)
   3674 {
   3675     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   3676     return webView->priv->viewportAttributes.get();
   3677 }
   3678 
   3679 // internal
   3680 static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures)
   3681 {
   3682     if (!webWindowFeatures)
   3683       return;
   3684     if (webkit_web_window_features_equal(webView->priv->webWindowFeatures.get(), webWindowFeatures))
   3685       return;
   3686     webView->priv->webWindowFeatures = webWindowFeatures;
   3687 }
   3688 
   3689 /**
   3690  * webkit_web_view_get_window_features:
   3691  * @webView: a #WebKitWebView
   3692  *
   3693  * Returns the instance of #WebKitWebWindowFeatures held by the given
   3694  * #WebKitWebView.
   3695  *
   3696  * Return value: (transfer none): the #WebKitWebWindowFeatures
   3697  *
   3698  * Since: 1.0.3
   3699  */
   3700 WebKitWebWindowFeatures* webkit_web_view_get_window_features(WebKitWebView* webView)
   3701 {
   3702     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   3703     return webView->priv->webWindowFeatures.get();
   3704 }
   3705 
   3706 /**
   3707  * webkit_web_view_get_title:
   3708  * @webView: a #WebKitWebView
   3709  *
   3710  * Returns the @web_view's document title
   3711  *
   3712  * Since: 1.1.4
   3713  *
   3714  * Return value: the title of @web_view
   3715  */
   3716 G_CONST_RETURN gchar* webkit_web_view_get_title(WebKitWebView* webView)
   3717 {
   3718     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   3719 
   3720     WebKitWebViewPrivate* priv = webView->priv;
   3721     return priv->mainFrame->priv->title;
   3722 }
   3723 
   3724 /**
   3725  * webkit_web_view_get_uri:
   3726  * @webView: a #WebKitWebView
   3727  *
   3728  * Returns the current URI of the contents displayed by the @web_view
   3729  *
   3730  * Since: 1.1.4
   3731  *
   3732  * Return value: the URI of @web_view
   3733  */
   3734 G_CONST_RETURN gchar* webkit_web_view_get_uri(WebKitWebView* webView)
   3735 {
   3736     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   3737 
   3738     WebKitWebViewPrivate* priv = webView->priv;
   3739     return priv->mainFrame->priv->uri;
   3740 }
   3741 
   3742 /**
   3743  * webkit_web_view_set_maintains_back_forward_list:
   3744  * @webView: a #WebKitWebView
   3745  * @flag: to tell the view to maintain a back or forward list
   3746  *
   3747  * Set the view to maintain a back or forward list of history items.
   3748  */
   3749 void webkit_web_view_set_maintains_back_forward_list(WebKitWebView* webView, gboolean flag)
   3750 {
   3751     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3752 
   3753     static_cast<BackForwardListImpl*>(core(webView)->backForwardList())->setEnabled(flag);
   3754 }
   3755 
   3756 /**
   3757  * webkit_web_view_get_back_forward_list:
   3758  * @webView: a #WebKitWebView
   3759  *
   3760  * Obtains the #WebKitWebBackForwardList associated with the given #WebKitWebView. The
   3761  * #WebKitWebBackForwardList is owned by the #WebKitWebView.
   3762  *
   3763  * Return value: (transfer none): the #WebKitWebBackForwardList
   3764  */
   3765 WebKitWebBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
   3766 {
   3767     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   3768     if (!core(webView) || !static_cast<BackForwardListImpl*>(core(webView)->backForwardList())->enabled())
   3769         return 0;
   3770     return webView->priv->backForwardList.get();
   3771 }
   3772 
   3773 /**
   3774  * webkit_web_view_go_to_back_forward_item:
   3775  * @webView: a #WebKitWebView
   3776  * @item: a #WebKitWebHistoryItem*
   3777  *
   3778  * Go to the specified #WebKitWebHistoryItem
   3779  *
   3780  * Return value: %TRUE if loading of item is successful, %FALSE if not
   3781  */
   3782 gboolean webkit_web_view_go_to_back_forward_item(WebKitWebView* webView, WebKitWebHistoryItem* item)
   3783 {
   3784     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   3785     g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(item), FALSE);
   3786 
   3787     WebKitWebBackForwardList* backForwardList = webkit_web_view_get_back_forward_list(webView);
   3788     if (!webkit_web_back_forward_list_contains_item(backForwardList, item))
   3789         return FALSE;
   3790 
   3791     core(webView)->goToItem(core(item), FrameLoadTypeIndexedBackForward);
   3792     return TRUE;
   3793 }
   3794 
   3795 /**
   3796  * webkit_web_view_go_back:
   3797  * @webView: a #WebKitWebView
   3798  *
   3799  * Loads the previous history item.
   3800  */
   3801 void webkit_web_view_go_back(WebKitWebView* webView)
   3802 {
   3803     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3804 
   3805     core(webView)->goBack();
   3806 }
   3807 
   3808 /**
   3809  * webkit_web_view_go_back_or_forward:
   3810  * @webView: a #WebKitWebView
   3811  * @steps: the number of steps
   3812  *
   3813  * Loads the history item that is the number of @steps away from the current
   3814  * item. Negative values represent steps backward while positive values
   3815  * represent steps forward.
   3816  */
   3817 void webkit_web_view_go_back_or_forward(WebKitWebView* webView, gint steps)
   3818 {
   3819     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3820 
   3821     core(webView)->goBackOrForward(steps);
   3822 }
   3823 
   3824 /**
   3825  * webkit_web_view_go_forward:
   3826  * @webView: a #WebKitWebView
   3827  *
   3828  * Loads the next history item.
   3829  */
   3830 void webkit_web_view_go_forward(WebKitWebView* webView)
   3831 {
   3832     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3833 
   3834     core(webView)->goForward();
   3835 }
   3836 
   3837 /**
   3838  * webkit_web_view_can_go_back:
   3839  * @webView: a #WebKitWebView
   3840  *
   3841  * Determines whether #web_view has a previous history item.
   3842  *
   3843  * Return value: %TRUE if able to move back, %FALSE otherwise
   3844  */
   3845 gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
   3846 {
   3847     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   3848 
   3849     if (!core(webView) || !core(webView)->backForwardList()->backItem())
   3850         return FALSE;
   3851 
   3852     return TRUE;
   3853 }
   3854 
   3855 /**
   3856  * webkit_web_view_can_go_back_or_forward:
   3857  * @webView: a #WebKitWebView
   3858  * @steps: the number of steps
   3859  *
   3860  * Determines whether #web_view has a history item of @steps. Negative values
   3861  * represent steps backward while positive values represent steps forward.
   3862  *
   3863  * Return value: %TRUE if able to move back or forward the given number of
   3864  * steps, %FALSE otherwise
   3865  */
   3866 gboolean webkit_web_view_can_go_back_or_forward(WebKitWebView* webView, gint steps)
   3867 {
   3868     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   3869 
   3870     return core(webView)->canGoBackOrForward(steps);
   3871 }
   3872 
   3873 /**
   3874  * webkit_web_view_can_go_forward:
   3875  * @webView: a #WebKitWebView
   3876  *
   3877  * Determines whether #web_view has a next history item.
   3878  *
   3879  * Return value: %TRUE if able to move forward, %FALSE otherwise
   3880  */
   3881 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
   3882 {
   3883     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   3884 
   3885     Page* page = core(webView);
   3886 
   3887     if (!page)
   3888         return FALSE;
   3889 
   3890     if (!page->backForwardList()->forwardItem())
   3891         return FALSE;
   3892 
   3893     return TRUE;
   3894 }
   3895 
   3896 /**
   3897  * webkit_web_view_open:
   3898  * @webView: a #WebKitWebView
   3899  * @uri: an URI
   3900  *
   3901  * Requests loading of the specified URI string.
   3902  *
   3903  * Deprecated: 1.1.1: Use webkit_web_view_load_uri() instead.
   3904   */
   3905 void webkit_web_view_open(WebKitWebView* webView, const gchar* uri)
   3906 {
   3907     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3908     g_return_if_fail(uri);
   3909 
   3910     // We used to support local paths, unlike the newer
   3911     // function webkit_web_view_load_uri
   3912     if (g_path_is_absolute(uri)) {
   3913         gchar* fileUri = g_filename_to_uri(uri, NULL, NULL);
   3914         webkit_web_view_load_uri(webView, fileUri);
   3915         g_free(fileUri);
   3916     }
   3917     else
   3918         webkit_web_view_load_uri(webView, uri);
   3919 }
   3920 
   3921 void webkit_web_view_reload(WebKitWebView* webView)
   3922 {
   3923     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3924 
   3925     core(webView)->mainFrame()->loader()->reload();
   3926 }
   3927 
   3928 /**
   3929  * webkit_web_view_reload_bypass_cache:
   3930  * @webView: a #WebKitWebView
   3931  *
   3932  * Reloads the @web_view without using any cached data.
   3933  *
   3934  * Since: 1.0.3
   3935  */
   3936 void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
   3937 {
   3938     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3939 
   3940     core(webView)->mainFrame()->loader()->reload(true);
   3941 }
   3942 
   3943 /**
   3944  * webkit_web_view_load_uri:
   3945  * @webView: a #WebKitWebView
   3946  * @uri: an URI string
   3947  *
   3948  * Requests loading of the specified URI string.
   3949  *
   3950  * Since: 1.1.1
   3951  */
   3952 void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
   3953 {
   3954     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3955     g_return_if_fail(uri);
   3956 
   3957     WebKitWebFrame* frame = webView->priv->mainFrame;
   3958     webkit_web_frame_load_uri(frame, uri);
   3959 }
   3960 
   3961 /**
   3962   * webkit_web_view_load_string:
   3963   * @webView: a #WebKitWebView
   3964   * @content: an URI string
   3965   * @mime_type: the MIME type, or %NULL
   3966   * @encoding: the encoding, or %NULL
   3967   * @base_uri: the base URI for relative locations
   3968   *
   3969   * Requests loading of the given @content with the specified @mime_type,
   3970   * @encoding and @base_uri.
   3971   *
   3972   * If @mime_type is %NULL, "text/html" is assumed.
   3973   *
   3974   * If @encoding is %NULL, "UTF-8" is assumed.
   3975   */
   3976 void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* mimeType, const gchar* encoding, const gchar* baseUri)
   3977 {
   3978     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3979     g_return_if_fail(content);
   3980 
   3981     WebKitWebFrame* frame = webView->priv->mainFrame;
   3982     webkit_web_frame_load_string(frame, content, mimeType, encoding, baseUri);
   3983 }
   3984 /**
   3985  * webkit_web_view_load_html_string:
   3986  * @webView: a #WebKitWebView
   3987  * @content: an URI string
   3988  * @base_uri: the base URI for relative locations
   3989  *
   3990  * Requests loading of the given @content with the specified @base_uri.
   3991  *
   3992  * Deprecated: 1.1.1: Use webkit_web_view_load_string() instead.
   3993  */
   3994 void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* content, const gchar* baseUri)
   3995 {
   3996     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   3997     g_return_if_fail(content);
   3998 
   3999     webkit_web_view_load_string(webView, content, NULL, NULL, baseUri);
   4000 }
   4001 
   4002 /**
   4003  * webkit_web_view_load_request:
   4004  * @webView: a #WebKitWebView
   4005  * @request: a #WebKitNetworkRequest
   4006  *
   4007  * Requests loading of the specified asynchronous client request.
   4008  *
   4009  * Creates a provisional data source that will transition to a committed data
   4010  * source once any data has been received. Use webkit_web_view_stop_loading() to
   4011  * stop the load.
   4012  *
   4013  * Since: 1.1.1
   4014  */
   4015 void webkit_web_view_load_request(WebKitWebView* webView, WebKitNetworkRequest* request)
   4016 {
   4017     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4018     g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request));
   4019 
   4020     WebKitWebFrame* frame = webView->priv->mainFrame;
   4021     webkit_web_frame_load_request(frame, request);
   4022 }
   4023 
   4024 /**
   4025  * webkit_web_view_stop_loading:
   4026  * @webView: a #WebKitWebView
   4027  *
   4028  * Stops any ongoing load in the @webView.
   4029  **/
   4030 void webkit_web_view_stop_loading(WebKitWebView* webView)
   4031 {
   4032     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4033 
   4034     Frame* frame = core(webView)->mainFrame();
   4035 
   4036     if (FrameLoader* loader = frame->loader())
   4037         loader->stopForUserCancel();
   4038 }
   4039 
   4040 /**
   4041  * webkit_web_view_search_text:
   4042  * @webView: a #WebKitWebView
   4043  * @text: a string to look for
   4044  * @forward: whether to find forward or not
   4045  * @case_sensitive: whether to respect the case of text
   4046  * @wrap: whether to continue looking at the beginning after reaching the end
   4047  *
   4048  * Looks for a specified string inside #web_view.
   4049  *
   4050  * Return value: %TRUE on success or %FALSE on failure
   4051  */
   4052 gboolean webkit_web_view_search_text(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, gboolean forward, gboolean shouldWrap)
   4053 {
   4054     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4055     g_return_val_if_fail(string, FALSE);
   4056 
   4057     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
   4058     FindDirection direction = forward ? FindDirectionForward : FindDirectionBackward;
   4059 
   4060     return core(webView)->findString(String::fromUTF8(string), caseSensitivity, direction, shouldWrap);
   4061 }
   4062 
   4063 /**
   4064  * webkit_web_view_mark_text_matches:
   4065  * @webView: a #WebKitWebView
   4066  * @string: a string to look for
   4067  * @case_sensitive: whether to respect the case of text
   4068  * @limit: the maximum number of strings to look for or 0 for all
   4069  *
   4070  * Attempts to highlight all occurances of #string inside #web_view.
   4071  *
   4072  * Return value: the number of strings highlighted
   4073  */
   4074 guint webkit_web_view_mark_text_matches(WebKitWebView* webView, const gchar* string, gboolean caseSensitive, guint limit)
   4075 {
   4076     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   4077     g_return_val_if_fail(string, 0);
   4078 
   4079     TextCaseSensitivity caseSensitivity = caseSensitive ? TextCaseSensitive : TextCaseInsensitive;
   4080 
   4081     return core(webView)->markAllMatchesForText(String::fromUTF8(string), caseSensitivity, false, limit);
   4082 }
   4083 
   4084 /**
   4085  * webkit_web_view_set_highlight_text_matches:
   4086  * @webView: a #WebKitWebView
   4087  * @highlight: whether to highlight text matches
   4088  *
   4089  * Highlights text matches previously marked by webkit_web_view_mark_text_matches.
   4090  */
   4091 void webkit_web_view_set_highlight_text_matches(WebKitWebView* webView, gboolean shouldHighlight)
   4092 {
   4093     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4094 
   4095     Frame *frame = core(webView)->mainFrame();
   4096     do {
   4097         frame->editor()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
   4098         frame = frame->tree()->traverseNextWithWrap(false);
   4099     } while (frame);
   4100 }
   4101 
   4102 /**
   4103  * webkit_web_view_unmark_text_matches:
   4104  * @webView: a #WebKitWebView
   4105  *
   4106  * Removes highlighting previously set by webkit_web_view_mark_text_matches.
   4107  */
   4108 void webkit_web_view_unmark_text_matches(WebKitWebView* webView)
   4109 {
   4110     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4111 
   4112     return core(webView)->unmarkAllTextMatches();
   4113 }
   4114 
   4115 /**
   4116  * webkit_web_view_get_main_frame:
   4117  * @webView: a #WebKitWebView
   4118  *
   4119  * Returns the main frame for the @webView.
   4120  *
   4121  * Return value: (transfer none): the main #WebKitWebFrame for @webView
   4122  */
   4123 WebKitWebFrame* webkit_web_view_get_main_frame(WebKitWebView* webView)
   4124 {
   4125     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   4126 
   4127     return webView->priv->mainFrame;
   4128 }
   4129 
   4130 /**
   4131  * webkit_web_view_get_focused_frame:
   4132  * @webView: a #WebKitWebView
   4133  *
   4134  * Returns the frame that has focus or an active text selection.
   4135  *
   4136  * Return value: (transfer none): The focused #WebKitWebFrame or %NULL if no frame is focused
   4137  */
   4138 WebKitWebFrame* webkit_web_view_get_focused_frame(WebKitWebView* webView)
   4139 {
   4140     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   4141 
   4142     Frame* focusedFrame = core(webView)->focusController()->focusedFrame();
   4143     return kit(focusedFrame);
   4144 }
   4145 
   4146 void webkit_web_view_execute_script(WebKitWebView* webView, const gchar* script)
   4147 {
   4148     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4149     g_return_if_fail(script);
   4150 
   4151     core(webView)->mainFrame()->script()->executeScript(String::fromUTF8(script), true);
   4152 }
   4153 
   4154 /**
   4155  * webkit_web_view_can_cut_clipboard:
   4156  * @webView: a #WebKitWebView
   4157  *
   4158  * Determines whether or not it is currently possible to cut to the clipboard.
   4159  *
   4160  * Return value: %TRUE if a selection can be cut, %FALSE if not
   4161  */
   4162 gboolean webkit_web_view_can_cut_clipboard(WebKitWebView* webView)
   4163 {
   4164     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4165 
   4166     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4167     return frame->editor()->canCut() || frame->editor()->canDHTMLCut();
   4168 }
   4169 
   4170 /**
   4171  * webkit_web_view_can_copy_clipboard:
   4172  * @webView: a #WebKitWebView
   4173  *
   4174  * Determines whether or not it is currently possible to copy to the clipboard.
   4175  *
   4176  * Return value: %TRUE if a selection can be copied, %FALSE if not
   4177  */
   4178 gboolean webkit_web_view_can_copy_clipboard(WebKitWebView* webView)
   4179 {
   4180     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4181 
   4182     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4183     return frame->editor()->canCopy() || frame->editor()->canDHTMLCopy();
   4184 }
   4185 
   4186 /**
   4187  * webkit_web_view_can_paste_clipboard:
   4188  * @webView: a #WebKitWebView
   4189  *
   4190  * Determines whether or not it is currently possible to paste from the clipboard.
   4191  *
   4192  * Return value: %TRUE if a selection can be pasted, %FALSE if not
   4193  */
   4194 gboolean webkit_web_view_can_paste_clipboard(WebKitWebView* webView)
   4195 {
   4196     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4197 
   4198     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4199     return frame->editor()->canPaste() || frame->editor()->canDHTMLPaste();
   4200 }
   4201 
   4202 /**
   4203  * webkit_web_view_cut_clipboard:
   4204  * @webView: a #WebKitWebView
   4205  *
   4206  * Cuts the current selection inside the @web_view to the clipboard.
   4207  */
   4208 void webkit_web_view_cut_clipboard(WebKitWebView* webView)
   4209 {
   4210     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4211 
   4212     if (webkit_web_view_can_cut_clipboard(webView))
   4213         g_signal_emit(webView, webkit_web_view_signals[CUT_CLIPBOARD], 0);
   4214 }
   4215 
   4216 /**
   4217  * webkit_web_view_copy_clipboard:
   4218  * @webView: a #WebKitWebView
   4219  *
   4220  * Copies the current selection inside the @web_view to the clipboard.
   4221  */
   4222 void webkit_web_view_copy_clipboard(WebKitWebView* webView)
   4223 {
   4224     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4225 
   4226     if (webkit_web_view_can_copy_clipboard(webView))
   4227         g_signal_emit(webView, webkit_web_view_signals[COPY_CLIPBOARD], 0);
   4228 }
   4229 
   4230 /**
   4231  * webkit_web_view_paste_clipboard:
   4232  * @webView: a #WebKitWebView
   4233  *
   4234  * Pastes the current contents of the clipboard to the @web_view.
   4235  */
   4236 void webkit_web_view_paste_clipboard(WebKitWebView* webView)
   4237 {
   4238     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4239 
   4240     if (webkit_web_view_can_paste_clipboard(webView))
   4241         g_signal_emit(webView, webkit_web_view_signals[PASTE_CLIPBOARD], 0);
   4242 }
   4243 
   4244 /**
   4245  * webkit_web_view_delete_selection:
   4246  * @webView: a #WebKitWebView
   4247  *
   4248  * Deletes the current selection inside the @web_view.
   4249  */
   4250 void webkit_web_view_delete_selection(WebKitWebView* webView)
   4251 {
   4252     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4253 
   4254     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4255     frame->editor()->performDelete();
   4256 }
   4257 
   4258 /**
   4259  * webkit_web_view_has_selection:
   4260  * @webView: a #WebKitWebView
   4261  *
   4262  * Determines whether text was selected.
   4263  *
   4264  * Return value: %TRUE if there is selected text, %FALSE if not
   4265  */
   4266 gboolean webkit_web_view_has_selection(WebKitWebView* webView)
   4267 {
   4268     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4269 
   4270     return !core(webView)->selection().isNone();
   4271 }
   4272 
   4273 /**
   4274  * webkit_web_view_get_selected_text:
   4275  * @webView: a #WebKitWebView
   4276  *
   4277  * Retrieves the selected text if any.
   4278  *
   4279  * Return value: a newly allocated string with the selection or %NULL
   4280  */
   4281 gchar* webkit_web_view_get_selected_text(WebKitWebView* webView)
   4282 {
   4283     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   4284 
   4285     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4286     return g_strdup(frame->editor()->selectedText().utf8().data());
   4287 }
   4288 
   4289 /**
   4290  * webkit_web_view_select_all:
   4291  * @webView: a #WebKitWebView
   4292  *
   4293  * Attempts to select everything inside the @web_view.
   4294  */
   4295 void webkit_web_view_select_all(WebKitWebView* webView)
   4296 {
   4297     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4298 
   4299     g_signal_emit(webView, webkit_web_view_signals[SELECT_ALL], 0);
   4300 }
   4301 
   4302 /**
   4303  * webkit_web_view_get_editable:
   4304  * @webView: a #WebKitWebView
   4305  *
   4306  * Returns whether the user is allowed to edit the document.
   4307  *
   4308  * Returns %TRUE if @web_view allows the user to edit the HTML document, %FALSE if
   4309  * it doesn't. You can change @web_view's document programmatically regardless of
   4310  * this setting.
   4311  *
   4312  * Return value: a #gboolean indicating the editable state
   4313  */
   4314 gboolean webkit_web_view_get_editable(WebKitWebView* webView)
   4315 {
   4316     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4317 
   4318     return core(webView)->isEditable();
   4319 }
   4320 
   4321 /**
   4322  * webkit_web_view_set_editable:
   4323  * @webView: a #WebKitWebView
   4324  * @flag: a #gboolean indicating the editable state
   4325  *
   4326  * Sets whether @web_view allows the user to edit its HTML document.
   4327  *
   4328  * If @flag is %TRUE, @web_view allows the user to edit the document. If @flag is
   4329  * %FALSE, an element in @web_view's document can only be edited if the
   4330  * CONTENTEDITABLE attribute has been set on the element or one of its parent
   4331  * elements. You can change @web_view's document programmatically regardless of
   4332  * this setting. By default a #WebKitWebView is not editable.
   4333 
   4334  * Normally, an HTML document is not editable unless the elements within the
   4335  * document are editable. This function provides a low-level way to make the
   4336  * contents of a #WebKitWebView editable without altering the document or DOM
   4337  * structure.
   4338  */
   4339 void webkit_web_view_set_editable(WebKitWebView* webView, gboolean flag)
   4340 {
   4341     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4342 
   4343     flag = flag != FALSE;
   4344     if (flag == webkit_web_view_get_editable(webView))
   4345         return;
   4346 
   4347     core(webView)->setEditable(flag);
   4348 
   4349     Frame* frame = core(webView)->mainFrame();
   4350     g_return_if_fail(frame);
   4351 
   4352     if (flag) {
   4353         frame->editor()->applyEditingStyleToBodyElement();
   4354         // TODO: If the WebKitWebView is made editable and the selection is empty, set it to something.
   4355         //if (!webkit_web_view_get_selected_dom_range(webView))
   4356         //    mainFrame->setSelectionFromNone();
   4357     }
   4358     g_object_notify(G_OBJECT(webView), "editable");
   4359 }
   4360 
   4361 /**
   4362  * webkit_web_view_get_copy_target_list:
   4363  * @webView: a #WebKitWebView
   4364  *
   4365  * This function returns the list of targets this #WebKitWebView can
   4366  * provide for clipboard copying and as DND source. The targets in the list are
   4367  * added with values from the #WebKitWebViewTargetInfo enum,
   4368  * using gtk_target_list_add() and
   4369  * gtk_target_list_add_text_targets().
   4370  *
   4371  * Return value: the #GtkTargetList
   4372  **/
   4373 GtkTargetList* webkit_web_view_get_copy_target_list(WebKitWebView* webView)
   4374 {
   4375     return pasteboardHelperInstance()->targetList();
   4376 }
   4377 
   4378 /**
   4379  * webkit_web_view_get_paste_target_list:
   4380  * @webView: a #WebKitWebView
   4381  *
   4382  * This function returns the list of targets this #WebKitWebView can
   4383  * provide for clipboard pasting and as DND destination. The targets in the list are
   4384  * added with values from the #WebKitWebViewTargetInfo enum,
   4385  * using gtk_target_list_add() and
   4386  * gtk_target_list_add_text_targets().
   4387  *
   4388  * Return value: the #GtkTargetList
   4389  **/
   4390 GtkTargetList* webkit_web_view_get_paste_target_list(WebKitWebView* webView)
   4391 {
   4392     return pasteboardHelperInstance()->targetList();
   4393 }
   4394 
   4395 /**
   4396  * webkit_web_view_can_show_mime_type:
   4397  * @webView: a #WebKitWebView
   4398  * @mime_type: a MIME type
   4399  *
   4400  * This functions returns whether or not a MIME type can be displayed using this view.
   4401  *
   4402  * Return value: a #gboolean indicating if the MIME type can be displayed
   4403  *
   4404  * Since: 1.0.3
   4405  **/
   4406 
   4407 gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const gchar* mimeType)
   4408 {
   4409     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4410 
   4411     Frame* frame = core(webkit_web_view_get_main_frame(webView));
   4412     if (FrameLoader* loader = frame->loader())
   4413         return loader->canShowMIMEType(String::fromUTF8(mimeType));
   4414     else
   4415         return FALSE;
   4416 }
   4417 
   4418 /**
   4419  * webkit_web_view_get_transparent:
   4420  * @webView: a #WebKitWebView
   4421  *
   4422  * Returns whether the #WebKitWebView has a transparent background.
   4423  *
   4424  * Return value: %FALSE when the #WebKitWebView draws a solid background
   4425  * (the default), otherwise %TRUE.
   4426  */
   4427 gboolean webkit_web_view_get_transparent(WebKitWebView* webView)
   4428 {
   4429     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4430 
   4431     WebKitWebViewPrivate* priv = webView->priv;
   4432     return priv->transparent;
   4433 }
   4434 
   4435 /**
   4436  * webkit_web_view_set_transparent:
   4437  * @webView: a #WebKitWebView
   4438  *
   4439  * Sets whether the #WebKitWebView has a transparent background.
   4440  *
   4441  * Pass %FALSE to have the #WebKitWebView draw a solid background
   4442  * (the default), otherwise %TRUE.
   4443  */
   4444 void webkit_web_view_set_transparent(WebKitWebView* webView, gboolean flag)
   4445 {
   4446     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4447 
   4448     WebKitWebViewPrivate* priv = webView->priv;
   4449     priv->transparent = flag;
   4450 
   4451     // TODO: This needs to be made persistent or it could become a problem when
   4452     // the main frame is replaced.
   4453     Frame* frame = core(webView)->mainFrame();
   4454     g_return_if_fail(frame);
   4455     frame->view()->setTransparent(flag);
   4456     g_object_notify(G_OBJECT(webView), "transparent");
   4457 }
   4458 
   4459 /**
   4460  * webkit_web_view_get_zoom_level:
   4461  * @webView: a #WebKitWebView
   4462  *
   4463  * Returns the zoom level of @web_view, i.e. the factor by which elements in
   4464  * the page are scaled with respect to their original size.
   4465  * If the "full-content-zoom" property is set to %FALSE (the default)
   4466  * the zoom level changes the text size, or if %TRUE, scales all
   4467  * elements in the page.
   4468  *
   4469  * Return value: the zoom level of @web_view
   4470  *
   4471  * Since: 1.0.1
   4472  */
   4473 gfloat webkit_web_view_get_zoom_level(WebKitWebView* webView)
   4474 {
   4475     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1.0f);
   4476 
   4477     Frame* frame = core(webView)->mainFrame();
   4478     if (!frame)
   4479         return 1.0f;
   4480 
   4481     WebKitWebViewPrivate* priv = webView->priv;
   4482     return priv->zoomFullContent ? frame->pageZoomFactor() : frame->textZoomFactor();
   4483 }
   4484 
   4485 static void webkit_web_view_apply_zoom_level(WebKitWebView* webView, gfloat zoomLevel)
   4486 {
   4487     Frame* frame = core(webView)->mainFrame();
   4488     if (!frame)
   4489         return;
   4490 
   4491     WebKitWebViewPrivate* priv = webView->priv;
   4492     if (priv->zoomFullContent)
   4493         frame->setPageZoomFactor(zoomLevel);
   4494     else
   4495         frame->setTextZoomFactor(zoomLevel);
   4496 }
   4497 
   4498 /**
   4499  * webkit_web_view_set_zoom_level:
   4500  * @webView: a #WebKitWebView
   4501  * @zoom_level: the new zoom level
   4502  *
   4503  * Sets the zoom level of @web_view, i.e. the factor by which elements in
   4504  * the page are scaled with respect to their original size.
   4505  * If the "full-content-zoom" property is set to %FALSE (the default)
   4506  * the zoom level changes the text size, or if %TRUE, scales all
   4507  * elements in the page.
   4508  *
   4509  * Since: 1.0.1
   4510  */
   4511 void webkit_web_view_set_zoom_level(WebKitWebView* webView, gfloat zoomLevel)
   4512 {
   4513     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4514 
   4515     webkit_web_view_apply_zoom_level(webView, zoomLevel);
   4516     g_object_notify(G_OBJECT(webView), "zoom-level");
   4517 }
   4518 
   4519 /**
   4520  * webkit_web_view_zoom_in:
   4521  * @webView: a #WebKitWebView
   4522  *
   4523  * Increases the zoom level of @web_view. The current zoom
   4524  * level is incremented by the value of the "zoom-step"
   4525  * property of the #WebKitWebSettings associated with @web_view.
   4526  *
   4527  * Since: 1.0.1
   4528  */
   4529 void webkit_web_view_zoom_in(WebKitWebView* webView)
   4530 {
   4531     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4532 
   4533     WebKitWebViewPrivate* priv = webView->priv;
   4534     gfloat zoomMultiplierRatio;
   4535     g_object_get(priv->webSettings.get(), "zoom-step", &zoomMultiplierRatio, NULL);
   4536 
   4537     webkit_web_view_set_zoom_level(webView, webkit_web_view_get_zoom_level(webView) + zoomMultiplierRatio);
   4538 }
   4539 
   4540 /**
   4541  * webkit_web_view_zoom_out:
   4542  * @webView: a #WebKitWebView
   4543  *
   4544  * Decreases the zoom level of @web_view. The current zoom
   4545  * level is decremented by the value of the "zoom-step"
   4546  * property of the #WebKitWebSettings associated with @web_view.
   4547  *
   4548  * Since: 1.0.1
   4549  */
   4550 void webkit_web_view_zoom_out(WebKitWebView* webView)
   4551 {
   4552     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4553 
   4554     WebKitWebViewPrivate* priv = webView->priv;
   4555     gfloat zoomMultiplierRatio;
   4556     g_object_get(priv->webSettings.get(), "zoom-step", &zoomMultiplierRatio, NULL);
   4557 
   4558     webkit_web_view_set_zoom_level(webView, webkit_web_view_get_zoom_level(webView) - zoomMultiplierRatio);
   4559 }
   4560 
   4561 /**
   4562  * webkit_web_view_get_full_content_zoom:
   4563  * @webView: a #WebKitWebView
   4564  *
   4565  * Returns whether the zoom level affects only text or all elements.
   4566  *
   4567  * Return value: %FALSE if only text should be scaled (the default),
   4568  * %TRUE if the full content of the view should be scaled.
   4569  *
   4570  * Since: 1.0.1
   4571  */
   4572 gboolean webkit_web_view_get_full_content_zoom(WebKitWebView* webView)
   4573 {
   4574     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4575 
   4576     WebKitWebViewPrivate* priv = webView->priv;
   4577     return priv->zoomFullContent;
   4578 }
   4579 
   4580 /**
   4581  * webkit_web_view_set_full_content_zoom:
   4582  * @webView: a #WebKitWebView
   4583  * @full_content_zoom: %FALSE if only text should be scaled (the default),
   4584  * %TRUE if the full content of the view should be scaled.
   4585  *
   4586  * Sets whether the zoom level affects only text or all elements.
   4587  *
   4588  * Since: 1.0.1
   4589  */
   4590 void webkit_web_view_set_full_content_zoom(WebKitWebView* webView, gboolean zoomFullContent)
   4591 {
   4592     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4593 
   4594     WebKitWebViewPrivate* priv = webView->priv;
   4595     if (priv->zoomFullContent == zoomFullContent)
   4596       return;
   4597 
   4598     Frame* frame = core(webView)->mainFrame();
   4599     if (!frame)
   4600       return;
   4601 
   4602     gfloat zoomLevel = priv->zoomFullContent ? frame->pageZoomFactor() : frame->textZoomFactor();
   4603 
   4604     priv->zoomFullContent = zoomFullContent;
   4605     if (priv->zoomFullContent)
   4606         frame->setPageAndTextZoomFactors(zoomLevel, 1);
   4607     else
   4608         frame->setPageAndTextZoomFactors(1, zoomLevel);
   4609 
   4610     g_object_notify(G_OBJECT(webView), "full-content-zoom");
   4611 }
   4612 
   4613 /**
   4614  * webkit_web_view_get_load_status:
   4615  * @webView: a #WebKitWebView
   4616  *
   4617  * Determines the current status of the load.
   4618  *
   4619  * Since: 1.1.7
   4620  */
   4621 WebKitLoadStatus webkit_web_view_get_load_status(WebKitWebView* webView)
   4622 {
   4623     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), WEBKIT_LOAD_FINISHED);
   4624 
   4625     WebKitWebViewPrivate* priv = webView->priv;
   4626     return priv->loadStatus;
   4627 }
   4628 
   4629 /**
   4630  * webkit_web_view_get_progress:
   4631  * @webView: a #WebKitWebView
   4632  *
   4633  * Determines the current progress of the load.
   4634  *
   4635  * Since: 1.1.7
   4636  */
   4637 gdouble webkit_web_view_get_progress(WebKitWebView* webView)
   4638 {
   4639     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1.0);
   4640 
   4641     return core(webView)->progress()->estimatedProgress();
   4642 }
   4643 
   4644 /**
   4645  * webkit_web_view_get_encoding:
   4646  * @webView: a #WebKitWebView
   4647  *
   4648  * Returns the default encoding of the #WebKitWebView.
   4649  *
   4650  * Return value: the default encoding
   4651  *
   4652  * Since: 1.1.1
   4653  */
   4654 const gchar* webkit_web_view_get_encoding(WebKitWebView* webView)
   4655 {
   4656     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   4657     String encoding = core(webView)->mainFrame()->document()->loader()->writer()->encoding();
   4658     if (encoding.isEmpty())
   4659         return 0;
   4660     webView->priv->encoding = encoding.utf8();
   4661     return webView->priv->encoding.data();
   4662 }
   4663 
   4664 /**
   4665  * webkit_web_view_set_custom_encoding:
   4666  * @webView: a #WebKitWebView
   4667  * @encoding: the new encoding, or %NULL to restore the default encoding
   4668  *
   4669  * Sets the current #WebKitWebView encoding, without modifying the default one,
   4670  * and reloads the page.
   4671  *
   4672  * Since: 1.1.1
   4673  */
   4674 void webkit_web_view_set_custom_encoding(WebKitWebView* webView, const char* encoding)
   4675 {
   4676     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4677 
   4678     core(webView)->mainFrame()->loader()->reloadWithOverrideEncoding(String::fromUTF8(encoding));
   4679 }
   4680 
   4681 /**
   4682  * webkit_web_view_get_custom_encoding:
   4683  * @webView: a #WebKitWebView
   4684  *
   4685  * Returns the current encoding of the #WebKitWebView, not the default-encoding
   4686  * of WebKitWebSettings.
   4687  *
   4688  * Return value: a string containing the current custom encoding for @web_view, or %NULL if there's none set.
   4689  *
   4690  * Since: 1.1.1
   4691  */
   4692 const char* webkit_web_view_get_custom_encoding(WebKitWebView* webView)
   4693 {
   4694     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   4695     String overrideEncoding = core(webView)->mainFrame()->loader()->documentLoader()->overrideEncoding();
   4696     if (overrideEncoding.isEmpty())
   4697         return 0;
   4698     webView->priv->customEncoding = overrideEncoding.utf8();
   4699     return webView->priv->customEncoding.data();
   4700 }
   4701 
   4702 /**
   4703  * webkit_web_view_set_view_mode:
   4704  * @webView: the #WebKitWebView that will have its view mode set
   4705  * @mode: the %WebKitWebViewViewMode to be set
   4706  *
   4707  * Sets the view-mode property of the #WebKitWebView. Check the
   4708  * property's documentation for more information.
   4709  *
   4710  * Since: 1.3.4
   4711  */
   4712 void webkit_web_view_set_view_mode(WebKitWebView* webView, WebKitWebViewViewMode mode)
   4713 {
   4714     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4715 
   4716     Page* page = core(webView);
   4717 
   4718     switch (mode) {
   4719     case WEBKIT_WEB_VIEW_VIEW_MODE_FLOATING:
   4720         page->setViewMode(Page::ViewModeFloating);
   4721         break;
   4722     case WEBKIT_WEB_VIEW_VIEW_MODE_FULLSCREEN:
   4723         page->setViewMode(Page::ViewModeFullscreen);
   4724         break;
   4725     case WEBKIT_WEB_VIEW_VIEW_MODE_MAXIMIZED:
   4726         page->setViewMode(Page::ViewModeMaximized);
   4727         break;
   4728     case WEBKIT_WEB_VIEW_VIEW_MODE_MINIMIZED:
   4729         page->setViewMode(Page::ViewModeMinimized);
   4730         break;
   4731     default:
   4732         page->setViewMode(Page::ViewModeWindowed);
   4733         break;
   4734     }
   4735 }
   4736 
   4737 /**
   4738  * webkit_web_view_get_view_mode:
   4739  * @webView: the #WebKitWebView to obtain the view mode from
   4740  *
   4741  * Gets the value of the view-mode property of the
   4742  * #WebKitWebView. Check the property's documentation for more
   4743  * information.
   4744  *
   4745  * Return value: the %WebKitWebViewViewMode currently set for the
   4746  * #WebKitWebView.
   4747  *
   4748  * Since: 1.3.4
   4749  */
   4750 WebKitWebViewViewMode webkit_web_view_get_view_mode(WebKitWebView* webView)
   4751 {
   4752     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), WEBKIT_WEB_VIEW_VIEW_MODE_WINDOWED);
   4753 
   4754     Page* page = core(webView);
   4755     Page::ViewMode mode = page->viewMode();
   4756 
   4757     if (mode == Page::ViewModeFloating)
   4758         return WEBKIT_WEB_VIEW_VIEW_MODE_FLOATING;
   4759 
   4760     if (mode == Page::ViewModeFullscreen)
   4761         return WEBKIT_WEB_VIEW_VIEW_MODE_FULLSCREEN;
   4762 
   4763     if (mode == Page::ViewModeMaximized)
   4764         return WEBKIT_WEB_VIEW_VIEW_MODE_MAXIMIZED;
   4765 
   4766     if (mode == Page::ViewModeMinimized)
   4767         return WEBKIT_WEB_VIEW_VIEW_MODE_MINIMIZED;
   4768 
   4769     return WEBKIT_WEB_VIEW_VIEW_MODE_WINDOWED;
   4770 }
   4771 
   4772 /**
   4773  * webkit_web_view_move_cursor:
   4774  * @webView: a #WebKitWebView
   4775  * @step: a #GtkMovementStep
   4776  * @count: integer describing the direction of the movement. 1 for forward, -1 for backwards.
   4777  *
   4778  * Move the cursor in @view as described by @step and @count.
   4779  *
   4780  * Since: 1.1.4
   4781  */
   4782 void webkit_web_view_move_cursor(WebKitWebView* webView, GtkMovementStep step, gint count)
   4783 {
   4784     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4785     g_return_if_fail(step == GTK_MOVEMENT_VISUAL_POSITIONS ||
   4786                      step == GTK_MOVEMENT_DISPLAY_LINES ||
   4787                      step == GTK_MOVEMENT_PAGES ||
   4788                      step == GTK_MOVEMENT_BUFFER_ENDS);
   4789     g_return_if_fail(count == 1 || count == -1);
   4790 
   4791     gboolean handled;
   4792     g_signal_emit(webView, webkit_web_view_signals[MOVE_CURSOR], 0, step, count, &handled);
   4793 }
   4794 
   4795 /**
   4796  * webkit_web_view_can_undo:
   4797  * @webView: a #WebKitWebView
   4798  *
   4799  * Determines whether or not it is currently possible to undo the last
   4800  * editing command in the view.
   4801  *
   4802  * Return value: %TRUE if a undo can be done, %FALSE if not
   4803  *
   4804  * Since: 1.1.14
   4805  */
   4806 gboolean webkit_web_view_can_undo(WebKitWebView* webView)
   4807 {
   4808     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4809 
   4810     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4811     return frame->editor()->canUndo();
   4812 }
   4813 
   4814 /**
   4815  * webkit_web_view_undo:
   4816  * @webView: a #WebKitWebView
   4817  *
   4818  * Undoes the last editing command in the view, if possible.
   4819  *
   4820  * Since: 1.1.14
   4821  */
   4822 void webkit_web_view_undo(WebKitWebView* webView)
   4823 {
   4824     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4825 
   4826     if (webkit_web_view_can_undo(webView))
   4827         g_signal_emit(webView, webkit_web_view_signals[UNDO], 0);
   4828 }
   4829 
   4830 /**
   4831  * webkit_web_view_can_redo:
   4832  * @webView: a #WebKitWebView
   4833  *
   4834  * Determines whether or not it is currently possible to redo the last
   4835  * editing command in the view.
   4836  *
   4837  * Return value: %TRUE if a redo can be done, %FALSE if not
   4838  *
   4839  * Since: 1.1.14
   4840  */
   4841 gboolean webkit_web_view_can_redo(WebKitWebView* webView)
   4842 {
   4843     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4844 
   4845     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   4846     return frame->editor()->canRedo();
   4847 }
   4848 
   4849 /**
   4850  * webkit_web_view_redo:
   4851  * @webView: a #WebKitWebView
   4852  *
   4853  * Redoes the last editing command in the view, if possible.
   4854  *
   4855  * Since: 1.1.14
   4856  */
   4857 void webkit_web_view_redo(WebKitWebView* webView)
   4858 {
   4859     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4860 
   4861     if (webkit_web_view_can_redo(webView))
   4862         g_signal_emit(webView, webkit_web_view_signals[REDO], 0);
   4863 }
   4864 
   4865 
   4866 /**
   4867  * webkit_web_view_set_view_source_mode:
   4868  * @webView: a #WebKitWebView
   4869  * @view_source_mode: the mode to turn on or off view source mode
   4870  *
   4871  * Set whether the view should be in view source mode. Setting this mode to
   4872  * %TRUE before loading a URI will display the source of the web page in a
   4873  * nice and readable format.
   4874  *
   4875  * Since: 1.1.14
   4876  */
   4877 void webkit_web_view_set_view_source_mode (WebKitWebView* webView, gboolean mode)
   4878 {
   4879     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
   4880 
   4881     if (Frame* mainFrame = core(webView)->mainFrame())
   4882         mainFrame->setInViewSourceMode(mode);
   4883 }
   4884 
   4885 /**
   4886  * webkit_web_view_get_view_source_mode:
   4887  * @webView: a #WebKitWebView
   4888  *
   4889  * Return value: %TRUE if @web_view is in view source mode, %FALSE otherwise.
   4890  *
   4891  * Since: 1.1.14
   4892  */
   4893 gboolean webkit_web_view_get_view_source_mode (WebKitWebView* webView)
   4894 {
   4895     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
   4896 
   4897     if (Frame* mainFrame = core(webView)->mainFrame())
   4898         return mainFrame->inViewSourceMode();
   4899 
   4900     return FALSE;
   4901 }
   4902 
   4903 // Internal subresource management
   4904 void webkit_web_view_add_main_resource(WebKitWebView* webView, const char* identifier, WebKitWebResource* webResource)
   4905 {
   4906     WebKitWebViewPrivate* priv = webView->priv;
   4907 
   4908     priv->mainResource = adoptGRef(webResource);
   4909     priv->mainResourceIdentifier = identifier;
   4910 }
   4911 
   4912 void webkit_web_view_add_resource(WebKitWebView* webView, const char* identifier, WebKitWebResource* webResource)
   4913 {
   4914     WebKitWebViewPrivate* priv = webView->priv;
   4915     g_hash_table_insert(priv->subResources.get(), g_strdup(identifier), webResource);
   4916 }
   4917 
   4918 void webkit_web_view_remove_resource(WebKitWebView* webView, const char* identifier)
   4919 {
   4920     WebKitWebViewPrivate* priv = webView->priv;
   4921     if (g_str_equal(identifier, priv->mainResourceIdentifier.data())) {
   4922         priv->mainResourceIdentifier = "";
   4923         priv->mainResource = 0;
   4924     } else
   4925       g_hash_table_remove(priv->subResources.get(), identifier);
   4926 }
   4927 
   4928 WebKitWebResource* webkit_web_view_get_resource(WebKitWebView* webView, char* identifier)
   4929 {
   4930     WebKitWebViewPrivate* priv = webView->priv;
   4931     gpointer webResource = 0;
   4932     gboolean resourceFound = g_hash_table_lookup_extended(priv->subResources.get(), identifier, NULL, &webResource);
   4933 
   4934     // The only resource we do not store in this hash table is the
   4935     // main!  If we did not find a request, it probably means the load
   4936     // has been interrupted while while a resource was still being
   4937     // loaded.
   4938     if (!resourceFound && !g_str_equal(identifier, priv->mainResourceIdentifier.data()))
   4939         return 0;
   4940 
   4941     if (!webResource)
   4942         return webkit_web_view_get_main_resource(webView);
   4943 
   4944     return WEBKIT_WEB_RESOURCE(webResource);
   4945 }
   4946 
   4947 WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView)
   4948 {
   4949     return webView->priv->mainResource.get();
   4950 }
   4951 
   4952 void webkit_web_view_clear_resources(WebKitWebView* webView)
   4953 {
   4954     WebKitWebViewPrivate* priv = webView->priv;
   4955 
   4956     if (priv->subResources)
   4957         g_hash_table_remove_all(priv->subResources.get());
   4958 }
   4959 
   4960 GList* webkit_web_view_get_subresources(WebKitWebView* webView)
   4961 {
   4962     WebKitWebViewPrivate* priv = webView->priv;
   4963     GList* subResources = g_hash_table_get_values(priv->subResources.get());
   4964     return g_list_remove(subResources, priv->mainResource.get());
   4965 }
   4966 
   4967 /* From EventHandler.cpp */
   4968 static IntPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint)
   4969 {
   4970     FrameView* view = frame->view();
   4971     // FIXME: Is it really OK to use the wrong coordinates here when view is 0?
   4972     // Historically the code would just crash; this is clearly no worse than that.
   4973     return view ? view->windowToContents(windowPoint) : windowPoint;
   4974 }
   4975 
   4976 void webkit_web_view_set_tooltip_text(WebKitWebView* webView, const char* tooltip)
   4977 {
   4978 #if GTK_CHECK_VERSION(2, 12, 0)
   4979     WebKitWebViewPrivate* priv = webView->priv;
   4980     if (tooltip && *tooltip != '\0') {
   4981         priv->tooltipText = tooltip;
   4982         gtk_widget_set_has_tooltip(GTK_WIDGET(webView), TRUE);
   4983     } else {
   4984         priv->tooltipText = "";
   4985         gtk_widget_set_has_tooltip(GTK_WIDGET(webView), FALSE);
   4986     }
   4987 
   4988     gtk_widget_trigger_tooltip_query(GTK_WIDGET(webView));
   4989 #else
   4990     // TODO: Support older GTK+ versions
   4991     // See http://bugs.webkit.org/show_bug.cgi?id=15793
   4992     notImplemented();
   4993 #endif
   4994 }
   4995 
   4996 /**
   4997  * webkit_web_view_get_hit_test_result:
   4998  * @webView: a #WebKitWebView
   4999  * @event: a #GdkEventButton
   5000  *
   5001  * Does a 'hit test' in the coordinates specified by @event to figure
   5002  * out context information about that position in the @webView.
   5003  *
   5004  * Returns: (transfer none): a newly created #WebKitHitTestResult with the context of the
   5005  * specified position.
   5006  *
   5007  * Since: 1.1.15
   5008  **/
   5009 WebKitHitTestResult* webkit_web_view_get_hit_test_result(WebKitWebView* webView, GdkEventButton* event)
   5010 {
   5011     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL);
   5012     g_return_val_if_fail(event, NULL);
   5013 
   5014     PlatformMouseEvent mouseEvent = PlatformMouseEvent(event);
   5015     Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
   5016     HitTestRequest request(HitTestRequest::Active);
   5017     IntPoint documentPoint = documentPointForWindowPoint(frame, mouseEvent.pos());
   5018     MouseEventWithHitTestResults mev = frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent);
   5019 
   5020     return kit(mev.hitTestResult());
   5021 }
   5022 
   5023 /**
   5024  * webkit_web_view_get_icon_uri:
   5025  * @webView: the #WebKitWebView object
   5026  *
   5027  * Obtains the URI for the favicon for the given #WebKitWebView, or
   5028  * %NULL if there is none.
   5029  *
   5030  * Return value: the URI for the favicon, or %NULL
   5031  *
   5032  * Since: 1.1.18
   5033  */
   5034 G_CONST_RETURN gchar* webkit_web_view_get_icon_uri(WebKitWebView* webView)
   5035 {
   5036     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   5037     String iconURL = iconDatabase().synchronousIconURLForPageURL(core(webView)->mainFrame()->document()->url().string());
   5038     webView->priv->iconURI = iconURL.utf8();
   5039     return webView->priv->iconURI.data();
   5040 }
   5041 
   5042 /**
   5043  * webkit_web_view_get_icon_pixbuf:
   5044  * @webView: the #WebKitWebView object
   5045  *
   5046  * Obtains a #GdkPixbuf of the favicon for the given #WebKitWebView, or
   5047  * a default icon if there is no icon for the given page. Use
   5048  * webkit_web_view_get_icon_uri() if you need to distinguish these cases.
   5049  * Usually you want to connect to WebKitWebView::icon-loaded and call this
   5050  * method in the callback.
   5051  *
   5052  * The pixbuf will have the largest size provided by the server and should
   5053  * be resized before it is displayed.
   5054  * See also webkit_icon_database_get_icon_pixbuf().
   5055  *
   5056  * Returns: (transfer full): a new reference to a #GdkPixbuf, or %NULL
   5057  *
   5058  * Since: 1.3.13
   5059  */
   5060 GdkPixbuf* webkit_web_view_get_icon_pixbuf(WebKitWebView* webView)
   5061 {
   5062     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   5063 
   5064     const gchar* pageURI = webkit_web_view_get_uri(webView);
   5065     WebKitIconDatabase* database = webkit_get_icon_database();
   5066     return webkit_icon_database_get_icon_pixbuf(database, pageURI);
   5067 }
   5068 
   5069 
   5070 
   5071 /**
   5072  * webkit_web_view_get_dom_document:
   5073  * @webView: a #WebKitWebView
   5074  *
   5075  * Returns: (transfer none): the #WebKitDOMDocument currently loaded in the @webView
   5076  *
   5077  * Since: 1.3.1
   5078  **/
   5079 WebKitDOMDocument*
   5080 webkit_web_view_get_dom_document(WebKitWebView* webView)
   5081 {
   5082     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   5083 
   5084     Frame* coreFrame = core(webView)->mainFrame();
   5085     if (!coreFrame)
   5086         return 0;
   5087 
   5088     Document* doc = coreFrame->document();
   5089     if (!doc)
   5090         return 0;
   5091 
   5092     return kit(doc);
   5093 }
   5094 
   5095 GtkMenu* webkit_web_view_get_context_menu(WebKitWebView* webView)
   5096 {
   5097     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
   5098 
   5099 #if ENABLE(CONTEXT_MENUS)
   5100     ContextMenu* menu = core(webView)->contextMenuController()->contextMenu();
   5101     if (!menu)
   5102         return 0;
   5103     return menu->platformDescription();
   5104 #else
   5105     return 0;
   5106 #endif
   5107 }
   5108 
   5109 void webViewEnterFullscreen(WebKitWebView* webView, Node* node)
   5110 {
   5111     if (!node->hasTagName(HTMLNames::videoTag))
   5112         return;
   5113 
   5114 #if ENABLE(VIDEO)
   5115     HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
   5116     WebKitWebViewPrivate* priv = webView->priv;
   5117 
   5118     // First exit Fullscreen for the old mediaElement.
   5119     if (priv->fullscreenVideoController)
   5120         priv->fullscreenVideoController->exitFullscreen();
   5121 
   5122     priv->fullscreenVideoController = new FullscreenVideoController;
   5123     priv->fullscreenVideoController->setMediaElement(videoElement);
   5124     priv->fullscreenVideoController->enterFullscreen();
   5125 #endif
   5126 }
   5127 
   5128 void webViewExitFullscreen(WebKitWebView* webView)
   5129 {
   5130 #if ENABLE(VIDEO)
   5131     WebKitWebViewPrivate* priv = webView->priv;
   5132     if (priv->fullscreenVideoController)
   5133         priv->fullscreenVideoController->exitFullscreen();
   5134 #endif
   5135 }
   5136 
   5137 namespace WebKit {
   5138 
   5139 WebCore::Page* core(WebKitWebView* webView)
   5140 {
   5141     if (!webView)
   5142         return 0;
   5143 
   5144     WebKitWebViewPrivate* priv = webView->priv;
   5145     return priv ? priv->corePage : 0;
   5146 }
   5147 
   5148 WebKitWebView* kit(WebCore::Page* corePage)
   5149 {
   5150     if (!corePage)
   5151         return 0;
   5152 
   5153     ASSERT(corePage->chrome());
   5154     WebKit::ChromeClient* client = static_cast<WebKit::ChromeClient*>(corePage->chrome()->client());
   5155     return client ? client->webView() : 0;
   5156 }
   5157 
   5158 }
   5159