📄 webkitwebview.cpp
字号:
/* * Copyright (C) 2007, 2008 Holger Hans Peter Freyther * Copyright (C) 2007, 2008, 2009 Christian Dywan <christian@imendio.com> * Copyright (C) 2007 Xan Lopez <xan@gnome.org> * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com> * Copyright (C) 2008 Jan Alonzo <jmalonzo@unpluggable.com> * Copyright (C) 2008 Gustavo Noronha Silva <gns@gnome.org> * Copyright (C) 2008 Nuanti Ltd. * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2009 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "config.h"#include "webkitdownload.h"#include "webkitwebview.h"#include "webkitenumtypes.h"#include "webkitmarshal.h"#include "webkitprivate.h"#include "webkitwebinspector.h"#include "webkitwebbackforwardlist.h"#include "webkitwebhistoryitem.h"#include "AXObjectCache.h"#include "NotImplemented.h"#include "BackForwardList.h"#include "CString.h"#include "ChromeClientGtk.h"#include "ContextMenu.h"#include "ContextMenuClientGtk.h"#include "ContextMenuController.h"#include "Cursor.h"#include "Document.h"#include "DocumentLoader.h"#include "DragClientGtk.h"#include "Editor.h"#include "EditorClientGtk.h"#include "EventHandler.h"#include "FloatQuad.h"#include "FocusController.h"#include "FrameLoaderTypes.h"#include "HitTestRequest.h"#include "HitTestResult.h"#include "GraphicsContext.h"#include "InspectorClientGtk.h"#include "FrameLoader.h"#include "FrameView.h"#include "PasteboardHelper.h"#include "PlatformKeyboardEvent.h"#include "PlatformWheelEvent.h"#include "ResourceHandle.h"#include "ScriptValue.h"#include "Scrollbar.h"#include <wtf/GOwnPtr.h>#include <gdk/gdkkeysyms.h>/** * SECTION:webkitwebview * @short_description: The central class of the WebKit/Gtk+ API * @see_also: #WebKitWebSettings, #WebKitWebFrame * * #WebKitWebView is the central class of the WebKit/Gtk+ API. It is a * #GtkWidget implementing the scrolling interface which means you can * embed in a #GtkScrolledWindow. It is responsible for managing the * drawing of the content, forwarding of events. You can load any URI * into the #WebKitWebView or any kind of data string. With #WebKitWebSettings * you can control various aspects of the rendering and loading of the content. * Each #WebKitWebView has exactly one #WebKitWebFrame as main frame. A * #WebKitWebFrame can have n children. * * <programlisting> * /<!-- -->* Create the widgets *<!-- -->/ * GtkWidget *main_window = gtk_window_new (GTK_WIDGET_TOPLEVEL); * GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); * GtkWidget *web_view = webkit_web_view_new (); * * /<!-- -->* Place the WebKitWebView in the GtkScrolledWindow *<!-- -->/ * gtk_container_add (GTK_CONTAINER (scrolled_window), web_view); * gtk_container_add (GTK_CONTAINER (main_window), scrolled_window); * * /<!-- -->* Open a webpage *<!-- -->/ * webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), "http://www.gnome.org"); * * /<!-- -->* Show the result *<!-- -->/ * gtk_window_set_default_size (GTK_WINDOW (main_window), 800, 600); * gtk_widget_show_all (main_window); * </programlisting> */static const double defaultDPI = 96.0;using namespace WebKit;using namespace WebCore;extern "C" {enum { /* normal signals */ NAVIGATION_REQUESTED, NAVIGATION_POLICY_DECISION_REQUESTED, MIME_TYPE_POLICY_DECISION_REQUESTED, CREATE_WEB_VIEW, WEB_VIEW_READY, WINDOW_OBJECT_CLEARED, LOAD_STARTED, LOAD_COMMITTED, LOAD_PROGRESS_CHANGED, LOAD_FINISHED, TITLE_CHANGED, HOVERING_OVER_LINK, POPULATE_POPUP, STATUS_BAR_TEXT_CHANGED, ICOND_LOADED, SELECTION_CHANGED, CONSOLE_MESSAGE, SCRIPT_ALERT, SCRIPT_CONFIRM, SCRIPT_PROMPT, SELECT_ALL, COPY_CLIPBOARD, PASTE_CLIPBOARD, CUT_CLIPBOARD, DOWNLOAD_REQUESTED, LAST_SIGNAL};enum { PROP_0, PROP_COPY_TARGET_LIST, PROP_PASTE_TARGET_LIST, PROP_EDITABLE, PROP_SETTINGS, PROP_WEB_INSPECTOR, PROP_WINDOW_FEATURES, PROP_TRANSPARENT, PROP_ZOOM_LEVEL, PROP_FULL_CONTENT_ZOOM, PROP_ENCODING, PROP_CUSTOM_ENCODING};static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, };G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GParamSpec* pspec, WebKitWebView* webView);static void webkit_web_view_set_window_features(WebKitWebView* webView, WebKitWebWindowFeatures* webWindowFeatures);static void webkit_web_view_context_menu_position_func(GtkMenu*, gint* x, gint* y, gboolean* pushIn, WebKitWebViewPrivate* data){ *pushIn = FALSE; *x = data->lastPopupXPosition; *y = data->lastPopupYPosition;}static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event){ Page* page = core(webView); page->contextMenuController()->clearContextMenu(); Frame* focusedFrame = page->focusController()->focusedOrMainFrame(); if (!focusedFrame->view()) return FALSE; focusedFrame->view()->setCursor(pointerCursor()); bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event); if (!handledEvent) return FALSE; ContextMenu* coreMenu = page->contextMenuController()->contextMenu(); if (!coreMenu) return FALSE; GtkMenu* menu = GTK_MENU(coreMenu->platformDescription()); if (!menu) return FALSE; g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu); GList* items = gtk_container_get_children(GTK_CONTAINER(menu)); bool empty = !g_list_nth(items, 0); g_list_free(items); if (empty) return FALSE; WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(webView); priv->lastPopupXPosition = event.globalX(); priv->lastPopupYPosition = event.globalY(); gtk_menu_popup(menu, NULL, NULL, reinterpret_cast<GtkMenuPositionFunc>(webkit_web_view_context_menu_position_func), priv, event.button() + 1, gtk_get_current_event_time()); return TRUE;}static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget){ static const int contextMenuMargin = 1; // The context menu event was generated from the keyboard, so show the context menu by the current selection. Page* page = core(WEBKIT_WEB_VIEW(widget)); FrameView* view = page->mainFrame()->view(); if (!view) return FALSE; Position start = page->mainFrame()->selection()->selection().start(); Position end = page->mainFrame()->selection()->selection().end(); int rightAligned = FALSE; IntPoint location; if (!start.node() || !end.node()) location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin); else { RenderObject* renderer = start.node()->renderer(); if (!renderer) return FALSE; // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:], // now Frame::firstRectForRange(), which perhaps this should call). int extraWidthToEndOfLine = 0; InlineBox* startInlineBox; int startCaretOffset; start.getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset); IntRect startCaretRect = renderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine); if (startCaretRect != IntRect()) startCaretRect = renderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox(); InlineBox* endInlineBox; int endCaretOffset; end.getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset); IntRect endCaretRect = renderer->localCaretRect(endInlineBox, endCaretOffset); if (endCaretRect != IntRect()) endCaretRect = renderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox(); IntRect firstRect; if (startCaretRect.y() == endCaretRect.y()) firstRect = IntRect(MIN(startCaretRect.x(), endCaretRect.x()), startCaretRect.y(), abs(endCaretRect.x() - startCaretRect.x()), MAX(startCaretRect.height(), endCaretRect.height())); else firstRect = IntRect(startCaretRect.x(), startCaretRect.y(), startCaretRect.width() + extraWidthToEndOfLine, startCaretRect.height()); location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom()); } int x, y; gdk_window_get_origin(GTK_WIDGET(view->hostWindow()->platformWindow())->window, &x, &y); // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element. // Ideally we'd have the position of a context menu event be separate from its target node. location = view->contentsToWindow(location) + IntSize(0, -1); IntPoint global = location + IntSize(x, y); PlatformMouseEvent event(location, global, NoButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time()); return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);}static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec){ WebKitWebView* webView = WEBKIT_WEB_VIEW(object); switch(prop_id) {#if GTK_CHECK_VERSION(2,10,0) case PROP_COPY_TARGET_LIST: g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView)); break; case PROP_PASTE_TARGET_LIST: g_value_set_boxed(value, webkit_web_view_get_paste_target_list(webView)); break;#endif case PROP_EDITABLE: g_value_set_boolean(value, webkit_web_view_get_editable(webView)); break; case PROP_SETTINGS: g_value_set_object(value, webkit_web_view_get_settings(webView)); break; case PROP_WEB_INSPECTOR: g_value_set_object(value, webkit_web_view_get_inspector(webView)); break; case PROP_WINDOW_FEATURES: g_value_set_object(value, webkit_web_view_get_window_features(webView)); break; case PROP_TRANSPARENT: g_value_set_boolean(value, webkit_web_view_get_transparent(webView)); break; case PROP_ZOOM_LEVEL: g_value_set_float(value, webkit_web_view_get_zoom_level(webView)); break; case PROP_FULL_CONTENT_ZOOM: g_value_set_boolean(value, webkit_web_view_get_full_content_zoom(webView)); break; case PROP_ENCODING: g_value_set_string(value, webkit_web_view_get_encoding(webView)); break; case PROP_CUSTOM_ENCODING: g_value_set_string(value, webkit_web_view_get_custom_encoding(webView)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); }}static void webkit_web_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec){ WebKitWebView* webView = WEBKIT_WEB_VIEW(object); switch(prop_id) { case PROP_EDITABLE: webkit_web_view_set_editable(webView, g_value_get_boolean(value)); break; case PROP_SETTINGS: webkit_web_view_set_settings(webView, WEBKIT_WEB_SETTINGS(g_value_get_object(value))); break; case PROP_WINDOW_FEATURES: webkit_web_view_set_window_features(webView, WEBKIT_WEB_WINDOW_FEATURES(g_value_get_object(value))); break; case PROP_TRANSPARENT: webkit_web_view_set_transparent(webView, g_value_get_boolean(value)); break; case PROP_ZOOM_LEVEL: webkit_web_view_set_zoom_level(webView, g_value_get_float(value)); break; case PROP_FULL_CONTENT_ZOOM: webkit_web_view_set_full_content_zoom(webView, g_value_get_boolean(value));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -