Changeset 111843 in webkit


Ignore:
Timestamp:
Mar 23, 2012 2:29:03 AM (12 years ago)
Author:
Carlos Garcia Campos
Message:

[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:
Location:
trunk/Source/WebKit/gtk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/gtk/ChangeLog

    r111838 r111843  
     12012-03-23  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 Gustavo Noronha Silva.
     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
    1322012-03-23  Carlos Garcia Campos  <cgarcia@igalia.com>
    233
  • trunk/Source/WebKit/gtk/tests/testhittestresult.c

    r98239 r111843  
    8484        GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
    8585        WebKitDOMNode* node;
     86        gint x, y;
    8687
    8788        /* Close enough to 0,0 */
     
    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
  • trunk/Source/WebKit/gtk/webkit/webkithittestresult.cpp

    r111696 r111843  
    2222#include "webkithittestresult.h"
    2323
     24#include "Frame.h"
     25#include "FrameView.h"
    2426#include "HitTestResult.h"
    2527#include "KURL.h"
     
    5052    char* mediaURI;
    5153    GRefPtr<WebKitDOMNode> innerNode;
     54    WebCore::IntPoint position;
    5255};
    5356
     
    5962    PROP_IMAGE_URI,
    6063    PROP_MEDIA_URI,
    61     PROP_INNER_NODE
     64    PROP_INNER_NODE,
     65    PROP_X,
     66    PROP_Y
    6267};
    6368
     
    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);
     
    130141    case PROP_INNER_NODE:
    131142        priv->innerNode = static_cast<WebKitDOMNode*>(g_value_get_object(value));
     143        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));
    132149        break;
    133150    default:
     
    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.10
     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.10
     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}
     
    244289    GOwnPtr<char> mediaURI(0);
    245290    WebKitDOMNode* node = 0;
     291    WebCore::Frame* targetFrame;
     292    WebCore::IntPoint point;
    246293
    247294    if (!result.absoluteLinkURL().isEmpty()) {
     
    268315    if (result.innerNonSharedNode())
    269316        node = kit(result.innerNonSharedNode());
     317
     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();
    270324
    271325    return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT,
     
    275329                                               "context", context,
    276330                                               "inner-node", node,
     331                                               "x", point.x(),
     332                                               "y", point.y(),
    277333                                               NULL));
    278334}
  • trunk/Source/WebKit/gtk/webkit/webkitwebsettings.cpp

    r111696 r111843  
    755755     *
    756756     * Since: 1.1.18
     757     *
     758     * Deprecated: 1.10: Use #WebKitWebView::context-menu signal instead.
    757759     */
    758760    g_object_class_install_property(gobject_class,
  • trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp

    r111707 r111843  
    220220    ENTERING_FULLSCREEN,
    221221    LEAVING_FULLSCREEN,
     222    CONTEXT_MENU,
    222223
    223224    LAST_SIGNAL
     
    324325}
    325326
    326 static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
     327static MouseEventWithHitTestResults prepareMouseEventForFrame(Frame* frame, const PlatformMouseEvent& event)
     328{
     329    HitTestRequest request(HitTestRequest::Active);
     330    IntPoint point = frame->view()->windowToContents(event.position());
     331    return frame->document()->prepareMouseEvent(request, point, event);
     332}
     333
     334// Check enable-default-context-menu setting for compatibility.
     335static bool defaultContextMenuEnabled(WebKitWebView* webView)
     336{
     337    gboolean enableDefaultContextMenu;
     338    g_object_get(webkit_web_view_get_settings(webView), "enable-default-context-menu", &enableDefaultContextMenu, NULL);
     339    return enableDefaultContextMenu;
     340}
     341
     342static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event, bool triggeredWithKeyboard)
    327343{
    328344    Page* page = core(webView);
     
    331347    Frame* mainFrame = page->mainFrame();
    332348    gboolean mousePressEventResult = FALSE;
     349    GRefPtr<WebKitHitTestResult> hitTestResult;
    333350
    334351    if (!mainFrame->view())
     
    337354    mainFrame->view()->setCursor(pointerCursor());
    338355    if (page->frameCount()) {
    339         HitTestRequest request(HitTestRequest::Active);
    340         IntPoint point = mainFrame->view()->windowToContents(event.position());
    341         MouseEventWithHitTestResults mev = mainFrame->document()->prepareMouseEvent(request, point, event);
    342 
     356        MouseEventWithHitTestResults mev = prepareMouseEventForFrame(mainFrame, event);
    343357        Frame* targetFrame = EventHandler::subframeForHitTestResult(mev);
    344358        if (!targetFrame)
     
    350364            focusedFrame = targetFrame;
    351365        }
     366        if (focusedFrame == mainFrame)
     367            hitTestResult = adoptGRef(kit(mev.hitTestResult()));
    352368    } else
    353369        focusedFrame = mainFrame;
     
    355371    if (focusedFrame->view() && focusedFrame->eventHandler()->handleMousePressEvent(event))
    356372        mousePressEventResult = TRUE;
    357 
    358373
    359374    bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
     
    369384        return mousePressEventResult;
    370385
    371     // If we reach here, it's because WebCore is going to show the
    372     // default context menu. We check our setting to figure out
    373     // whether we want it or not.
    374     WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
    375     gboolean enableDefaultContextMenu;
    376     g_object_get(settings, "enable-default-context-menu", &enableDefaultContextMenu, NULL);
    377 
    378     if (!enableDefaultContextMenu)
    379         return FALSE;
    380 
    381     GtkMenu* menu = GTK_MENU(coreMenu->platformDescription());
    382     if (!menu)
    383         return FALSE;
     386    GtkMenu* defaultMenu = coreMenu->platformDescription();
     387    ASSERT(defaultMenu);
    384388
    385389    // We connect the "activate" signal here rather than in ContextMenuGtk to avoid
    386390    // a layering violation. ContextMenuGtk should not know about the ContextMenuController.
    387     gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)contextMenuConnectActivate, controller);
    388 
    389     g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, menu);
     391    gtk_container_foreach(GTK_CONTAINER(defaultMenu), reinterpret_cast<GtkCallback>(contextMenuConnectActivate), controller);
     392
     393    if (!hitTestResult) {
     394        MouseEventWithHitTestResults mev = prepareMouseEventForFrame(focusedFrame, event);
     395        hitTestResult = adoptGRef(kit(mev.hitTestResult()));
     396    }
     397
     398    gboolean handled;
     399    g_signal_emit(webView, webkit_web_view_signals[CONTEXT_MENU], 0, defaultMenu, hitTestResult.get(), triggeredWithKeyboard, &handled);
     400    if (handled)
     401        return TRUE;
     402
     403    // Return now if default context menu is disabled by enable-default-context-menu setting.
     404    // Check enable-default-context-menu setting for compatibility.
     405    if (!defaultContextMenuEnabled(webView))
     406        return FALSE;
     407
     408    // Emit populate-popup signal for compatibility.
     409    g_signal_emit(webView, webkit_web_view_signals[POPULATE_POPUP], 0, defaultMenu);
    390410
    391411    // If the context menu is now empty, don't show it.
    392     GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
     412    GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(defaultMenu)));
    393413    if (!items)
    394414        return FALSE;
    395415
    396416    WebKitWebViewPrivate* priv = webView->priv;
    397     priv->currentMenu = menu;
     417    priv->currentMenu = defaultMenu;
    398418    priv->lastPopupXPosition = event.globalPosition().x();
    399419    priv->lastPopupYPosition = event.globalPosition().y();
    400420
    401     gtk_menu_popup(menu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
     421    gtk_menu_popup(defaultMenu, 0, 0, &PopupMenuPositionFunc, webView, event.button() + 1, gtk_get_current_event_time());
    402422    return TRUE;
    403423}
     
    440460    IntPoint globalPoint(convertWidgetPointToScreenPoint(widget, location));
    441461    PlatformMouseEvent event(location, globalPoint, RightButton, PlatformEvent::MousePressed, 0, false, false, false, false, gtk_get_current_event_time());
    442     return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
     462    return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event, true);
    443463}
    444464
     
    741761
    742762    if (event->button == 3)
    743         return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event));
     763        return webkit_web_view_forward_context_menu_event(webView, PlatformMouseEvent(event), false);
    744764
    745765    Frame* frame = core(webView)->mainFrame();
     
    21062126     *
    21072127     * Add menu items to #menu to extend the context menu.
     2128     *
     2129     * Deprecated: 1.10: Use #WebKitWebView::context-menu signal instead.
    21082130     */
    21092131    webkit_web_view_signals[POPULATE_POPUP] = g_signal_new("populate-popup",
     
    28252847            WEBKIT_TYPE_WEB_RESOURCE,
    28262848            G_TYPE_POINTER);
     2849
     2850    /**
     2851     * WebKitWebView::context-menu:
     2852     * @web_view: the object which received the signal
     2853     * @default_menu: the default context menu
     2854     * @hit_test_result: a #WebKitHitTestResult with the context of the current position.
     2855     * @keyboard_mode: %TRUE if the context menu was triggered using the keyboard
     2856     *
     2857     * Emmited when a context menu is about to be displayed to give the application
     2858     * a chance to create and handle its own context menu. If you only want to add custom
     2859     * options to the default context menu you can simply modify the given @default_menu.
     2860     *
     2861     * When @keyboard_mode is %TRUE the coordinates of the given @hit_test_result should be
     2862     * used to position the popup menu. When the context menu has been triggered by a
     2863     * mouse event you could either use the @hit_test_result coordinates or pass %NULL
     2864     * to the #GtkMenuPositionFunc parameter of gtk_menu_popup() function.
     2865     * Note that coordinates of @hit_test_result are relative to @web_view window.
     2866     *
     2867     * If your application will create and display its own popup menu, %TRUE should be returned.
     2868     * Note that when the context menu is handled by the application, the #WebKitWebSettings:enable-default-context-menu
     2869     * setting will be ignored and the #WebKitWebView::populate-popup signal won't be emitted.
     2870     * If you don't want any context menu to be shown, you can simply connect to this signal
     2871     * and return %TRUE without doing anything else.
     2872     *
     2873     * Since: 1.10
     2874     */
     2875    webkit_web_view_signals[CONTEXT_MENU] = g_signal_new("context-menu",
     2876            G_TYPE_FROM_CLASS(webViewClass),
     2877            G_SIGNAL_RUN_LAST,
     2878            0, 0, 0,
     2879            webkit_marshal_BOOLEAN__OBJECT_OBJECT_BOOLEAN,
     2880            G_TYPE_BOOLEAN, 3,
     2881            GTK_TYPE_WIDGET,
     2882            WEBKIT_TYPE_HIT_TEST_RESULT,
     2883            G_TYPE_BOOLEAN);
    28272884
    28282885    /*
  • trunk/Source/WebKit/gtk/webkitmarshal.list

    r106445 r111843  
    33BOOLEAN:OBJECT
    44BOOLEAN:OBJECT,OBJECT
     5BOOLEAN:OBJECT,OBJECT,BOOLEAN
    56BOOLEAN:OBJECT,OBJECT,ENUM
    67BOOLEAN:OBJECT,OBJECT,ENUM,BOOLEAN
Note: See TracChangeset for help on using the changeset viewer.