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