Diff
Modified: trunk/Source/WebKit/gtk/ChangeLog (111842 => 111843)
--- trunk/Source/WebKit/gtk/ChangeLog 2012-03-23 09:26:47 UTC (rev 111842)
+++ trunk/Source/WebKit/gtk/ChangeLog 2012-03-23 09:29:03 UTC (rev 111843)
@@ -1,5 +1,36 @@
2012-03-23 Carlos Garcia Campos <cgar...@igalia.com>
+ [GTK] Add a signal to allow applications to handle its own context menu
+ https://bugs.webkit.org/show_bug.cgi?id=49904
+
+ Reviewed by Gustavo Noronha Silva.
+
+ * tests/testhittestresult.c:
+ (load_status_cb): Test x, y properties of WebKitHitTestResult.
+ * webkit/webkithittestresult.cpp:
+ (webkit_hit_test_result_get_property):
+ (webkit_hit_test_result_set_property):
+ (webkit_hit_test_result_class_init): Add x and y construct only
+ properties to keep the coordinates of the event relative to view's
+ widget.
+ (WebKit::kit):
+ * webkit/webkitwebsettings.cpp:
+ (webkit_web_settings_class_init): Mark enable-default-context-menu
+ property as deprecated.
+ * webkit/webkitwebview.cpp:
+ (prepareMouseEventForFrame):
+ (defaultContextMenuEnabled): Helper function to check whether
+ default context menu setting is enabled or not.
+ (webkit_web_view_forward_context_menu_event): Emit the new
+ context-menu signal.
+ (webkit_web_view_popup_menu_handler):
+ (webkit_web_view_button_press_event):
+ (webkit_web_view_class_init): Add new context-menu signal and mark
+ populate-popup as deprecated.
+ * webkitmarshal.list:
+
+2012-03-23 Carlos Garcia Campos <cgar...@igalia.com>
+
Unreviewed. Fix GTK+ build after r111707.
* WebCoreSupport/UserMediaClientGtk.h:
Modified: trunk/Source/WebKit/gtk/tests/testhittestresult.c (111842 => 111843)
--- trunk/Source/WebKit/gtk/tests/testhittestresult.c 2012-03-23 09:26:47 UTC (rev 111842)
+++ trunk/Source/WebKit/gtk/tests/testhittestresult.c 2012-03-23 09:29:03 UTC (rev 111843)
@@ -83,6 +83,7 @@
guint context;
GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
WebKitDOMNode* node;
+ gint x, y;
/* Close enough to 0,0 */
event->button.x = 5;
@@ -98,6 +99,11 @@
g_object_get(result, "inner-node", &node, NULL);
g_assert(node);
g_assert(WEBKIT_DOM_IS_NODE(node));
+
+ g_object_get(result, "x", &x, "y", &y, NULL);
+ g_assert_cmpint(x, ==, 5);
+ g_assert_cmpint(y, ==, 5);
+
/* We can only test these node types at the moment. In the
* input case there seems to be an extra layer with a DIV on
* top of the input, which gets assigned to the inner-node.
Modified: trunk/Source/WebKit/gtk/webkit/webkithittestresult.cpp (111842 => 111843)
--- trunk/Source/WebKit/gtk/webkit/webkithittestresult.cpp 2012-03-23 09:26:47 UTC (rev 111842)
+++ trunk/Source/WebKit/gtk/webkit/webkithittestresult.cpp 2012-03-23 09:29:03 UTC (rev 111843)
@@ -21,6 +21,8 @@
#include "config.h"
#include "webkithittestresult.h"
+#include "Frame.h"
+#include "FrameView.h"
#include "HitTestResult.h"
#include "KURL.h"
#include "WebKitDOMBinding.h"
@@ -49,6 +51,7 @@
char* imageURI;
char* mediaURI;
GRefPtr<WebKitDOMNode> innerNode;
+ WebCore::IntPoint position;
};
enum {
@@ -58,7 +61,9 @@
PROP_LINK_URI,
PROP_IMAGE_URI,
PROP_MEDIA_URI,
- PROP_INNER_NODE
+ PROP_INNER_NODE,
+ PROP_X,
+ PROP_Y
};
static void webkit_hit_test_result_finalize(GObject* object)
@@ -101,6 +106,12 @@
case PROP_INNER_NODE:
g_value_set_object(value, priv->innerNode.get());
break;
+ case PROP_X:
+ g_value_set_int(value, priv->position.x());
+ break;
+ case PROP_Y:
+ g_value_set_int(value, priv->position.y());
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
}
@@ -130,6 +141,12 @@
case PROP_INNER_NODE:
priv->innerNode = static_cast<WebKitDOMNode*>(g_value_get_object(value));
break;
+ case PROP_X:
+ priv->position.setX(g_value_get_int(value));
+ break;
+ case PROP_Y:
+ priv->position.setY(g_value_get_int(value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
}
@@ -225,6 +242,34 @@
WEBKIT_TYPE_DOM_NODE,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+ /**
+ * WebKitHitTestResult:x:
+ *
+ * The x coordintate of the event relative to the view's window.
+ *
+ * Since: 1.10
+ */
+ g_object_class_install_property(objectClass, PROP_X,
+ g_param_spec_int("x",
+ _("X coordinate"),
+ _("The x coordintate of the event relative to the view's window."),
+ G_MININT, G_MAXINT, 0,
+ static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+
+ /**
+ * WebKitHitTestResult:y:
+ *
+ * The x coordintate of the event relative to the view's window.
+ *
+ * Since: 1.10
+ */
+ g_object_class_install_property(objectClass, PROP_Y,
+ g_param_spec_int("y",
+ _("Y coordinate"),
+ _("The y coordintate of the event relative to the view's window."),
+ G_MININT, G_MAXINT, 0,
+ static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+
g_type_class_add_private(webHitTestResultClass, sizeof(WebKitHitTestResultPrivate));
}
@@ -243,6 +288,8 @@
GOwnPtr<char> imageURI(0);
GOwnPtr<char> mediaURI(0);
WebKitDOMNode* node = 0;
+ WebCore::Frame* targetFrame;
+ WebCore::IntPoint point;
if (!result.absoluteLinkURL().isEmpty()) {
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;
@@ -268,12 +315,21 @@
if (result.innerNonSharedNode())
node = kit(result.innerNonSharedNode());
+ targetFrame = result.targetFrame();
+ if (targetFrame && targetFrame->view()) {
+ // Convert document coords to widget coords.
+ point = targetFrame->view()->contentsToWindow(result.point());
+ } else
+ point = result.point();
+
return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT,
"link-uri", linkURI.get(),
"image-uri", imageURI.get(),
"media-uri", mediaURI.get(),
"context", context,
"inner-node", node,
+ "x", point.x(),
+ "y", point.y(),
NULL));
}
Modified: trunk/Source/WebKit/gtk/webkit/webkitwebsettings.cpp (111842 => 111843)
--- trunk/Source/WebKit/gtk/webkit/webkitwebsettings.cpp 2012-03-23 09:26:47 UTC (rev 111842)
+++ trunk/Source/WebKit/gtk/webkit/webkitwebsettings.cpp 2012-03-23 09:29:03 UTC (rev 111843)
@@ -754,6 +754,8 @@
* right-clicks that are handled by the page itself.
*
* Since: 1.1.18
+ *
+ * Deprecated: 1.10: Use #WebKitWebView::context-menu signal instead.
*/
g_object_class_install_property(gobject_class,
PROP_ENABLE_DEFAULT_CONTEXT_MENU,
Modified: trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp (111842 => 111843)
--- trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp 2012-03-23 09:26:47 UTC (rev 111842)
+++ trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp 2012-03-23 09:29:03 UTC (rev 111843)
@@ -219,6 +219,7 @@
RESOURCE_LOAD_FAILED,
ENTERING_FULLSCREEN,
LEAVING_FULLSCREEN,
+ CONTEXT_MENU,
LAST_SIGNAL
};
@@ -323,23 +324,36 @@
g_signal_connect(item, "activate", G_CALLBACK(contextMenuItemActivated), controller);
}
-static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
+static MouseEventWithHitTestResults prepareMouseEventForFrame(Frame* frame, const PlatformMouseEvent& event)
{
+ HitTestRequest request(HitTestRequest::Active);
+ IntPoint point = frame->view()->windowToContents(event.position());
+ return frame->document()->prepareMouseEvent(request, point, event);
+}
+
+// Check enable-default-context-menu setting for compatibility.
+static bool defaultContextMenuEnabled(WebKitWebView* webView)
+{
+ gboolean enableDefaultContextMenu;
+ g_object_get(webkit_web_view_get_settings(webView), "enable-default-context-menu", &enableDefaultContextMenu, NULL);
+ return enableDefaultContextMenu;
+}
+
+static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event, bool triggeredWithKeyboard)
+{
Page* page = core(webView);
page->contextMenuController()->clearContextMenu();
Frame* focusedFrame;
Frame* mainFrame = page->mainFrame();
gboolean mousePressEventResult = FALSE;
+ GRefPtr<WebKitHitTestResult> hitTestResult;
if (!mainFrame->view())
return FALSE;
mainFrame->view()->setCursor(pointerCursor());
if (page->frameCount()) {
- HitTestRequest request(HitTestRequest::Active);
- IntPoint point = mainFrame->view()->windowToContents(event.position());
- MouseEventWithHitTestResults mev = mainFrame->document()->prepareMouseEvent(request, point, event);
-
+ MouseEventWithHitTestResults mev = prepareMouseEventForFrame(mainFrame, event);
Frame* targetFrame = EventHandler::subframeForHitTestResult(mev);
if (!targetFrame)
targetFrame = mainFrame;
@@ -349,13 +363,14 @@
page->focusController()->setFocusedFrame(targetFrame);
focusedFrame = targetFrame;
}
+ if (focusedFrame == mainFrame)
+ hitTestResult = adoptGRef(kit(mev.hitTestResult()));
} else
focusedFrame = mainFrame;
if (focusedFrame->view() && focusedFrame->eventHandler()->handleMousePressEvent(event))
mousePressEventResult = TRUE;
-
bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
if (!handledEvent)
return FALSE;
@@ -368,37 +383,42 @@
if (!coreMenu)
return mousePressEventResult;
- // If we reach here, it's because WebCore is going to show the
- // default context menu. We check our setting to figure out
- // whether we want it or not.
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- gboolean enableDefaultContextMenu;
- g_object_get(settings, "enable-default-context-menu", &enableDefaultContextMenu, NULL);
+ GtkMenu* defaultMenu = coreMenu->platformDescription();
+ ASSERT(defaultMenu);
- if (!enableDefaultContextMenu)
- return FALSE;
+ // We connect the "activate" signal here rather than in ContextMenuGtk to avoid
+ // a layering violation. ContextMenuGtk should not know about the ContextMenuController.
+ gtk_container_foreach(GTK_CONTAINER(defaultMenu), reinterpret_cast<GtkCallback>(contextMenuConnectActivate), controller);
- GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
- if (!menu)
+ if (!hitTestResult) {
+ MouseEventWithHitTestResults mev = prepareMouseEventForFrame(focusedFrame, event);
+ hitTestResult = adoptGRef(kit(mev.hitTestResult()));
+ }
+
+ gboolean handled;
+ g_signal_emit(webView, webkit_web_view_signals[CONTEXT_MENU], 0, defaultMenu, hitTestResult.get(), triggeredWithKeyboard, &handled);
+ if (handled)
+ return TRUE;
+
+ // Return now if default context menu is disabled by enable-default-context-menu setting.
+ // Check enable-default-context-menu setting for compatibility.
+ if (!defaultContextMenuEnabled(webView))
return FALSE;
- // We connect the "activate" signal here rather than in ContextMenuGtk to avoid
- // a layering violation. ContextMenuGtk should not know about the ContextMenuController.
- gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)contextMenuConnectActivate, controller);
+ // Emit populate-popup signal for compatibility.
+ g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, defaultMenu);
- g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
-
// If the context menu is now empty, don't show it.
- GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
+ GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(defaultMenu)));
if (!items)
return FALSE;
WebKitWebViewPrivate* priv = webView->priv;
- priv->currentMenu = menu;
+ priv->currentMenu = defaultMenu;
priv->lastPopupXPosition = event.globalPosition().x();
priv->lastPopupYPosition = event.globalPosition().y();
- gtk_menu_popup(menu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
+ gtk_menu_popup(defaultMenu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
return TRUE;
}
@@ -439,7 +459,7 @@
IntPoint globalPoint(convertWidgetPointToScreenPoint(widget, location));
PlatformMouseEvent event(location, globalPoint, RightButton, PlatformEvent::MousePressed, 0, false, false, false, false, gtk_get_current_event_time());
- return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
+ return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event, true);
}
static void setHorizontalAdjustment(WebKitWebView* webView, GtkAdjustment* adjustment)
@@ -740,7 +760,7 @@
platformEvent.setClickCount(count);
if (event->button == 3)
- return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
+ return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event), false);
Frame* frame = core(webView)->mainFrame();
if (!frame->view())
@@ -2105,6 +2125,8 @@
* When a context menu is about to be displayed this signal is emitted.
*
* Add menu items to #menu to extend the context menu.
+ *
+ * Deprecated: 1.10: Use #WebKitWebView::context-menu signal instead.
*/
webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
G_TYPE_FROM_CLASS(webViewClass),
@@ -2825,6 +2847,41 @@
WEBKIT_TYPE_WEB_RESOURCE,
G_TYPE_POINTER);
+ /**
+ * WebKitWebView::context-menu:
+ * @web_view: the object which received the signal
+ * @default_menu: the default context menu
+ * @hit_test_result: a #WebKitHitTestResult with the context of the current position.
+ * @keyboard_mode: %TRUE if the context menu was triggered using the keyboard
+ *
+ * Emmited when a context menu is about to be displayed to give the application
+ * a chance to create and handle its own context menu. If you only want to add custom
+ * options to the default context menu you can simply modify the given @default_menu.
+ *
+ * When @keyboard_mode is %TRUE the coordinates of the given @hit_test_result should be
+ * used to position the popup menu. When the context menu has been triggered by a
+ * mouse event you could either use the @hit_test_result coordinates or pass %NULL
+ * to the #GtkMenuPositionFunc parameter of gtk_menu_popup() function.
+ * Note that coordinates of @hit_test_result are relative to @web_view window.
+ *
+ * If your application will create and display its own popup menu, %TRUE should be returned.
+ * Note that when the context menu is handled by the application, the #WebKitWebSettings:enable-default-context-menu
+ * setting will be ignored and the #WebKitWebView::populate-popup signal won't be emitted.
+ * If you don't want any context menu to be shown, you can simply connect to this signal
+ * and return %TRUE without doing anything else.
+ *
+ * Since: 1.10
+ */
+ webkit_web_view_signals[CONTEXT_MENU] = g_signal_new("context-menu",
+ G_TYPE_FROM_CLASS(webViewClass),
+ G_SIGNAL_RUN_LAST,
+ 0, 0, 0,
+ webkit_marshal_BOOLEAN__OBJECT_OBJECT_BOOLEAN,
+ G_TYPE_BOOLEAN, 3,
+ GTK_TYPE_WIDGET,
+ WEBKIT_TYPE_HIT_TEST_RESULT,
+ G_TYPE_BOOLEAN);
+
/*
* implementations of virtual methods
*/
Modified: trunk/Source/WebKit/gtk/webkitmarshal.list (111842 => 111843)
--- trunk/Source/WebKit/gtk/webkitmarshal.list 2012-03-23 09:26:47 UTC (rev 111842)
+++ trunk/Source/WebKit/gtk/webkitmarshal.list 2012-03-23 09:29:03 UTC (rev 111843)
@@ -2,6 +2,7 @@
BOOLEAN:INT,INT,STRING
BOOLEAN:OBJECT
BOOLEAN:OBJECT,OBJECT
+BOOLEAN:OBJECT,OBJECT,BOOLEAN
BOOLEAN:OBJECT,OBJECT,ENUM
BOOLEAN:OBJECT,OBJECT,ENUM,BOOLEAN
BOOLEAN:OBJECT,OBJECT,OBJECT,OBJECT