Source/WebKit/gtk/ChangeLog

 12011-09-07 Carlos Garcia Campos <cgarcia@igalia.com>
 2
 3 [GTK] Add a signal to allow applications to handle its own context menu
 4 https://bugs.webkit.org/show_bug.cgi?id=49904
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * tests/testhittestresult.c:
 9 (load_status_cb): Test x, y properties of WebKitHitTestResult.
 10 * webkit/webkithittestresult.cpp:
 11 (webkit_hit_test_result_get_property):
 12 (webkit_hit_test_result_set_property):
 13 (webkit_hit_test_result_class_init): Add x and y construct only
 14 properties to keep the coordinates of the event relative to view's
 15 widget.
 16 (WebKit::kit):
 17 * webkit/webkitwebsettings.cpp:
 18 (webkit_web_settings_class_init): Mark enable-default-context-menu
 19 property as deprecated.
 20 * webkit/webkitwebview.cpp:
 21 (prepareMouseEventForFrame):
 22 (defaultContextMenuEnabled): Helper function to check whether
 23 default context menu setting is enabled or not.
 24 (webkit_web_view_forward_context_menu_event): Emit the new
 25 context-menu signal.
 26 (webkit_web_view_popup_menu_handler):
 27 (webkit_web_view_button_press_event):
 28 (webkit_web_view_class_init): Add new context-menu signal and mark
 29 populate-popup as deprecated.
 30 * webkitmarshal.list:
 31
1322011-08-30 Sheriff Bot <webkit.review.bot@gmail.com>
233
334 Unreviewed, rolling out r94142, r94144, r94145, and r94148.

Source/WebKit/gtk/tests/testhittestresult.c

@@load_status_cb(WebKitWebView* webView,
8383 guint context;
8484 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
8585 WebKitDOMNode* node;
 86 gint x, y;
8687
8788 /* Close enough to 0,0 */
8889 event->button.x = 5;

@@load_status_cb(WebKitWebView* webView,
9899 g_object_get(result, "inner-node", &node, NULL);
99100 g_assert(node);
100101 g_assert(WEBKIT_DOM_IS_NODE(node));
 102
 103 g_object_get(result, "x", &x, "y", &y, NULL);
 104 g_assert_cmpint(x, ==, 5);
 105 g_assert_cmpint(y, ==, 5);
 106
101107 /* We can only test these node types at the moment. In the
102108 * input case there seems to be an extra layer with a DIV on
103109 * top of the input, which gets assigned to the inner-node.

Source/WebKit/gtk/webkit/webkithittestresult.cpp

2121#include "config.h"
2222#include "webkithittestresult.h"
2323
 24#include "Frame.h"
 25#include "FrameView.h"
2426#include "GOwnPtr.h"
2527#include "GRefPtr.h"
2628#include "HitTestResult.h"

@@struct _WebKitHitTestResultPrivate {
4951 char* imageURI;
5052 char* mediaURI;
5153 GRefPtr<WebKitDOMNode> innerNode;
 54 WebCore::IntPoint position;
5255};
5356
5457enum {

@@enum {
5861 PROP_LINK_URI,
5962 PROP_IMAGE_URI,
6063 PROP_MEDIA_URI,
61  PROP_INNER_NODE
 64 PROP_INNER_NODE,
 65 PROP_X,
 66 PROP_Y
6267};
6368
6469static void webkit_hit_test_result_finalize(GObject* object)

@@static void webkit_hit_test_result_get_property(GObject* object, guint propertyI
101106 case PROP_INNER_NODE:
102107 g_value_set_object(value, priv->innerNode.get());
103108 break;
 109 case PROP_X:
 110 g_value_set_int(value, priv->position.x());
 111 break;
 112 case PROP_Y:
 113 g_value_set_int(value, priv->position.y());
 114 break;
104115 default:
105116 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
106117 }

@@static void webkit_hit_test_result_set_property(GObject* object, guint propertyI
130141 case PROP_INNER_NODE:
131142 priv->innerNode = static_cast<WebKitDOMNode*>(g_value_get_object(value));
132143 break;
 144 case PROP_X:
 145 priv->position.setX(g_value_get_int(value));
 146 break;
 147 case PROP_Y:
 148 priv->position.setY(g_value_get_int(value));
 149 break;
133150 default:
134151 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
135152 }

@@static void webkit_hit_test_result_class_init(WebKitHitTestResultClass* webHitTe
225242 WEBKIT_TYPE_DOM_NODE,
226243 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
227244
 245 /**
 246 * WebKitHitTestResult:x:
 247 *
 248 * The x coordintate of the event relative to the view's window.
 249 *
 250 * Since: 1.5.3
 251 */
 252 g_object_class_install_property(objectClass, PROP_X,
 253 g_param_spec_int("x",
 254 _("X coordinate"),
 255 _("The x coordintate of the event relative to the view's window."),
 256 G_MININT, G_MAXINT, 0,
 257 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
 258
 259 /**
 260 * WebKitHitTestResult:y:
 261 *
 262 * The x coordintate of the event relative to the view's window.
 263 *
 264 * Since: 1.5.3
 265 */
 266 g_object_class_install_property(objectClass, PROP_Y,
 267 g_param_spec_int("y",
 268 _("Y coordinate"),
 269 _("The y coordintate of the event relative to the view's window."),
 270 G_MININT, G_MAXINT, 0,
 271 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
 272
228273 g_type_class_add_private(webHitTestResultClass, sizeof(WebKitHitTestResultPrivate));
229274}
230275

@@WebKitHitTestResult* kit(const WebCore::HitTestResult& result)
243288 GOwnPtr<char> imageURI(0);
244289 GOwnPtr<char> mediaURI(0);
245290 WebKitDOMNode* node = 0;
 291 WebCore::Frame* targetFrame;
 292 WebCore::IntPoint point;
246293
247294 if (!result.absoluteLinkURL().isEmpty()) {
248295 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;

@@WebKitHitTestResult* kit(const WebCore::HitTestResult& result)
268315 if (result.innerNonSharedNode())
269316 node = kit(result.innerNonSharedNode());
270317
 318 targetFrame = result.targetFrame();
 319 if (targetFrame && targetFrame->view()) {
 320 // Convert document coords to widget coords.
 321 point = targetFrame->view()->contentsToWindow(result.point());
 322 } else
 323 point = result.point();
 324
271325 return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT,
272326 "link-uri", linkURI.get(),
273327 "image-uri", imageURI.get(),
274328 "media-uri", mediaURI.get(),
275329 "context", context,
276330 "inner-node", node,
 331 "x", point.x(),
 332 "y", point.y(),
277333 NULL));
278334}
279335

Source/WebKit/gtk/webkit/webkitwebsettings.cpp

@@static void webkit_web_settings_class_init(WebKitWebSettingsClass* klass)
761761 * right-clicks that are handled by the page itself.
762762 *
763763 * Since: 1.1.18
 764 *
 765 * Deprecated: 1.5.3: Use #WebKitWebView::context-menu signal instead.
764766 */
765767 g_object_class_install_property(gobject_class,
766768 PROP_ENABLE_DEFAULT_CONTEXT_MENU,

Source/WebKit/gtk/webkit/webkitwebview.cpp

@@enum {
204204 EDITING_ENDED,
205205 VIEWPORT_ATTRIBUTES_RECOMPUTE_REQUESTED,
206206 VIEWPORT_ATTRIBUTES_CHANGED,
 207 CONTEXT_MENU,
207208
208209 LAST_SIGNAL
209210};

@@static void contextMenuConnectActivate(GtkMenuItem* item, ContextMenuController*
308309 g_signal_connect(item, "activate", G_CALLBACK(contextMenuItemActivated), controller);
309310}
310311
311 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
 312static MouseEventWithHitTestResults prepareMouseEventForFrame(Frame* frame, const PlatformMouseEvent& event)
 313{
 314 HitTestRequest request(HitTestRequest::Active);
 315 IntPoint point = frame->view()->windowToContents(event.pos());
 316 return frame->document()->prepareMouseEvent(request, point, event);
 317}
 318
 319// Check enable-default-context-menu setting for compatibility.
 320static bool defaultContextMenuEnabled(WebKitWebView* webView)
 321{
 322 gboolean enableDefaultContextMenu;
 323 g_object_get(webkit_web_view_get_settings(webView), "enable-default-context-menu", &enableDefaultContextMenu, NULL);
 324 return enableDefaultContextMenu;
 325}
 326
 327static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event, bool triggeredWithKeyboard)
312328{
313329 Page* page = core(webView);
314330 page->contextMenuController()->clearContextMenu();
315331 Frame* focusedFrame;
316332 Frame* mainFrame = page->mainFrame();
317333 gboolean mousePressEventResult = FALSE;
 334 GRefPtr<WebKitHitTestResult> hitTestResult;
318335
319336 if (!mainFrame->view())
320337 return FALSE;
321338
322339 mainFrame->view()->setCursor(pointerCursor());
323340 if (page->frameCount()) {
324  HitTestRequest request(HitTestRequest::Active);
325  IntPoint point = mainFrame->view()->windowToContents(event.pos());
326  MouseEventWithHitTestResults mev = mainFrame->document()->prepareMouseEvent(request, point, event);
327 
 341 MouseEventWithHitTestResults mev = prepareMouseEventForFrame(mainFrame, event);
328342 Frame* targetFrame = EventHandler::subframeForHitTestResult(mev);
329343 if (!targetFrame)
330344 targetFrame = mainFrame;

@@static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webVie
334348 page->focusController()->setFocusedFrame(targetFrame);
335349 focusedFrame = targetFrame;
336350 }
 351 if (focusedFrame == mainFrame)
 352 hitTestResult = adoptGRef(kit(mev.hitTestResult()));
337353 } else
338354 focusedFrame = mainFrame;
339355
340356 if (focusedFrame->view() && focusedFrame->eventHandler()->handleMousePressEvent(event))
341357 mousePressEventResult = TRUE;
342358
343 
344359 bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
345360 if (!handledEvent)
346361 return FALSE;

@@static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webVie
353368 if (!coreMenu)
354369 return mousePressEventResult;
355370
356  // If we reach here, it's because WebCore is going to show the
357  // default context menu. We check our setting to figure out
358  // whether we want it or not.
359  WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
360  gboolean enableDefaultContextMenu;
361  g_object_get(settings, "enable-default-context-menu", &enableDefaultContextMenu, NULL);
362 
363  if (!enableDefaultContextMenu)
364  return FALSE;
365 
366  GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
367  if (!menu)
368  return FALSE;
 371 GtkMenu* defaultMenu = coreMenu->platformDescription();
 372 ASSERT(defaultMenu);
369373
370374 // We connect the "activate" signal here rather than in ContextMenuGtk to avoid
371375 // a layering violation. ContextMenuGtk should not know about the ContextMenuController.
372  gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)contextMenuConnectActivate, controller);
 376 gtk_container_foreach(GTK_CONTAINER(defaultMenu), (GtkCallback)contextMenuConnectActivate, controller);
373377
374  g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
 378 if (!hitTestResult) {
 379 MouseEventWithHitTestResults mev = prepareMouseEventForFrame(focusedFrame, event);
 380 hitTestResult = adoptGRef(kit(mev.hitTestResult()));
 381 }
 382
 383 gboolean handled;
 384 g_signal_emit(webView, webkit_web_view_signals[CONTEXT_MENU], 0, defaultMenu, hitTestResult.get(), triggeredWithKeyboard, &handled);
 385 if (handled)
 386 return TRUE;
 387
 388 // Return now if default context menu is disabled by enable-default-context-menu setting.
 389 // Check enable-default-context-menu setting for compatibility.
 390 if (!defaultContextMenuEnabled(webView))
 391 return FALSE;
 392
 393 // Emit populate-popup signal for compatibility.
 394 g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, defaultMenu);
375395
376396 // If the context menu is now empty, don't show it.
377  GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
 397 GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(defaultMenu)));
378398 if (!items)
379399 return FALSE;
380400
381401 WebKitWebViewPrivate* priv = webView->priv;
382  priv->currentMenu = menu;
 402 priv->currentMenu = defaultMenu;
383403 priv->lastPopupXPosition = event.globalX();
384404 priv->lastPopupYPosition = event.globalY();
385405
386  gtk_menu_popup(menu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
 406 gtk_menu_popup(defaultMenu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
387407 return TRUE;
388408}
389409

@@static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
424444
425445 IntPoint globalPoint(convertWidgetPointToScreenPoint(widget, location));
426446 PlatformMouseEvent event(location, globalPoint, RightButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
427  return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
 447 return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event, true);
428448}
429449
430450#ifndef GTK_API_VERSION_2

@@static gboolean webkit_web_view_button_press_event(GtkWidget* widget, GdkEventBu
782802 platformEvent.setClickCount(priv->clickCounter.clickCountForGdkButtonEvent(widget, event));
783803
784804 if (event->button == 3)
785  return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
 805 return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event), false);
786806
787807 Frame* frame = core(webView)->mainFrame();
788808 if (!frame->view())

@@static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
21662186 * When a context menu is about to be displayed this signal is emitted.
21672187 *
21682188 * Add menu items to #menu to extend the context menu.
 2189 *
 2190 * Deprecated: 1.5.3: Use #WebKitWebView::context-menu signal instead.
21692191 */
21702192 webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
21712193 G_TYPE_FROM_CLASS(webViewClass),

@@static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
27452767 WEBKIT_TYPE_VIEWPORT_ATTRIBUTES);
27462768
27472769 /*
 2770 * WebKitWebView::context-menu
 2771 * @webView: the object which received the signal
 2772 * @default_menu: the default context menu
 2773 * @hit_test_result: a #WebKitHitTestResult with the context of the current position.
 2774 * @keyboard_mode: %TRUE if the context menu was triggered using the keyboard
 2775 *
 2776 * Emmited when a context menu is about to be displayed to give the application
 2777 * a chance to create and handle its own context menu. If you only want to add custom
 2778 * options to the default context menu you can simply modify the given @default_menu.
 2779 *
 2780 * When keyboard_mode is %TRUE the coordinates of the given @hit_test_result should be
 2781 * used to position the popup menu. When the context menu has been triggered by a
 2782 * mouse event you could either use the @hit_test_result coordinates or pass %NULL
 2783 * to the #GtkMenuPositionFunc parameter of gtk_menu_popup() function.
 2784 * Note that coordinates of @hit_test_result are relative to @webView window.
 2785 *
 2786 * If your application will create and display its own popup menu, %TRUE should be returned.
 2787 * Note that when the context menu is handled by the application, the "enable-default-context-menu"
 2788 * setting will be ignored and the #WebKitWebView::populate-popup signal won't be emitted.
 2789 * If you don't want any context menu to be shown, you can simply connect to this signal
 2790 * and return %TRUE without doing anything else.
 2791 *
 2792 * Since: 1.5.3
 2793 */
 2794 webkit_web_view_signals[CONTEXT_MENU] = g_signal_new("context-menu",
 2795 G_TYPE_FROM_CLASS(webViewClass),
 2796 (GSignalFlags)G_SIGNAL_RUN_LAST,
 2797 0,
 2798 0, 0,
 2799 webkit_marshal_BOOLEAN__OBJECT_OBJECT_BOOLEAN,
 2800 G_TYPE_BOOLEAN, 3,
 2801 GTK_TYPE_WIDGET,
 2802 WEBKIT_TYPE_HIT_TEST_RESULT,
 2803 G_TYPE_BOOLEAN);
 2804
 2805 /*
27482806 * implementations of virtual methods
27492807 */
27502808 webViewClass->create_web_view = webkit_web_view_real_create_web_view;

Source/WebKit/gtk/webkitmarshal.list

@@BOOLEAN:ENUM,INT
22BOOLEAN:INT,INT,STRING
33BOOLEAN:OBJECT
44BOOLEAN:OBJECT,OBJECT
 5BOOLEAN:OBJECT,OBJECT,BOOLEAN
56BOOLEAN:OBJECT,OBJECT,ENUM
67BOOLEAN:OBJECT,OBJECT,ENUM,BOOLEAN
78BOOLEAN:OBJECT,OBJECT,OBJECT,OBJECT