WebKitWebViewBase.cpp [plain text]
#include "config.h"
#include "WebKitWebViewBase.h"
#include "DrawingAreaProxyImpl.h"
#include "GOwnPtrGtk.h"
#include "GtkClickCounter.h"
#include "GtkVersioning.h"
#include "NativeWebKeyboardEvent.h"
#include "NativeWebMouseEvent.h"
#include "NativeWebWheelEvent.h"
#include "NotImplemented.h"
#include "PageClientImpl.h"
#include "RefPtrCairo.h"
#include "Region.h"
#include "WebContext.h"
#include "WebEventFactory.h"
#include "WebKitWebViewBasePrivate.h"
#include "WebPageProxy.h"
#include <WebKit2/WKContext.h>
using namespace WebKit;
using namespace WebCore;
struct _WebKitWebViewBasePrivate {
OwnPtr<PageClientImpl> pageClient;
RefPtr<WebPageProxy> pageProxy;
gboolean isPageActive;
GtkIMContext* imContext;
GtkClickCounter clickCounter;
};
G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
static void webkitWebViewBaseRealize(GtkWidget* widget)
{
gtk_widget_set_realized(widget, TRUE);
GtkAllocation allocation;
gtk_widget_get_allocation(widget, &allocation);
GdkWindowAttr attributes;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = allocation.x;
attributes.y = allocation.y;
attributes.width = allocation.width;
attributes.height = allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual(widget);
#ifdef GTK_API_VERSION_2
attributes.colormap = gtk_widget_get_colormap(widget);
#endif
attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
| GDK_EXPOSURE_MASK
| GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_MASK
| GDK_KEY_PRESS_MASK
| GDK_KEY_RELEASE_MASK
| GDK_BUTTON_MOTION_MASK
| GDK_BUTTON1_MOTION_MASK
| GDK_BUTTON2_MOTION_MASK
| GDK_BUTTON3_MOTION_MASK;
gint attributesMask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
#ifdef GTK_API_VERSION_2
attributesMask |= GDK_WA_COLORMAP;
#endif
GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributesMask);
gtk_widget_set_window(widget, window);
gdk_window_set_user_data(window, widget);
#ifdef GTK_API_VERSION_2
#if GTK_CHECK_VERSION(2, 20, 0)
gtk_widget_style_attach(widget);
#else
widget->style = gtk_style_attach(gtk_widget_get_style(widget), window);
#endif
gtk_style_set_background(gtk_widget_get_style(widget), window, GTK_STATE_NORMAL);
#else
gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
#endif
WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webView->priv;
gtk_im_context_set_client_window(priv->imContext, window);
}
static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget)
{
gtk_widget_set_parent(widget, GTK_WIDGET(container));
}
static void webkitWebViewBaseFinalize(GObject* gobject)
{
WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(gobject);
WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
if (priv->imContext) {
g_object_unref(priv->imContext);
priv->imContext = 0;
}
priv->pageProxy->close();
delete priv;
webkitWebViewBase->priv = 0;
G_OBJECT_CLASS(webkit_web_view_base_parent_class)->finalize(gobject);
}
static void webkit_web_view_base_init(WebKitWebViewBase* webkitWebViewBase)
{
WebKitWebViewBasePrivate* priv = new WebKitWebViewBasePrivate();
webkitWebViewBase->priv = priv;
priv->isPageActive = TRUE;
gtk_widget_set_can_focus(GTK_WIDGET(webkitWebViewBase), TRUE);
priv->imContext = gtk_im_multicontext_new();
priv->pageClient = PageClientImpl::create(GTK_WIDGET(webkitWebViewBase));
}
static void callDrawingAreaPaintMethod(DrawingAreaProxy* drawingArea, cairo_t* context, const IntRect& area)
{
WebKit::Region unpaintedRegion; static_cast<DrawingAreaProxyImpl*>(drawingArea)->paint(context, area, unpaintedRegion);
}
#ifdef GTK_API_VERSION_2
static gboolean webkitWebViewBaseExpose(GtkWidget* widget, GdkEventExpose* event)
{
GdkRectangle clipRect;
gdk_region_get_clipbox(event->region, &clipRect);
RefPtr<cairo_t> cr = adoptRef(gdk_cairo_create(gtk_widget_get_window(widget)));
callDrawingAreaPaintMethod(WEBKIT_WEB_VIEW_BASE(widget)->priv->pageProxy->drawingArea(), cr.get(), clipRect);
return FALSE;
}
#else
static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
{
GdkRectangle clipRect;
if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
return FALSE;
callDrawingAreaPaintMethod(WEBKIT_WEB_VIEW_BASE(widget)->priv->pageProxy->drawingArea(), cr, clipRect);
return FALSE;
}
#endif
static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize());
}
static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
if (gtk_widget_is_toplevel(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) {
gtk_im_context_focus_in(priv->imContext);
if (!priv->isPageActive) {
priv->isPageActive = TRUE;
priv->pageProxy->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
}
}
return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_in_event(widget, event);
}
static gboolean webkitWebViewBaseFocusOutEvent(GtkWidget* widget, GdkEventFocus* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
priv->isPageActive = FALSE;
priv->pageProxy->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
if (priv->imContext)
gtk_im_context_focus_out(priv->imContext);
return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_out_event(widget, event);
}
static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast<GdkEvent*>(event)));
return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, event);
}
static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (gtk_im_context_filter_keypress(priv->imContext, event))
return TRUE;
priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(reinterpret_cast<GdkEvent*>(event)));
return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, event);
}
static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventButton* buttonEvent)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
gtk_widget_grab_focus(widget);
if (!priv->clickCounter.shouldProcessButtonEvent(buttonEvent))
return TRUE;
priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent),
priv->clickCounter.clickCountForGdkButtonEvent(widget, buttonEvent)));
return FALSE;
}
static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventButton* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
gtk_widget_grab_focus(widget);
priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 ));
return FALSE;
}
static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(reinterpret_cast<GdkEvent*>(event)));
return FALSE;
}
static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 ));
return FALSE;
}
static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebViewBaseClass)
{
GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
widgetClass->realize = webkitWebViewBaseRealize;
#ifdef GTK_API_VERSION_2
widgetClass->expose_event = webkitWebViewBaseExpose;
#else
widgetClass->draw = webkitWebViewBaseDraw;
#endif
widgetClass->size_allocate = webkitWebViewBaseSizeAllocate;
widgetClass->focus_in_event = webkitWebViewBaseFocusInEvent;
widgetClass->focus_out_event = webkitWebViewBaseFocusOutEvent;
widgetClass->key_press_event = webkitWebViewBaseKeyPressEvent;
widgetClass->key_release_event = webkitWebViewBaseKeyReleaseEvent;
widgetClass->button_press_event = webkitWebViewBaseButtonPressEvent;
widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);
gobjectClass->finalize = webkitWebViewBaseFinalize;
GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass);
containerClass->add = webkitWebViewBaseContainerAdd;
}
WebKitWebViewBase* webkitWebViewBaseCreate(WebContext* context, WebPageGroup* pageGroup)
{
WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, NULL));
WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
priv->pageProxy = context->createWebPage(priv->pageClient.get(), pageGroup);
priv->pageProxy->initializeWebPage();
return webkitWebViewBase;
}
GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase* webkitWebViewBase)
{
return webkitWebViewBase->priv->imContext;
}
WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
{
return webkitWebViewBase->priv->pageProxy.get();
}