.: [GTK] Enable touch features
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / gtk / WebKitWebViewBase.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
4  * Copyright (C) 2011 Igalia S.L.
5  * Copyright (C) 2013 Gustavo Noronha Silva <gns@gnome.org>.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "WebKitWebViewBase.h"
31
32 #include "DrawingAreaProxyImpl.h"
33 #include "NativeWebMouseEvent.h"
34 #include "NativeWebWheelEvent.h"
35 #include "PageClientImpl.h"
36 #include "ViewState.h"
37 #include "WebContext.h"
38 #include "WebEventFactory.h"
39 #include "WebFullScreenClientGtk.h"
40 #include "WebInspectorProxy.h"
41 #include "WebKitAuthenticationDialog.h"
42 #include "WebKitPrivate.h"
43 #include "WebKitWebViewBaseAccessible.h"
44 #include "WebKitWebViewBasePrivate.h"
45 #include "WebPageGroup.h"
46 #include "WebPageProxy.h"
47 #include "WebPreferences.h"
48 #include "WebViewBaseInputMethodFilter.h"
49 #include <WebCore/ClipboardUtilitiesGtk.h>
50 #include <WebCore/DataObjectGtk.h>
51 #include <WebCore/DragData.h>
52 #include <WebCore/DragIcon.h>
53 #include <WebCore/GUniquePtrGtk.h>
54 #include <WebCore/GtkClickCounter.h>
55 #include <WebCore/GtkDragAndDropHelper.h>
56 #include <WebCore/GtkTouchContextHelper.h>
57 #include <WebCore/GtkUtilities.h>
58 #include <WebCore/GtkVersioning.h>
59 #include <WebCore/NotImplemented.h>
60 #include <WebCore/PasteboardHelper.h>
61 #include <WebCore/RefPtrCairo.h>
62 #include <WebCore/Region.h>
63 #include <gdk/gdk.h>
64 #include <gdk/gdkkeysyms.h>
65 #ifdef GDK_WINDOWING_X11
66 #include <gdk/gdkx.h>
67 #endif
68 #include <wtf/HashMap.h>
69 #include <wtf/gobject/GRefPtr.h>
70 #include <wtf/text/CString.h>
71
72 #if ENABLE(FULLSCREEN_API)
73 #include "WebFullScreenManagerProxy.h"
74 #endif
75
76 #if USE(TEXTURE_MAPPER_GL) && defined(GDK_WINDOWING_X11)
77 #include <WebCore/RedirectedXCompositeWindow.h>
78 #endif
79
80 using namespace WebKit;
81 using namespace WebCore;
82
83 typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap;
84
85 #if USE(TEXTURE_MAPPER_GL)
86 void redirectedWindowDamagedCallback(void* data);
87 #endif
88
89 struct _WebKitWebViewBasePrivate {
90     ~_WebKitWebViewBasePrivate()
91     {
92         pageProxy->close();
93     }
94
95     WebKitWebViewChildrenMap children;
96     OwnPtr<PageClientImpl> pageClient;
97     RefPtr<WebPageProxy> pageProxy;
98     bool shouldForwardNextKeyEvent;
99     GtkClickCounter clickCounter;
100     CString tooltipText;
101     IntRect tooltipArea;
102     GtkDragAndDropHelper dragAndDropHelper;
103     DragIcon dragIcon;
104     IntSize resizerSize;
105     GRefPtr<AtkObject> accessible;
106     bool needsResizeOnMap;
107     GtkWidget* authenticationDialog;
108     GtkWidget* inspectorView;
109     AttachmentSide inspectorAttachmentSide;
110     unsigned inspectorViewSize;
111     GUniquePtr<GdkEvent> contextMenuEvent;
112     WebContextMenuProxyGtk* activeContextMenuProxy;
113     WebViewBaseInputMethodFilter inputMethodFilter;
114     GtkTouchContextHelper touchContext;
115
116     GtkWindow* toplevelOnScreenWindow;
117     unsigned long toplevelResizeGripVisibilityID;
118     unsigned long toplevelFocusInEventID;
119     unsigned long toplevelFocusOutEventID;
120     unsigned long toplevelVisibilityEventID;
121
122     // View State.
123     bool isInWindowActive : 1;
124     bool isFocused : 1;
125     bool isVisible : 1;
126     bool isWindowVisible : 1;
127
128     WebKitWebViewBaseDownloadRequestHandler downloadHandler;
129
130 #if ENABLE(FULLSCREEN_API)
131     bool fullScreenModeActive;
132     WebFullScreenClientGtk fullScreenClient;
133 #endif
134
135 #if USE(TEXTURE_MAPPER_GL)
136     OwnPtr<RedirectedXCompositeWindow> redirectedWindow;
137 #endif
138 };
139
140 WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
141
142 static void webkitWebViewBaseNotifyResizerSize(WebKitWebViewBase* webViewBase)
143 {
144     WebKitWebViewBasePrivate* priv = webViewBase->priv;
145     if (!priv->toplevelOnScreenWindow)
146         return;
147
148     gboolean resizerVisible;
149     g_object_get(G_OBJECT(priv->toplevelOnScreenWindow), "resize-grip-visible", &resizerVisible, NULL);
150
151     IntSize resizerSize;
152     if (resizerVisible) {
153         GdkRectangle resizerRect;
154         gtk_window_get_resize_grip_area(priv->toplevelOnScreenWindow, &resizerRect);
155         GdkRectangle allocation;
156         gtk_widget_get_allocation(GTK_WIDGET(webViewBase), &allocation);
157         if (gdk_rectangle_intersect(&resizerRect, &allocation, 0))
158             resizerSize = IntSize(resizerRect.width, resizerRect.height);
159     }
160
161     if (resizerSize != priv->resizerSize) {
162         priv->resizerSize = resizerSize;
163         priv->pageProxy->setWindowResizerSize(resizerSize);
164     }
165 }
166
167 static void toplevelWindowResizeGripVisibilityChanged(GObject*, GParamSpec*, WebKitWebViewBase* webViewBase)
168 {
169     webkitWebViewBaseNotifyResizerSize(webViewBase);
170 }
171
172 static gboolean toplevelWindowFocusInEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
173 {
174     WebKitWebViewBasePrivate* priv = webViewBase->priv;
175     if (!priv->isInWindowActive) {
176         priv->isInWindowActive = true;
177         priv->pageProxy->viewStateDidChange(ViewState::WindowIsActive);
178     }
179
180     return FALSE;
181 }
182
183 static gboolean toplevelWindowFocusOutEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
184 {
185     WebKitWebViewBasePrivate* priv = webViewBase->priv;
186     if (priv->isInWindowActive) {
187         priv->isInWindowActive = false;
188         priv->pageProxy->viewStateDidChange(ViewState::WindowIsActive);
189     }
190
191     return FALSE;
192 }
193
194 static gboolean toplevelWindowVisibilityEvent(GtkWidget*, GdkEventVisibility* visibilityEvent, WebKitWebViewBase* webViewBase)
195 {
196     WebKitWebViewBasePrivate* priv = webViewBase->priv;
197     bool isWindowVisible = visibilityEvent->state != GDK_VISIBILITY_FULLY_OBSCURED;
198     if (priv->isWindowVisible != isWindowVisible) {
199         priv->isWindowVisible = isWindowVisible;
200         priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
201     }
202
203     return FALSE;
204 }
205
206 static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webViewBase, GtkWindow* window)
207 {
208     WebKitWebViewBasePrivate* priv = webViewBase->priv;
209     if (priv->toplevelOnScreenWindow == window)
210         return;
211
212     if (priv->toplevelResizeGripVisibilityID) {
213         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelResizeGripVisibilityID);
214         priv->toplevelResizeGripVisibilityID = 0;
215     }
216     if (priv->toplevelFocusInEventID) {
217         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusInEventID);
218         priv->toplevelFocusInEventID = 0;
219     }
220     if (priv->toplevelFocusOutEventID) {
221         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelFocusOutEventID);
222         priv->toplevelFocusOutEventID = 0;
223     }
224     if (priv->toplevelVisibilityEventID) {
225         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelVisibilityEventID);
226         priv->toplevelVisibilityEventID = 0;
227     }
228
229     priv->toplevelOnScreenWindow = window;
230     priv->pageProxy->viewStateDidChange(ViewState::IsInWindow);
231     if (!priv->toplevelOnScreenWindow)
232         return;
233
234     webkitWebViewBaseNotifyResizerSize(webViewBase);
235
236     priv->toplevelResizeGripVisibilityID =
237         g_signal_connect(priv->toplevelOnScreenWindow, "notify::resize-grip-visible",
238                          G_CALLBACK(toplevelWindowResizeGripVisibilityChanged), webViewBase);
239     priv->toplevelFocusInEventID =
240         g_signal_connect(priv->toplevelOnScreenWindow, "focus-in-event",
241                          G_CALLBACK(toplevelWindowFocusInEvent), webViewBase);
242     priv->toplevelFocusOutEventID =
243         g_signal_connect(priv->toplevelOnScreenWindow, "focus-out-event",
244                          G_CALLBACK(toplevelWindowFocusOutEvent), webViewBase);
245     priv->toplevelVisibilityEventID =
246         g_signal_connect(priv->toplevelOnScreenWindow, "visibility-notify-event",
247                          G_CALLBACK(toplevelWindowVisibilityEvent), webViewBase);
248 }
249
250 static void webkitWebViewBaseRealize(GtkWidget* widget)
251 {
252     gtk_widget_set_realized(widget, TRUE);
253
254     GtkAllocation allocation;
255     gtk_widget_get_allocation(widget, &allocation);
256
257     GdkWindowAttr attributes;
258     attributes.window_type = GDK_WINDOW_CHILD;
259     attributes.x = allocation.x;
260     attributes.y = allocation.y;
261     attributes.width = allocation.width;
262     attributes.height = allocation.height;
263     attributes.wclass = GDK_INPUT_OUTPUT;
264     attributes.visual = gtk_widget_get_visual(widget);
265     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
266         | GDK_EXPOSURE_MASK
267         | GDK_BUTTON_PRESS_MASK
268         | GDK_BUTTON_RELEASE_MASK
269         | GDK_SCROLL_MASK
270         | GDK_SMOOTH_SCROLL_MASK
271         | GDK_POINTER_MOTION_MASK
272         | GDK_KEY_PRESS_MASK
273         | GDK_KEY_RELEASE_MASK
274         | GDK_BUTTON_MOTION_MASK
275         | GDK_BUTTON1_MOTION_MASK
276         | GDK_BUTTON2_MOTION_MASK
277         | GDK_BUTTON3_MOTION_MASK
278         | GDK_TOUCH_MASK;
279
280     gint attributesMask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
281
282     GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributesMask);
283     gtk_widget_set_window(widget, window);
284     gdk_window_set_user_data(window, widget);
285
286     gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
287
288     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
289     GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
290     if (widgetIsOnscreenToplevelWindow(toplevel))
291         webkitWebViewBaseSetToplevelOnScreenWindow(webView, GTK_WINDOW(toplevel));
292 }
293
294 static bool webkitWebViewChildIsInternalWidget(WebKitWebViewBase* webViewBase, GtkWidget* widget)
295 {
296     WebKitWebViewBasePrivate* priv = webViewBase->priv;
297     return widget == priv->inspectorView || widget == priv->authenticationDialog;
298 }
299
300 static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget)
301 {
302     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
303     WebKitWebViewBasePrivate* priv = webView->priv;
304
305     // Internal widgets like the web inspector and authentication dialog have custom
306     // allocations so we don't need to add them to our list of children.
307     if (!webkitWebViewChildIsInternalWidget(webView, widget)) {
308         GtkAllocation childAllocation;
309         gtk_widget_get_allocation(widget, &childAllocation);
310         priv->children.set(widget, childAllocation);
311     }
312
313     gtk_widget_set_parent(widget, GTK_WIDGET(container));
314 }
315
316 void webkitWebViewBaseAddAuthenticationDialog(WebKitWebViewBase* webViewBase, GtkWidget* dialog)
317 {
318     WebKitWebViewBasePrivate* priv = webViewBase->priv;
319     priv->authenticationDialog = dialog;
320     gtk_container_add(GTK_CONTAINER(webViewBase), dialog);
321     gtk_widget_show(dialog);
322
323     // We need to draw the shadow over the widget.
324     gtk_widget_queue_draw(GTK_WIDGET(webViewBase));
325 }
326
327 void webkitWebViewBaseAddWebInspector(WebKitWebViewBase* webViewBase, GtkWidget* inspector, AttachmentSide attachmentSide)
328 {
329     if (webViewBase->priv->inspectorView == inspector && webViewBase->priv->inspectorAttachmentSide == attachmentSide)
330         return;
331
332     webViewBase->priv->inspectorAttachmentSide = attachmentSide;
333
334     if (webViewBase->priv->inspectorView == inspector) {
335         gtk_widget_queue_resize(GTK_WIDGET(webViewBase));
336         return;
337     }
338
339     webViewBase->priv->inspectorView = inspector;
340     gtk_container_add(GTK_CONTAINER(webViewBase), inspector);
341 }
342
343 static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget)
344 {
345     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
346     WebKitWebViewBasePrivate* priv = webView->priv;
347     GtkWidget* widgetContainer = GTK_WIDGET(container);
348
349     gboolean wasVisible = gtk_widget_get_visible(widget);
350     gtk_widget_unparent(widget);
351
352     if (priv->inspectorView == widget) {
353         priv->inspectorView = 0;
354         priv->inspectorViewSize = 0;
355     } else if (priv->authenticationDialog == widget) {
356         priv->authenticationDialog = 0;
357     } else {
358         ASSERT(priv->children.contains(widget));
359         priv->children.remove(widget);
360     }
361     if (wasVisible && gtk_widget_get_visible(widgetContainer))
362         gtk_widget_queue_resize(widgetContainer);
363 }
364
365 static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData)
366 {
367     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
368     WebKitWebViewBasePrivate* priv = webView->priv;
369
370     WebKitWebViewChildrenMap children = priv->children;
371     WebKitWebViewChildrenMap::const_iterator end = children.end();
372     for (WebKitWebViewChildrenMap::const_iterator current = children.begin(); current != end; ++current)
373         (*callback)(current->key, callbackData);
374
375     if (includeInternals && priv->inspectorView)
376         (*callback)(priv->inspectorView, callbackData);
377
378     if (includeInternals && priv->authenticationDialog)
379         (*callback)(priv->authenticationDialog, callbackData);
380 }
381
382 void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect)
383 {
384     const IntRect& geometry = webView->priv->children.get(child);
385     if (geometry == childRect)
386         return;
387
388     webView->priv->children.set(child, childRect);
389     gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView));
390 }
391
392 static void webkitWebViewBaseDispose(GObject* gobject)
393 {
394     webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(gobject), 0);
395     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->dispose(gobject);
396 }
397
398 static void webkitWebViewBaseConstructed(GObject* object)
399 {
400     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->constructed(object);
401
402     GtkWidget* viewWidget = GTK_WIDGET(object);
403     gtk_widget_set_can_focus(viewWidget, TRUE);
404     gtk_drag_dest_set(viewWidget, static_cast<GtkDestDefaults>(0), 0, 0,
405                       static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
406     gtk_drag_dest_set_target_list(viewWidget, PasteboardHelper::defaultPasteboardHelper()->targetList());
407
408     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(object)->priv;
409     priv->pageClient = PageClientImpl::create(viewWidget);
410     priv->dragAndDropHelper.setWidget(viewWidget);
411
412 #if USE(TEXTURE_MAPPER_GL) && defined(GDK_WINDOWING_X11)
413     GdkDisplay* display = gdk_display_manager_get_default_display(gdk_display_manager_get());
414     if (GDK_IS_X11_DISPLAY(display)) {
415         priv->redirectedWindow = RedirectedXCompositeWindow::create(IntSize(1, 1), RedirectedXCompositeWindow::DoNotCreateGLContext);
416         if (priv->redirectedWindow)
417             priv->redirectedWindow->setDamageNotifyCallback(redirectedWindowDamagedCallback, object);
418     }
419 #endif
420
421     priv->authenticationDialog = 0;
422 }
423
424 #if USE(TEXTURE_MAPPER_GL)
425 static bool webkitWebViewRenderAcceleratedCompositingResults(WebKitWebViewBase* webViewBase, DrawingAreaProxyImpl* drawingArea, cairo_t* cr, GdkRectangle* clipRect)
426 {
427     if (!drawingArea->isInAcceleratedCompositingMode())
428         return false;
429
430     // To avoid flashes when initializing accelerated compositing for the first
431     // time, we wait until we know there's a frame ready before rendering.
432     WebKitWebViewBasePrivate* priv = webViewBase->priv;
433     if (!priv->redirectedWindow)
434         return false;
435
436     cairo_rectangle(cr, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
437     cairo_surface_t* surface = priv->redirectedWindow->cairoSurfaceForWidget(GTK_WIDGET(webViewBase));
438     cairo_set_source_surface(cr, surface, 0, 0);
439     cairo_fill(cr);
440     return true;
441 }
442 #endif
443
444 static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
445 {
446     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
447     DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(webViewBase->priv->pageProxy->drawingArea());
448     if (!drawingArea)
449         return FALSE;
450
451     GdkRectangle clipRect;
452     if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
453         return FALSE;
454
455 #if USE(TEXTURE_MAPPER_GL)
456     if (webkitWebViewRenderAcceleratedCompositingResults(webViewBase, drawingArea, cr, &clipRect))
457         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
458 #endif
459
460     WebCore::Region unpaintedRegion; // This is simply unused.
461     drawingArea->paint(cr, clipRect, unpaintedRegion);
462
463     if (webViewBase->priv->authenticationDialog) {
464         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
465         cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
466         cairo_paint(cr);
467     }
468
469     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->draw(widget, cr);
470
471     return FALSE;
472 }
473
474 static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData)
475 {
476     if (!gtk_widget_get_visible(child))
477         return;
478
479     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData);
480     WebKitWebViewBasePrivate* priv = webViewBase->priv;
481     const IntRect& geometry = priv->children.get(child);
482     if (geometry.isEmpty())
483         return;
484
485     GtkAllocation childAllocation = geometry;
486     gtk_widget_size_allocate(child, &childAllocation);
487     priv->children.set(child, IntRect());
488 }
489
490 static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation, bool sizeChanged)
491 {
492     gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase);
493
494     IntRect viewRect(allocation->x, allocation->y, allocation->width, allocation->height);
495     WebKitWebViewBasePrivate* priv = webViewBase->priv;
496     if (priv->inspectorView) {
497         GtkAllocation childAllocation = viewRect;
498
499         if (priv->inspectorAttachmentSide == AttachmentSideBottom) {
500             int inspectorViewHeight = std::min(static_cast<int>(priv->inspectorViewSize), allocation->height);
501             childAllocation.x = 0;
502             childAllocation.y = allocation->height - inspectorViewHeight;
503             childAllocation.height = inspectorViewHeight;
504             viewRect.setHeight(std::max(allocation->height - inspectorViewHeight, 1));
505         } else {
506             int inspectorViewWidth = std::min(static_cast<int>(priv->inspectorViewSize), allocation->width);
507             childAllocation.y = 0;
508             childAllocation.x = allocation->width - inspectorViewWidth;
509             childAllocation.width = inspectorViewWidth;
510             viewRect.setWidth(std::max(allocation->width - inspectorViewWidth, 1));
511         }
512
513         gtk_widget_size_allocate(priv->inspectorView, &childAllocation);
514     }
515
516     // The authentication dialog is centered in the view rect, which means that it
517     // never overlaps the web inspector. Thus, we need to calculate the allocation here
518     // after calculating the inspector allocation.
519     if (priv->authenticationDialog) {
520         GtkRequisition naturalSize;
521         gtk_widget_get_preferred_size(priv->authenticationDialog, 0, &naturalSize);
522
523         GtkAllocation childAllocation = {
524             (viewRect.width() - naturalSize.width) / 2,
525             (viewRect.height() - naturalSize.height) / 2,
526             naturalSize.width,
527             naturalSize.height
528         };
529         gtk_widget_size_allocate(priv->authenticationDialog, &childAllocation);
530     }
531
532 #if USE(TEXTURE_MAPPER_GL)
533     if (sizeChanged && webViewBase->priv->redirectedWindow)
534         webViewBase->priv->redirectedWindow->resize(viewRect.size());
535 #endif
536
537     if (priv->pageProxy->drawingArea())
538         priv->pageProxy->drawingArea()->setSize(viewRect.size(), IntSize(), IntSize());
539
540     webkitWebViewBaseNotifyResizerSize(webViewBase);
541 }
542
543 static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allocation)
544 {
545     bool sizeChanged = gtk_widget_get_allocated_width(widget) != allocation->width
546                        || gtk_widget_get_allocated_height(widget) != allocation->height;
547
548     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->size_allocate(widget, allocation);
549
550     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
551     if (sizeChanged && !gtk_widget_get_mapped(widget)) {
552         webViewBase->priv->needsResizeOnMap = true;
553         return;
554     }
555
556     resizeWebKitWebViewBaseFromAllocation(webViewBase, allocation, sizeChanged);
557 }
558
559 static void webkitWebViewBaseMap(GtkWidget* widget)
560 {
561     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->map(widget);
562
563     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
564     WebKitWebViewBasePrivate* priv = webViewBase->priv;
565     if (!priv->isVisible) {
566         priv->isVisible = true;
567         priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
568     }
569
570     if (!priv->needsResizeOnMap)
571         return;
572
573     GtkAllocation allocation;
574     gtk_widget_get_allocation(widget, &allocation);
575     resizeWebKitWebViewBaseFromAllocation(webViewBase, &allocation, true /* sizeChanged */);
576     priv->needsResizeOnMap = false;
577 }
578
579 static void webkitWebViewBaseUnmap(GtkWidget* widget)
580 {
581     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unmap(widget);
582
583     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
584     if (priv->isVisible) {
585         priv->isVisible = false;
586         priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
587     }
588 }
589
590 static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
591 {
592     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
593     webkitWebViewBaseSetFocus(webViewBase, true);
594     webViewBase->priv->inputMethodFilter.notifyFocusedIn();
595
596     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_in_event(widget, event);
597 }
598
599 static gboolean webkitWebViewBaseFocusOutEvent(GtkWidget* widget, GdkEventFocus* event)
600 {
601     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
602     webkitWebViewBaseSetFocus(webViewBase, false);
603     webViewBase->priv->inputMethodFilter.notifyFocusedOut();
604
605     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus_out_event(widget, event);
606 }
607
608 static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* event)
609 {
610     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
611     WebKitWebViewBasePrivate* priv = webViewBase->priv;
612
613     if (priv->authenticationDialog)
614         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, event);
615
616 #if ENABLE(FULLSCREEN_API)
617     if (priv->fullScreenModeActive) {
618         switch (event->keyval) {
619         case GDK_KEY_Escape:
620         case GDK_KEY_f:
621         case GDK_KEY_F:
622             webkitWebViewBaseRequestExitFullScreen(webViewBase);
623             return TRUE;
624         default:
625             break;
626         }
627     }
628 #endif
629
630     // Since WebProcess key event handling is not synchronous, handle the event in two passes.
631     // When WebProcess processes the input event, it will call PageClientImpl::doneWithKeyEvent
632     // with event handled status which determines whether to pass the input event to parent or not
633     // using gtk_main_do_event().
634     if (priv->shouldForwardNextKeyEvent) {
635         priv->shouldForwardNextKeyEvent = FALSE;
636         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_press_event(widget, event);
637     }
638     priv->inputMethodFilter.filterKeyEvent(event);
639     return TRUE;
640 }
641
642 static gboolean webkitWebViewBaseKeyReleaseEvent(GtkWidget* widget, GdkEventKey* event)
643 {
644     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
645     WebKitWebViewBasePrivate* priv = webViewBase->priv;
646
647     if (priv->shouldForwardNextKeyEvent) {
648         priv->shouldForwardNextKeyEvent = FALSE;
649         return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->key_release_event(widget, event);
650     }
651     priv->inputMethodFilter.filterKeyEvent(event);
652     return TRUE;
653 }
654
655 static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventButton* buttonEvent)
656 {
657     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
658     WebKitWebViewBasePrivate* priv = webViewBase->priv;
659
660     if (priv->authenticationDialog)
661         return TRUE;
662
663     gtk_widget_grab_focus(widget);
664
665     priv->inputMethodFilter.notifyMouseButtonPress();
666
667     if (!priv->clickCounter.shouldProcessButtonEvent(buttonEvent))
668         return TRUE;
669
670     // If it's a right click event save it as a possible context menu event.
671     if (buttonEvent->button == 3)
672         priv->contextMenuEvent.reset(gdk_event_copy(reinterpret_cast<GdkEvent*>(buttonEvent)));
673     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent),
674                                                      priv->clickCounter.clickCountForGdkButtonEvent(widget, buttonEvent)));
675     return TRUE;
676 }
677
678 static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventButton* event)
679 {
680     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
681     WebKitWebViewBasePrivate* priv = webViewBase->priv;
682
683     if (priv->authenticationDialog)
684         return TRUE;
685
686     gtk_widget_grab_focus(widget);
687     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
688
689     return TRUE;
690 }
691
692 static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* event)
693 {
694     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
695     WebKitWebViewBasePrivate* priv = webViewBase->priv;
696
697     if (priv->authenticationDialog)
698         return TRUE;
699
700     priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(reinterpret_cast<GdkEvent*>(event)));
701
702     return TRUE;
703 }
704
705 static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event)
706 {
707     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
708     WebKitWebViewBasePrivate* priv = webViewBase->priv;
709
710     if (priv->authenticationDialog)
711         return TRUE;
712
713     priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */));
714
715     return TRUE;
716 }
717
718 static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* event)
719 {
720     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
721
722     if (priv->authenticationDialog)
723         return TRUE;
724
725     priv->touchContext.handleEvent(reinterpret_cast<GdkEvent*>(event));
726     priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), priv->touchContext));
727
728     return TRUE;
729 }
730
731 static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint x, gint y, gboolean keyboardMode, GtkTooltip* tooltip)
732 {
733     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
734
735     if (keyboardMode) {
736         // TODO: https://bugs.webkit.org/show_bug.cgi?id=61732.
737         notImplemented();
738         return FALSE;
739     }
740
741     if (priv->tooltipText.length() <= 0)
742         return FALSE;
743
744     if (!priv->tooltipArea.isEmpty()) {
745         GdkRectangle area = priv->tooltipArea;
746         gtk_tooltip_set_tip_area(tooltip, &area);
747     } else
748         gtk_tooltip_set_tip_area(tooltip, 0);
749     gtk_tooltip_set_text(tooltip, priv->tooltipText.data());
750
751     return TRUE;
752 }
753
754 #if ENABLE(DRAG_SUPPORT)
755 static void webkitWebViewBaseDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint time)
756 {
757     WEBKIT_WEB_VIEW_BASE(widget)->priv->dragAndDropHelper.handleGetDragData(context, selectionData, info);
758 }
759
760 static void webkitWebViewBaseDragEnd(GtkWidget* widget, GdkDragContext* context)
761 {
762     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
763     if (!webViewBase->priv->dragAndDropHelper.handleDragEnd(context))
764         return;
765
766     GdkDevice* device = gdk_drag_context_get_device(context);
767     int x = 0, y = 0;
768     gdk_device_get_window_at_position(device, &x, &y);
769     int xRoot = 0, yRoot = 0;
770     gdk_device_get_position(device, 0, &xRoot, &yRoot);
771     webViewBase->priv->pageProxy->dragEnded(IntPoint(x, y), IntPoint(xRoot, yRoot),
772                                             gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
773 }
774
775 static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint x, gint y, GtkSelectionData* selectionData, guint info, guint time)
776 {
777     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
778     IntPoint position;
779     DataObjectGtk* dataObject = webViewBase->priv->dragAndDropHelper.handleDragDataReceived(context, selectionData, info, position);
780     if (!dataObject)
781         return;
782
783     DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(widget, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
784     webViewBase->priv->pageProxy->resetDragOperation();
785     webViewBase->priv->pageProxy->dragEntered(dragData);
786     DragOperation operation = webViewBase->priv->pageProxy->dragSession().operation;
787     gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
788 }
789 #endif // ENABLE(DRAG_SUPPORT)
790
791 static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget)
792 {
793     // If the socket has already been created and embedded a plug ID, return it.
794     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
795     if (priv->accessible && atk_socket_is_occupied(ATK_SOCKET(priv->accessible.get())))
796         return priv->accessible.get();
797
798     // Create the accessible object and associate it to the widget.
799     if (!priv->accessible) {
800         priv->accessible = adoptGRef(ATK_OBJECT(webkitWebViewBaseAccessibleNew(widget)));
801
802         // Set the parent not to break bottom-up navigation.
803         GtkWidget* parentWidget = gtk_widget_get_parent(widget);
804         AtkObject* axParent = parentWidget ? gtk_widget_get_accessible(parentWidget) : 0;
805         if (axParent)
806             atk_object_set_parent(priv->accessible.get(), axParent);
807     }
808
809     // Try to embed the plug in the socket, if posssible.
810     String plugID = priv->pageProxy->accessibilityPlugID();
811     if (plugID.isNull())
812         return priv->accessible.get();
813
814     atk_socket_embed(ATK_SOCKET(priv->accessible.get()), const_cast<gchar*>(plugID.utf8().data()));
815
816     return priv->accessible.get();
817 }
818
819 #if ENABLE(DRAG_SUPPORT)
820 static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
821 {
822     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
823     IntPoint position(x, y);
824     DataObjectGtk* dataObject = webViewBase->priv->dragAndDropHelper.handleDragMotion(context, position, time);
825     if (!dataObject)
826         return TRUE;
827
828     DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(widget, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
829     webViewBase->priv->pageProxy->dragUpdated(dragData);
830     DragOperation operation = webViewBase->priv->pageProxy->dragSession().operation;
831     gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time);
832     return TRUE;
833 }
834
835 static void dragExitedCallback(GtkWidget* widget, DragData& dragData, bool dropHappened)
836 {
837     // Don't call dragExited if we have just received a drag-drop signal. This
838     // happens in the case of a successful drop onto the view.
839     if (dropHappened)
840         return;
841
842     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
843     webViewBase->priv->pageProxy->dragExited(dragData);
844     webViewBase->priv->pageProxy->resetDragOperation();
845 }
846
847 static void webkitWebViewBaseDragLeave(GtkWidget* widget, GdkDragContext* context, guint time)
848 {
849     WEBKIT_WEB_VIEW_BASE(widget)->priv->dragAndDropHelper.handleDragLeave(context, dragExitedCallback);
850 }
851
852 static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time)
853 {
854     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
855     DataObjectGtk* dataObject = webViewBase->priv->dragAndDropHelper.handleDragDrop(context);
856     if (!dataObject)
857         return FALSE;
858
859     IntPoint position(x, y);
860     DragData dragData(dataObject, position, convertWidgetPointToScreenPoint(widget, position), gdkDragActionToDragOperation(gdk_drag_context_get_actions(context)));
861     SandboxExtension::Handle handle;
862     SandboxExtension::HandleArray sandboxExtensionForUpload;
863     webViewBase->priv->pageProxy->performDrag(dragData, String(), handle, sandboxExtensionForUpload);
864     gtk_drag_finish(context, TRUE, FALSE, time);
865     return TRUE;
866 }
867 #endif // ENABLE(DRAG_SUPPORT)
868
869 static void webkitWebViewBaseParentSet(GtkWidget* widget, GtkWidget* oldParent)
870 {
871     if (!gtk_widget_get_parent(widget))
872         webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), 0);
873 }
874
875 static gboolean webkitWebViewBaseFocus(GtkWidget* widget, GtkDirectionType direction)
876 {
877     // If the authentication dialog is active, we need to forward focus events there. This
878     // ensures that you can tab between elements in the box.
879     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
880     if (priv->authenticationDialog) {
881         gboolean returnValue;
882         g_signal_emit_by_name(priv->authenticationDialog, "focus", direction, &returnValue);
883         return returnValue;
884     }
885
886     return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus(widget, direction);
887 }
888
889 static void webkitWebViewBaseDestroy(GtkWidget* widget)
890 {
891     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
892     if (priv->authenticationDialog)
893         gtk_widget_destroy(priv->authenticationDialog);
894
895     GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->destroy(widget);
896 }
897
898 static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebViewBaseClass)
899 {
900     GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(webkitWebViewBaseClass);
901     widgetClass->realize = webkitWebViewBaseRealize;
902     widgetClass->draw = webkitWebViewBaseDraw;
903     widgetClass->size_allocate = webkitWebViewBaseSizeAllocate;
904     widgetClass->map = webkitWebViewBaseMap;
905     widgetClass->unmap = webkitWebViewBaseUnmap;
906     widgetClass->focus = webkitWebViewBaseFocus;
907     widgetClass->focus_in_event = webkitWebViewBaseFocusInEvent;
908     widgetClass->focus_out_event = webkitWebViewBaseFocusOutEvent;
909     widgetClass->key_press_event = webkitWebViewBaseKeyPressEvent;
910     widgetClass->key_release_event = webkitWebViewBaseKeyReleaseEvent;
911     widgetClass->button_press_event = webkitWebViewBaseButtonPressEvent;
912     widgetClass->button_release_event = webkitWebViewBaseButtonReleaseEvent;
913     widgetClass->scroll_event = webkitWebViewBaseScrollEvent;
914     widgetClass->motion_notify_event = webkitWebViewBaseMotionNotifyEvent;
915     widgetClass->touch_event = webkitWebViewBaseTouchEvent;
916     widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
917 #if ENABLE(DRAG_SUPPORT)
918     widgetClass->drag_end = webkitWebViewBaseDragEnd;
919     widgetClass->drag_data_get = webkitWebViewBaseDragDataGet;
920     widgetClass->drag_motion = webkitWebViewBaseDragMotion;
921     widgetClass->drag_leave = webkitWebViewBaseDragLeave;
922     widgetClass->drag_drop = webkitWebViewBaseDragDrop;
923     widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
924 #endif // ENABLE(DRAG_SUPPORT)
925     widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
926     widgetClass->parent_set = webkitWebViewBaseParentSet;
927     widgetClass->destroy = webkitWebViewBaseDestroy;
928
929     GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);
930     gobjectClass->constructed = webkitWebViewBaseConstructed;
931     gobjectClass->dispose = webkitWebViewBaseDispose;
932
933     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass);
934     containerClass->add = webkitWebViewBaseContainerAdd;
935     containerClass->remove = webkitWebViewBaseContainerRemove;
936     containerClass->forall = webkitWebViewBaseContainerForall;
937 }
938
939 WebKitWebViewBase* webkitWebViewBaseCreate(WebContext* context, WebPageGroup* pageGroup)
940 {
941     WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, NULL));
942     webkitWebViewBaseCreateWebPage(webkitWebViewBase, context, pageGroup);
943     return webkitWebViewBase;
944 }
945
946 GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase* webkitWebViewBase)
947 {
948     return webkitWebViewBase->priv->inputMethodFilter.context();
949 }
950
951 WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
952 {
953     return webkitWebViewBase->priv->pageProxy.get();
954 }
955
956 void webkitWebViewBaseUpdatePreferences(WebKitWebViewBase* webkitWebViewBase)
957 {
958     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
959
960 #if USE(TEXTURE_MAPPER_GL)
961     if (priv->redirectedWindow)
962         return;
963 #endif
964
965     priv->pageProxy->pageGroup().preferences().setAcceleratedCompositingEnabled(false);
966 }
967
968 void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WebContext* context, WebPageGroup* pageGroup)
969 {
970     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
971
972     WebPageConfiguration webPageConfiguration;
973     webPageConfiguration.pageGroup = pageGroup;
974     priv->pageProxy = context->createWebPage(*priv->pageClient, std::move(webPageConfiguration));
975     priv->pageProxy->initializeWebPage();
976
977 #if USE(TEXTURE_MAPPER_GL)
978     if (priv->redirectedWindow)
979         priv->pageProxy->setAcceleratedCompositingWindowId(priv->redirectedWindow->windowId());
980 #endif
981
982     webkitWebViewBaseUpdatePreferences(webkitWebViewBase);
983
984     // This must happen here instead of the instance initializer, because the input method
985     // filter must have access to the page.
986     priv->inputMethodFilter.setWebView(webkitWebViewBase);
987 }
988
989 void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip)
990 {
991     WebKitWebViewBasePrivate* priv = webViewBase->priv;
992     if (tooltip && tooltip[0] != '\0') {
993         priv->tooltipText = tooltip;
994         gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), TRUE);
995     } else {
996         priv->tooltipText = "";
997         gtk_widget_set_has_tooltip(GTK_WIDGET(webViewBase), FALSE);
998     }
999
1000     gtk_widget_trigger_tooltip_query(GTK_WIDGET(webViewBase));
1001 }
1002
1003 void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase* webViewBase, const IntRect& tooltipArea)
1004 {
1005     webViewBase->priv->tooltipArea = tooltipArea;
1006 }
1007
1008 #if ENABLE(DRAG_SUPPORT)
1009 void webkitWebViewBaseStartDrag(WebKitWebViewBase* webViewBase, const DragData& dragData, PassRefPtr<ShareableBitmap> dragImage)
1010 {
1011     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1012
1013     RefPtr<DataObjectGtk> dataObject = adoptRef(dragData.platformData());
1014     GRefPtr<GtkTargetList> targetList = adoptGRef(PasteboardHelper::defaultPasteboardHelper()->targetListForDataObject(dataObject.get()));
1015     GUniquePtr<GdkEvent> currentEvent(gtk_get_current_event());
1016     GdkDragContext* context = gtk_drag_begin(GTK_WIDGET(webViewBase),
1017                                              targetList.get(),
1018                                              dragOperationToGdkDragActions(dragData.draggingSourceOperationMask()),
1019                                              1, /* button */
1020                                              currentEvent.get());
1021     priv->dragAndDropHelper.startedDrag(context, dataObject.get());
1022
1023
1024     // A drag starting should prevent a double-click from happening. This might
1025     // happen if a drag is followed very quickly by another click (like in the DRT).
1026     priv->clickCounter.reset();
1027
1028     if (dragImage) {
1029         RefPtr<cairo_surface_t> image(dragImage->createCairoSurface());
1030         priv->dragIcon.setImage(image.get());
1031         priv->dragIcon.useForDrag(context);
1032     } else
1033         gtk_drag_set_icon_default(context);
1034 }
1035 #endif // ENABLE(DRAG_SUPPORT)
1036
1037 void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase)
1038 {
1039     webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE;
1040 }
1041
1042 void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase)
1043 {
1044 #if ENABLE(FULLSCREEN_API)
1045     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1046     if (priv->fullScreenModeActive)
1047         return;
1048
1049     if (!priv->fullScreenClient.willEnterFullScreen())
1050         return;
1051
1052     WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1053     fullScreenManagerProxy->willEnterFullScreen();
1054
1055     GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1056     if (gtk_widget_is_toplevel(topLevelWindow))
1057         gtk_window_fullscreen(GTK_WINDOW(topLevelWindow));
1058     fullScreenManagerProxy->didEnterFullScreen();
1059     priv->fullScreenModeActive = true;
1060 #endif
1061 }
1062
1063 void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase)
1064 {
1065 #if ENABLE(FULLSCREEN_API)
1066     WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
1067     if (!priv->fullScreenModeActive)
1068         return;
1069
1070     if (!priv->fullScreenClient.willExitFullScreen())
1071         return;
1072
1073     WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager();
1074     fullScreenManagerProxy->willExitFullScreen();
1075
1076     GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase));
1077     if (gtk_widget_is_toplevel(topLevelWindow))
1078         gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow));
1079     fullScreenManagerProxy->didExitFullScreen();
1080     priv->fullScreenModeActive = false;
1081 #endif
1082 }
1083
1084 void webkitWebViewBaseRequestExitFullScreen(WebKitWebViewBase* webkitWebViewBase)
1085 {
1086 #if ENABLE(FULLSCREEN_API)
1087     webkitWebViewBase->priv->pageProxy->fullScreenManager()->requestExitFullScreen();
1088 #endif
1089 }
1090
1091 void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase* webkitWebViewBase, const WKFullScreenClientGtkBase* wkClient)
1092 {
1093     webkitWebViewBase->priv->fullScreenClient.initialize(wkClient);
1094 }
1095
1096 void webkitWebViewBaseSetInspectorViewSize(WebKitWebViewBase* webkitWebViewBase, unsigned size)
1097 {
1098     if (webkitWebViewBase->priv->inspectorViewSize == size)
1099         return;
1100     webkitWebViewBase->priv->inspectorViewSize = size;
1101     if (webkitWebViewBase->priv->inspectorView)
1102         gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase));
1103 }
1104
1105 void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase, WebContextMenuProxyGtk* contextMenuProxy)
1106 {
1107     webkitWebViewBase->priv->activeContextMenuProxy = contextMenuProxy;
1108 }
1109
1110 WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase* webkitWebViewBase)
1111 {
1112     return webkitWebViewBase->priv->activeContextMenuProxy;
1113 }
1114
1115 GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebViewBase)
1116 {
1117     return webkitWebViewBase->priv->contextMenuEvent.release();
1118 }
1119
1120 #if USE(TEXTURE_MAPPER_GL)
1121 void redirectedWindowDamagedCallback(void* data)
1122 {
1123     gtk_widget_queue_draw(GTK_WIDGET(data));
1124 }
1125 #endif
1126
1127 void webkitWebViewBaseSetFocus(WebKitWebViewBase* webViewBase, bool focused)
1128 {
1129     WebKitWebViewBasePrivate* priv = webViewBase->priv;
1130     if (priv->isFocused == focused)
1131         return;
1132
1133     unsigned viewStateFlags = ViewState::IsFocused;
1134     priv->isFocused = focused;
1135
1136     // If the view has received the focus and the window is not active
1137     // mark the current window as active now. This can happen if the
1138     // toplevel window is a GTK_WINDOW_POPUP and the focus has been
1139     // set programatically like WebKitTestRunner does, because POPUP
1140     // can't be focused.
1141     if (priv->isFocused && !priv->isInWindowActive) {
1142         priv->isInWindowActive = true;
1143         viewStateFlags |= ViewState::WindowIsActive;
1144     }
1145     priv->pageProxy->viewStateDidChange(viewStateFlags);
1146 }
1147
1148 bool webkitWebViewBaseIsInWindowActive(WebKitWebViewBase* webViewBase)
1149 {
1150     return webViewBase->priv->isInWindowActive;
1151 }
1152
1153 bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
1154 {
1155     return webViewBase->priv->isFocused;
1156 }
1157
1158 bool webkitWebViewBaseIsVisible(WebKitWebViewBase* webViewBase)
1159 {
1160     return webViewBase->priv->isVisible;
1161 }
1162
1163 bool webkitWebViewBaseIsInWindow(WebKitWebViewBase* webViewBase)
1164 {
1165     return webViewBase->priv->toplevelOnScreenWindow;
1166 }
1167
1168 bool webkitWebViewBaseIsWindowVisible(WebKitWebViewBase* webViewBase)
1169 {
1170     return webViewBase->priv->isWindowVisible;
1171 }
1172
1173 void webkitWebViewBaseSetDownloadRequestHandler(WebKitWebViewBase* webViewBase, WebKitWebViewBaseDownloadRequestHandler downloadHandler)
1174 {
1175     webViewBase->priv->downloadHandler = downloadHandler;
1176 }
1177
1178 void webkitWebViewBaseHandleDownloadRequest(WebKitWebViewBase* webViewBase, DownloadProxy* download)
1179 {
1180     if (webViewBase->priv->downloadHandler)
1181         webViewBase->priv->downloadHandler(webViewBase, download);
1182 }
1183
1184 void webkitWebViewBaseSetInputMethodState(WebKitWebViewBase* webkitWebViewBase, bool enabled)
1185 {
1186     webkitWebViewBase->priv->inputMethodFilter.setEnabled(enabled);
1187 }
1188
1189 void webkitWebViewBaseUpdateTextInputState(WebKitWebViewBase* webkitWebViewBase)
1190 {
1191     webkitWebViewBase->priv->inputMethodFilter.setCursorRect(webkitWebViewBase->priv->pageProxy->editorState().cursorRect);
1192 }
1193
1194 void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
1195 {
1196     webkitWebViewBase->priv->clickCounter.reset();
1197 }