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