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