📄 bridgeimpl.cpp
字号:
/* * Copyright (c) 2004 Nokia. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Nokia nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */#include <assert.h>#include <glib.h>#include <gdk/gdk.h>#include <gtk/gtk.h>#include "BridgeImpl.h"#include "NRCore/WebCoreViewFactory.h"#include "NRCore/WebCoreSettings.h"#include "NRCore/WebCoreResourceLoader.h"#include "NRCore/WebCoreCache.h"#include "NRCore/KWIQResponse.h"#include "Http.h"#include "XftTextRendererFactory.h"#include "ImageRendererFactory.h"#include "VisitedURLHistory.h"#include "GdkXftContext.h"#include "UnicodeImpl.h"#include "ResourceLoadListener.h"#include "PageLoadListener.h"#include "osbimpl.h"#include "GdkHelpers.h"#include "GLibHelpers.h"static void mapToParentWindow(GdkWindow* parent, GdkWindow* child, int&x, int&y);extern "C" { static void size_allocate( GtkWidget *widget, GtkAllocation *allocation, gpointer data); static int expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); static gint motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer data); static gint button_press(GtkWidget *widget, GdkEventButton *event, gpointer data); static gint button_release(GtkWidget *widget, GdkEventButton *event, gpointer data); static gboolean focus(GtkWidget *widget, GtkDirectionType dir, gpointer data); static gboolean focus_inout_event(GtkWidget *widget, GdkEventFocus *event, gpointer data); static gboolean key_press(GtkWidget *widget, GdkEventKey *event, gpointer data);}class FactoryInitializer{public: FactoryInitializer() { WebCoreUnicodeDigitValueFunction = UnicodeImplDigitValueFunction; WebCoreUnicodeDirectionFunction = UnicodeImplDirectionFunction; WebCoreUnicodeMirroredFunction = UnicodeImplMirroredFunction; WebCoreUnicodeMirroredCharFunction = UnicodeImplMirroredCharFunction; WebCoreUnicodeLowerFunction = UnicodeImplLowerFunction; WebCoreUnicodeUpperFunction = UnicodeImplUpperFunction; XftTextRendererFactory::useAsSharedFactory(); ImageRendererFactory::useAsSharedFactory(); VisitedURLHistory::useAsSharedProvider(); }};static FactoryInitializer _fi;extern "C"{static gbooleanfocus_scrolledwindow(GtkWidget *widget, GtkDirectionType dir, gpointer data){#if DEBUG g_printerr("%s: widget:%x dir:%x data:%x \n", __PRETTY_FUNCTION__, (int)widget, (int)dir, (int)data);#endif BridgeImpl *bridge = static_cast<BridgeImpl*>(data); GtkWidget *foundWidget = 0; switch (dir){ case GTK_DIR_TAB_FORWARD: foundWidget = bridge->nextKeyView(); break; case GTK_DIR_TAB_BACKWARD: foundWidget = bridge->previousKeyView(); break; default: break; } if (foundWidget && foundWidget != widget) bridge->makeFirstResponder(foundWidget); return foundWidget ? TRUE : FALSE; // TRUE To stop propagating, FALSE to continue}static gbooleanfocus_in_scrolledwindow(GtkWidget *widget, GdkEventFocus *event, gpointer data){#if DEBUG g_printerr("%s: widget:%x data:%x in:%x\n", __PRETTY_FUNCTION__, (int)widget, (int)data, event->in);#endif if (event->in == FALSE) { // FIXME: How to unset document focus // BridgeImpl *bridge = static_cast<BridgeImpl*>(data); } return FALSE;}}staticvoid freeGListOfStrings(GList* listOfStrings){ if (listOfStrings) { GList* iter = listOfStrings; while (iter) { if (iter->data) g_free(iter->data); iter = g_list_next(iter); } g_list_free(listOfStrings); }}BridgeImpl::BridgeImpl(BridgeImpl *parent) :_parent(parent) , _childFrames(0) , _documentState(0) , _shouldReapplyStyles(false) , _inexpose(false) , _requestedURL(0) , _currentURL(0) , _generatedFrameName(0) , _generatedFrameNameId(0) , _frameName(0) , _activeRequest(0) , _isReloading(false){ if (parent) { _parent = parent; setParent(parent); didSetName("root frame"); } else { _parent = 0; } WebCoreBridge::init(); WebCoreCache::setDisabled(false); _oldCanvasSize.x = _oldCanvasSize.y = _oldCanvasSize.width = _oldCanvasSize.height = 0; frameWidget = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new(NULL, NULL)); gtk_scrolled_window_set_shadow_type(frameWidget, GTK_SHADOW_NONE); GtkAdjustment* ha = gtk_scrolled_window_get_hadjustment(frameWidget); GtkAdjustment* va = gtk_scrolled_window_get_vadjustment(frameWidget); ha->step_increment = 20; va->step_increment = 10; frameCanvas = gtk_layout_new(gtk_scrolled_window_get_hadjustment(frameWidget), gtk_scrolled_window_get_vadjustment(frameWidget)); gtk_widget_set_double_buffered(GTK_WIDGET (frameCanvas), FALSE); gtk_widget_set_double_buffered(GTK_WIDGET (frameWidget), FALSE); gtk_widget_add_events(GTK_WIDGET (frameCanvas), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_EXPOSURE_MASK); gtk_container_add(GTK_CONTAINER (frameWidget), frameCanvas); frameWidget.connect("focus", ::focus_scrolledwindow, this); frameWidget.connect("focus-in-event", ::focus_in_scrolledwindow, this); frameWidget.connect("focus-out-event", ::focus_in_scrolledwindow, this); connectFrameContents(); createKHTMLViewWithGtkWidget(GTK_WIDGET(frameWidget), 0,0);}void BridgeImpl::sizeAllocate(GtkWidget *widget, GtkAllocation* allocation){ if (_oldCanvasSize.x == allocation->x && _oldCanvasSize.y == allocation->y && _oldCanvasSize.width == allocation->width && _oldCanvasSize.height == allocation->height) return; _oldCanvasSize = *allocation; GtkAdjustment* ha = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(frameWidget)); GtkAdjustment* va = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(frameWidget)); va->page_increment = (gdouble) allocation->width; ha->page_increment = (gdouble) allocation->height; forceLayoutAdjustingViewSize(false); sendResizeEvent();}/** * * Bridge delete semantics: * on deleting top level main frame, the KHTMLPart takes care of subframes. * HTMLFrameElementImpl::detach calls KHTMLPart::frameDetached, which will inform * Bridge that frame is ready to be deleted * Bridge then deletes itself and derefs its part. * After that KHTMLPart::frameDetached removes the part KHTMLPart's subframe list * and derefs the part for the last time. part gets destroyed. */BridgeImpl::~BridgeImpl(){#ifdef DEBUG g_printerr("%s this:%x, part:%x, frameName:%s", __PRETTY_FUNCTION__, (int)this, (int)part(), _frameName);#endif if (_frameName) g_free(_frameName); if (_requestedURL) g_free(_requestedURL); if (_currentURL) g_free(_currentURL); if (_generatedFrameName) g_free(_generatedFrameName); GList* iter = g_list_first(_childFrames); BridgeImpl* child; while (iter) { child = static_cast<BridgeImpl*>(iter->data); assert(child); child->_parent = 0; iter = g_list_next(iter); } g_list_free(_childFrames); freeGListOfStrings(_documentState); disconnectFrameContents(); }BridgeImpl* BridgeImpl::mainFrame(){ if (_parent) return _parent->mainFrame(); return this;}/** Searches for a child frame from current frame and subframes * internal function * Searches for a child frame from current frame and subframes recursively * @return 0 on failure */BridgeImpl* BridgeImpl::findChildFrameNamed(const gchar* frameName){ if (strcmp(this->_frameName, frameName)==0) return this; BridgeImpl* result; GList* iter = g_list_first(_childFrames); BridgeImpl* child; while (iter) { child = static_cast<BridgeImpl*>(iter->data); assert(child); result = child->findChildFrameNamed(frameName); if (result) return result; iter = g_list_next(iter); } return 0;}/** Searches for child frames from current frame, subframes, and parent frames * internal * First searches name from self, then childframes, except asendFrom -branch. * If not found, ascens one level up in the hierarchy */BridgeImpl* BridgeImpl::ascendingFindFrameNamed(const gchar* frameName, BridgeImpl* ascendFrom){ // search self if (strcmp(this->_frameName, frameName)==0) return this; BridgeImpl* result = 0; // search subtrees != ascendFrom GList* iter = g_list_first(_childFrames); BridgeImpl* child; while (iter) { child = static_cast<BridgeImpl*>(iter->data); assert(child); if (child != ascendFrom) { result = child->findChildFrameNamed(frameName); if (result) return result; } iter = g_list_next(iter); } // search parent if (_parent) return _parent->ascendingFindFrameNamed(frameName, this); return 0;}WebCoreBridge* BridgeImpl::findFrameNamed(const gchar *frameName){ // search common names if (strcmp(frameName, "_top")==0) return mainFrame(); if (strcmp(frameName,"_parent")==0) return _parent ? _parent : this; if (strcmp(frameName,"_self")==0) return this; // search self if (this->_frameName == frameName) return this; BridgeImpl* result = 0; // search subframes result = findChildFrameNamed(frameName); if (result) return result; // search upper branches if (_parent) { result = _parent->ascendingFindFrameNamed(frameName, this); if (result) return result; } // search other peers BridgeImpl *thisMain = mainFrame(); GList* myPeers = thisMain->peers(); GList* iter = g_list_first(myPeers); BridgeImpl *child; while (iter) { child = static_cast<BridgeImpl*>(iter->data); if (thisMain != child) { // skip this windows' branch, already searched result = child->findChildFrameNamed(frameName); if (result) return result; } iter = g_list_next(iter); } return 0;}const gchar* BridgeImpl::generateFrameName(){ static gchar* templ = "<!-- frame: %d-->"; // doesn't this leak one duplicated string? if (_generatedFrameName) g_free(_generatedFrameName); _generatedFrameName = g_strdup_printf(templ, _generatedFrameNameId); _generatedFrameNameId++; return _generatedFrameName;}void BridgeImpl::frameDetached(){ if (_parent) { _parent->_childFrames = g_list_remove(_parent->_childFrames, this); } delete this;}GtkWidget* BridgeImpl::documentView(){ return GTK_WIDGET (frameWidget);}void BridgeImpl::commitLoad(){ assignToString(&_currentURL, _requestedURL); emitCommitLoad(); }// methods overrides default WebCore method. void BridgeImpl::openURL(const gchar *_URL, bool reload, const gchar *_contentType, const gchar *refresh, GTime _lastModified, KWIQPageCache* pageCache){ _generatedFrameNameId = 0; clearFrameContents(true); WebCoreBridge::openURL(_URL, reload, _contentType, refresh, _lastModified, pageCache); VisitedURLHistory::sharedProvider()->insertVisitedURL(_URL);}/** * call didNotOpenURL(URL) * if user doesn't accept the load (popup-blocker, form submission dialog */void BridgeImpl::loadURL(const gchar* URL, const gchar* referrer, bool reload, bool onLoadEvent, const gchar* target, NSEvent *event, NRCit::DOMElement* form, GHashTable* formValues){ WebCoreBridge *targetBridge = this; if (isEmptyString(_frameName)) assignToString(&_frameName, target); if (!isEmptyString(target)) targetBridge = findFrameNamed(target); if (targetBridge && targetBridge != this) { targetBridge->loadURL(URL, referrer, reload, onLoadEvent, target, event, form, formValues); return; } if (!URL) URL = ""; if (!targetBridge) { // unknown windows should open in new window // target will have _blank or some custom name if (onLoadEvent) { // FIXME: implement: settings -> block popups didNotOpenURL(URL); } else { mainFrame()->createWindowWithURL(URL, target); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -